diff options
| -rw-r--r-- | gc/default/default.c | 10 | ||||
| -rw-r--r-- | test/ruby/test_weakmap.rb | 23 |
2 files changed, 32 insertions, 1 deletions
diff --git a/gc/default/default.c b/gc/default/default.c index c33570f920..f6628fe9fd 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -5329,7 +5329,13 @@ rb_gc_impl_handle_weak_references_alive_p(void *objspace_ptr, VALUE obj) { rb_objspace_t *objspace = objspace_ptr; - return RVALUE_MARKED(objspace, obj); + bool marked = RVALUE_MARKED(objspace, obj); + + if (marked) { + rgengc_check_relation(objspace, obj); + } + + return marked; } static void @@ -5337,7 +5343,9 @@ gc_update_weak_references(rb_objspace_t *objspace) { VALUE *obj_ptr; rb_darray_foreach(objspace->weak_references, i, obj_ptr) { + gc_mark_set_parent(objspace, *obj_ptr); rb_gc_handle_weak_references(*obj_ptr); + gc_mark_set_parent_invalid(objspace); } size_t capa = rb_darray_capa(objspace->weak_references); diff --git a/test/ruby/test_weakmap.rb b/test/ruby/test_weakmap.rb index a2904776bc..1050c74b3d 100644 --- a/test/ruby/test_weakmap.rb +++ b/test/ruby/test_weakmap.rb @@ -265,4 +265,27 @@ class TestWeakMap < Test::Unit::TestCase 10_000.times { weakmap[Object.new] = Object.new } RUBY end + + def test_generational_gc + EnvUtil.without_gc do + wmap = ObjectSpace::WeakMap.new + + (GC::INTERNAL_CONSTANTS[:RVALUE_OLD_AGE] - 1).times { GC.start } + + retain = [] + 50.times do + k = Object.new + wmap[k] = true + retain << k + end + + GC.start # WeakMap promoted, other objects still young + + retain.clear + + GC.start(full_mark: false) + + wmap.keys.each(&:itself) # call method on keys to cause crash + end + end end |
