summaryrefslogtreecommitdiff
path: root/ext/objspace/objspace.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/objspace/objspace.c')
-rw-r--r--ext/objspace/objspace.c342
1 files changed, 100 insertions, 242 deletions
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 3fa4fd279b..24d7bd419f 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -12,14 +12,13 @@
**********************************************************************/
-#include "gc.h"
#include "internal.h"
#include "internal/class.h"
#include "internal/compilers.h"
+#include "internal/gc.h"
#include "internal/hash.h"
#include "internal/imemo.h"
#include "internal/sanitizers.h"
-#include "node.h"
#include "ruby/io.h"
#include "ruby/re.h"
#include "ruby/st.h"
@@ -61,17 +60,10 @@ total_i(VALUE v, void *ptr)
{
struct total_data *data = (struct total_data *)ptr;
- switch (BUILTIN_TYPE(v)) {
- case T_NONE:
- case T_IMEMO:
- case T_ICLASS:
- case T_NODE:
- case T_ZOMBIE:
- return;
- default:
- if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
- data->total += rb_obj_memsize_of(v);
- }
+ if (!rb_objspace_internal_object_p(v)) {
+ if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
+ data->total += rb_obj_memsize_of(v);
+ }
}
}
@@ -147,7 +139,7 @@ memsize_of_all_m(int argc, VALUE *argv, VALUE self)
struct total_data data = {0, 0};
if (argc > 0) {
- rb_scan_args(argc, argv, "01", &data.klass);
+ rb_scan_args(argc, argv, "01", &data.klass);
}
each_object_with_flags(total_i, &data);
@@ -177,8 +169,7 @@ setup_hash(int argc, VALUE *argv)
hash = rb_hash_new();
}
else if (!RHASH_EMPTY_P(hash)) {
- /* WB: no new reference */
- st_foreach(RHASH_TBL_RAW(hash), set_zero_i, hash);
+ rb_hash_foreach(hash, set_zero_i, (st_data_t)hash);
}
return hash;
@@ -197,33 +188,33 @@ type2sym(enum ruby_value_type i)
VALUE type;
switch (i) {
#define CASE_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
- CASE_TYPE(T_NONE);
- CASE_TYPE(T_OBJECT);
- CASE_TYPE(T_CLASS);
- CASE_TYPE(T_MODULE);
- CASE_TYPE(T_FLOAT);
- CASE_TYPE(T_STRING);
- CASE_TYPE(T_REGEXP);
- CASE_TYPE(T_ARRAY);
- CASE_TYPE(T_HASH);
- CASE_TYPE(T_STRUCT);
- CASE_TYPE(T_BIGNUM);
- CASE_TYPE(T_FILE);
- CASE_TYPE(T_DATA);
- CASE_TYPE(T_MATCH);
- CASE_TYPE(T_COMPLEX);
- CASE_TYPE(T_RATIONAL);
- CASE_TYPE(T_NIL);
- CASE_TYPE(T_TRUE);
- CASE_TYPE(T_FALSE);
- CASE_TYPE(T_SYMBOL);
- CASE_TYPE(T_FIXNUM);
- CASE_TYPE(T_UNDEF);
- CASE_TYPE(T_IMEMO);
- CASE_TYPE(T_NODE);
- CASE_TYPE(T_ICLASS);
+ CASE_TYPE(T_NONE);
+ CASE_TYPE(T_OBJECT);
+ CASE_TYPE(T_CLASS);
+ CASE_TYPE(T_MODULE);
+ CASE_TYPE(T_FLOAT);
+ CASE_TYPE(T_STRING);
+ CASE_TYPE(T_REGEXP);
+ CASE_TYPE(T_ARRAY);
+ CASE_TYPE(T_HASH);
+ CASE_TYPE(T_STRUCT);
+ CASE_TYPE(T_BIGNUM);
+ CASE_TYPE(T_FILE);
+ CASE_TYPE(T_DATA);
+ CASE_TYPE(T_MATCH);
+ CASE_TYPE(T_COMPLEX);
+ CASE_TYPE(T_RATIONAL);
+ CASE_TYPE(T_NIL);
+ CASE_TYPE(T_TRUE);
+ CASE_TYPE(T_FALSE);
+ CASE_TYPE(T_SYMBOL);
+ CASE_TYPE(T_FIXNUM);
+ CASE_TYPE(T_UNDEF);
+ CASE_TYPE(T_IMEMO);
+ CASE_TYPE(T_NODE);
+ CASE_TYPE(T_ICLASS);
CASE_TYPE(T_MOVED);
- CASE_TYPE(T_ZOMBIE);
+ CASE_TYPE(T_ZOMBIE);
#undef CASE_TYPE
default: rb_bug("type2sym: unknown type (%d)", i);
}
@@ -262,17 +253,17 @@ count_objects_size(int argc, VALUE *argv, VALUE os)
VALUE hash = setup_hash(argc, argv);
for (i = 0; i <= T_MASK; i++) {
- counts[i] = 0;
+ counts[i] = 0;
}
each_object_with_flags(cos_i, &counts[0]);
for (i = 0; i <= T_MASK; i++) {
- if (counts[i]) {
- VALUE type = type2sym(i);
- total += counts[i];
- rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
- }
+ if (counts[i]) {
+ VALUE type = type2sym(i);
+ total += counts[i];
+ rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
+ }
}
rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
return hash;
@@ -344,17 +335,6 @@ count_symbols(int argc, VALUE *argv, VALUE os)
return hash;
}
-static void
-cn_i(VALUE v, void *n)
-{
- size_t *nodes = (size_t *)n;
-
- if (BUILTIN_TYPE(v) == T_NODE) {
- size_t s = nd_type((NODE *)v);
- nodes[s]++;
- }
-}
-
/*
* call-seq:
* ObjectSpace.count_nodes([result_hash]) -> hash
@@ -381,135 +361,7 @@ cn_i(VALUE v, void *n)
static VALUE
count_nodes(int argc, VALUE *argv, VALUE os)
{
- size_t nodes[NODE_LAST+1];
- enum node_type i;
- VALUE hash = setup_hash(argc, argv);
-
- for (i = 0; i <= NODE_LAST; i++) {
- nodes[i] = 0;
- }
-
- each_object_with_flags(cn_i, &nodes[0]);
-
- for (i=0; i<NODE_LAST; i++) {
- if (nodes[i] != 0) {
- VALUE node;
- switch (i) {
-#define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); goto set
- COUNT_NODE(NODE_SCOPE);
- COUNT_NODE(NODE_BLOCK);
- COUNT_NODE(NODE_IF);
- COUNT_NODE(NODE_UNLESS);
- COUNT_NODE(NODE_CASE);
- COUNT_NODE(NODE_CASE2);
- COUNT_NODE(NODE_CASE3);
- COUNT_NODE(NODE_WHEN);
- COUNT_NODE(NODE_IN);
- COUNT_NODE(NODE_WHILE);
- COUNT_NODE(NODE_UNTIL);
- COUNT_NODE(NODE_ITER);
- COUNT_NODE(NODE_FOR);
- COUNT_NODE(NODE_FOR_MASGN);
- COUNT_NODE(NODE_BREAK);
- COUNT_NODE(NODE_NEXT);
- COUNT_NODE(NODE_REDO);
- COUNT_NODE(NODE_RETRY);
- COUNT_NODE(NODE_BEGIN);
- COUNT_NODE(NODE_RESCUE);
- COUNT_NODE(NODE_RESBODY);
- COUNT_NODE(NODE_ENSURE);
- COUNT_NODE(NODE_AND);
- COUNT_NODE(NODE_OR);
- COUNT_NODE(NODE_MASGN);
- COUNT_NODE(NODE_LASGN);
- COUNT_NODE(NODE_DASGN);
- COUNT_NODE(NODE_DASGN_CURR);
- COUNT_NODE(NODE_GASGN);
- COUNT_NODE(NODE_IASGN);
- COUNT_NODE(NODE_CDECL);
- COUNT_NODE(NODE_CVASGN);
- COUNT_NODE(NODE_OP_ASGN1);
- COUNT_NODE(NODE_OP_ASGN2);
- COUNT_NODE(NODE_OP_ASGN_AND);
- COUNT_NODE(NODE_OP_ASGN_OR);
- COUNT_NODE(NODE_OP_CDECL);
- COUNT_NODE(NODE_CALL);
- COUNT_NODE(NODE_OPCALL);
- COUNT_NODE(NODE_FCALL);
- COUNT_NODE(NODE_VCALL);
- COUNT_NODE(NODE_QCALL);
- COUNT_NODE(NODE_SUPER);
- COUNT_NODE(NODE_ZSUPER);
- COUNT_NODE(NODE_LIST);
- COUNT_NODE(NODE_ZLIST);
- COUNT_NODE(NODE_VALUES);
- COUNT_NODE(NODE_HASH);
- COUNT_NODE(NODE_RETURN);
- COUNT_NODE(NODE_YIELD);
- COUNT_NODE(NODE_LVAR);
- COUNT_NODE(NODE_DVAR);
- COUNT_NODE(NODE_GVAR);
- COUNT_NODE(NODE_IVAR);
- COUNT_NODE(NODE_CONST);
- COUNT_NODE(NODE_CVAR);
- COUNT_NODE(NODE_NTH_REF);
- COUNT_NODE(NODE_BACK_REF);
- COUNT_NODE(NODE_MATCH);
- COUNT_NODE(NODE_MATCH2);
- COUNT_NODE(NODE_MATCH3);
- COUNT_NODE(NODE_LIT);
- COUNT_NODE(NODE_STR);
- COUNT_NODE(NODE_DSTR);
- COUNT_NODE(NODE_XSTR);
- COUNT_NODE(NODE_DXSTR);
- COUNT_NODE(NODE_EVSTR);
- COUNT_NODE(NODE_DREGX);
- COUNT_NODE(NODE_ONCE);
- COUNT_NODE(NODE_ARGS);
- COUNT_NODE(NODE_ARGS_AUX);
- COUNT_NODE(NODE_OPT_ARG);
- COUNT_NODE(NODE_KW_ARG);
- COUNT_NODE(NODE_POSTARG);
- COUNT_NODE(NODE_ARGSCAT);
- COUNT_NODE(NODE_ARGSPUSH);
- COUNT_NODE(NODE_SPLAT);
- COUNT_NODE(NODE_BLOCK_PASS);
- COUNT_NODE(NODE_DEFN);
- COUNT_NODE(NODE_DEFS);
- COUNT_NODE(NODE_ALIAS);
- COUNT_NODE(NODE_VALIAS);
- COUNT_NODE(NODE_UNDEF);
- COUNT_NODE(NODE_CLASS);
- COUNT_NODE(NODE_MODULE);
- COUNT_NODE(NODE_SCLASS);
- COUNT_NODE(NODE_COLON2);
- COUNT_NODE(NODE_COLON3);
- COUNT_NODE(NODE_DOT2);
- COUNT_NODE(NODE_DOT3);
- COUNT_NODE(NODE_FLIP2);
- COUNT_NODE(NODE_FLIP3);
- COUNT_NODE(NODE_SELF);
- COUNT_NODE(NODE_NIL);
- COUNT_NODE(NODE_TRUE);
- COUNT_NODE(NODE_FALSE);
- COUNT_NODE(NODE_ERRINFO);
- COUNT_NODE(NODE_DEFINED);
- COUNT_NODE(NODE_POSTEXE);
- COUNT_NODE(NODE_DSYM);
- COUNT_NODE(NODE_ATTRASGN);
- COUNT_NODE(NODE_LAMBDA);
- COUNT_NODE(NODE_ARYPTN);
- COUNT_NODE(NODE_FNDPTN);
- COUNT_NODE(NODE_HSHPTN);
-#undef COUNT_NODE
- case NODE_LAST: break;
- }
- UNREACHABLE;
- set:
- rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
- }
- }
- return hash;
+ return setup_hash(argc, argv);
}
static void
@@ -637,20 +489,22 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self)
VALUE hash = setup_hash(argc, argv);
if (imemo_type_ids[0] == 0) {
- imemo_type_ids[0] = rb_intern("imemo_env");
- imemo_type_ids[1] = rb_intern("imemo_cref");
- imemo_type_ids[2] = rb_intern("imemo_svar");
- imemo_type_ids[3] = rb_intern("imemo_throw_data");
- imemo_type_ids[4] = rb_intern("imemo_ifunc");
- imemo_type_ids[5] = rb_intern("imemo_memo");
- imemo_type_ids[6] = rb_intern("imemo_ment");
- imemo_type_ids[7] = rb_intern("imemo_iseq");
- imemo_type_ids[8] = rb_intern("imemo_tmpbuf");
- imemo_type_ids[9] = rb_intern("imemo_ast");
- imemo_type_ids[10] = rb_intern("imemo_parser_strterm");
- imemo_type_ids[11] = rb_intern("imemo_callinfo");
- imemo_type_ids[12] = rb_intern("imemo_callcache");
- imemo_type_ids[13] = rb_intern("imemo_constcache");
+#define INIT_IMEMO_TYPE_ID(n) (imemo_type_ids[n] = rb_intern_const(#n))
+ INIT_IMEMO_TYPE_ID(imemo_env);
+ INIT_IMEMO_TYPE_ID(imemo_cref);
+ INIT_IMEMO_TYPE_ID(imemo_svar);
+ INIT_IMEMO_TYPE_ID(imemo_throw_data);
+ INIT_IMEMO_TYPE_ID(imemo_ifunc);
+ INIT_IMEMO_TYPE_ID(imemo_memo);
+ INIT_IMEMO_TYPE_ID(imemo_ment);
+ INIT_IMEMO_TYPE_ID(imemo_iseq);
+ INIT_IMEMO_TYPE_ID(imemo_tmpbuf);
+ INIT_IMEMO_TYPE_ID(imemo_ast);
+ INIT_IMEMO_TYPE_ID(imemo_parser_strterm);
+ INIT_IMEMO_TYPE_ID(imemo_callinfo);
+ INIT_IMEMO_TYPE_ID(imemo_callcache);
+ INIT_IMEMO_TYPE_ID(imemo_constcache);
+#undef INIT_IMEMO_TYPE_ID
}
each_object_with_flags(count_imemo_objects_i, (void *)hash);
@@ -713,7 +567,7 @@ iow_internal_object_id(VALUE self)
struct rof_data {
VALUE refs;
- VALUE internals;
+ VALUE values;
};
static void
@@ -724,11 +578,15 @@ reachable_object_from_i(VALUE obj, void *data_ptr)
VALUE val = obj;
if (rb_objspace_markable_object_p(obj)) {
- if (rb_objspace_internal_object_p(obj)) {
- val = iow_newobj(obj);
- rb_ary_push(data->internals, val);
- }
- rb_hash_aset(data->refs, key, val);
+ if (NIL_P(rb_hash_lookup(data->refs, key))) {
+ rb_hash_aset(data->refs, key, Qtrue);
+
+ if (rb_objspace_internal_object_p(obj)) {
+ val = iow_newobj(obj);
+ }
+
+ rb_ary_push(data->values, val);
+ }
}
}
@@ -765,7 +623,7 @@ collect_values(st_data_t key, st_data_t value, st_data_t data)
*
* With this method, you can find memory leaks.
*
- * This method is only expected to work except with C Ruby.
+ * This method is only expected to work with C Ruby.
*
* Example:
* ObjectSpace.reachable_objects_from(['a', 'b', 'c'])
@@ -786,21 +644,21 @@ static VALUE
reachable_objects_from(VALUE self, VALUE obj)
{
if (rb_objspace_markable_object_p(obj)) {
- struct rof_data data;
+ struct rof_data data;
- if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
- obj = (VALUE)DATA_PTR(obj);
- }
+ if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
+ obj = (VALUE)DATA_PTR(obj);
+ }
- data.refs = rb_ident_hash_new();
- data.internals = rb_ary_new();
+ data.refs = rb_obj_hide(rb_ident_hash_new());
+ data.values = rb_ary_new();
- rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
+ rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
- return rb_funcall(data.refs, rb_intern("values"), 0);
+ return data.values;
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -819,26 +677,26 @@ reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
VALUE category_objects;
if (category == data->last_category) {
- category_str = data->last_category_str;
- category_objects = data->last_category_objects;
+ category_str = data->last_category_str;
+ category_objects = data->last_category_objects;
}
else {
- data->last_category = category;
- category_str = data->last_category_str = rb_str_new2(category);
- category_objects = data->last_category_objects = rb_ident_hash_new();
- if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
- rb_bug("reachable_object_from_root_i: category should insert at once");
- }
- rb_hash_aset(data->categories, category_str, category_objects);
+ data->last_category = category;
+ category_str = data->last_category_str = rb_str_new2(category);
+ category_objects = data->last_category_objects = rb_ident_hash_new();
+ if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
+ rb_bug("reachable_object_from_root_i: category should insert at once");
+ }
+ rb_hash_aset(data->categories, category_str, category_objects);
}
if (rb_objspace_markable_object_p(obj) &&
- obj != data->categories &&
- obj != data->last_category_objects) {
- if (rb_objspace_internal_object_p(obj)) {
- obj = iow_newobj(obj);
- }
- rb_hash_aset(category_objects, obj, obj);
+ obj != data->categories &&
+ obj != data->last_category_objects) {
+ if (rb_objspace_internal_object_p(obj)) {
+ obj = iow_newobj(obj);
+ }
+ rb_hash_aset(category_objects, obj, obj);
}
}
@@ -874,14 +732,14 @@ static VALUE
wrap_klass_iow(VALUE klass)
{
if (!RTEST(klass)) {
- return Qnil;
+ return Qnil;
}
else if (RB_TYPE_P(klass, T_ICLASS) ||
CLASS_OF(klass) == Qfalse /* hidden object */) {
- return iow_newobj(klass);
+ return iow_newobj(klass);
}
else {
- return klass;
+ return klass;
}
}
@@ -900,7 +758,7 @@ objspace_internal_class_of(VALUE self, VALUE obj)
VALUE klass;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
- obj = (VALUE)DATA_PTR(obj);
+ obj = (VALUE)DATA_PTR(obj);
}
if (RB_TYPE_P(obj, T_IMEMO)) {
@@ -927,17 +785,17 @@ objspace_internal_super_of(VALUE self, VALUE obj)
VALUE super;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
- obj = (VALUE)DATA_PTR(obj);
+ obj = (VALUE)DATA_PTR(obj);
}
switch (OBJ_BUILTIN_TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_ICLASS:
- super = RCLASS_SUPER(obj);
- break;
+ super = RCLASS_SUPER(obj);
+ break;
default:
- rb_raise(rb_eArgError, "class or module is expected");
+ rb_raise(rb_eArgError, "class or module is expected");
}
return wrap_klass_iow(super);
@@ -955,7 +813,7 @@ void Init_objspace_dump(VALUE rb_mObjSpace);
*
* You need to <code>require 'objspace'</code> to use this extension module.
*
- * Generally, you *SHOULD NOT* use this library if you do not know
+ * Generally, you *SHOULD* *NOT* use this library if you do not know
* about the MRI implementation. Mainly, this library is for (memory)
* profiler developers and MRI developers who need to know about MRI
* memory usage.