summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gc/default/default.c10
-rw-r--r--test/ruby/test_weakmap.rb23
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