diff options
Diffstat (limited to 'ext/objspace/objspace.c')
-rw-r--r-- | ext/objspace/objspace.c | 342 |
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. |