diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index ad5bbe7d0c..d33dfeb80a 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -712,7 +712,7 @@ iow_internal_object_id(VALUE self) struct rof_data { VALUE refs; - VALUE internals; + VALUE values; }; static void @@ -723,11 +723,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); + } } } @@ -785,21 +789,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; } } diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb index 34d9dd76ec..781fb5b3c2 100644 --- a/test/objspace/test_objspace.rb +++ b/test/objspace/test_objspace.rb @@ -140,6 +140,18 @@ class TestObjSpace < Test::Unit::TestCase end; end + def test_reachable_objects_during_iteration + opts = %w[--disable-gem --disable=frozen-string-literal -robjspace] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + begin; + ObjectSpace.each_object{|o| + o.inspect + ObjectSpace.reachable_objects_from(Class) + } + end; + end + + def test_reachable_objects_from_root root_objects = ObjectSpace.reachable_objects_from_root