diff --git a/shape.c b/shape.c index 01ec0f0604..e264e7bee5 100644 --- a/shape.c +++ b/shape.c @@ -451,6 +451,7 @@ rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *dest_shap switch ((enum shape_type)dest_shape->type) { case SHAPE_IVAR: + case SHAPE_FROZEN: if (!next_shape->edges) { return NULL; } @@ -464,7 +465,6 @@ rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *dest_shap } break; case SHAPE_ROOT: - case SHAPE_FROZEN: case SHAPE_CAPACITY_CHANGE: case SHAPE_INITIAL_CAPACITY: case SHAPE_T_OBJECT: diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb index 72d79be037..bef2ba9605 100644 --- a/test/ruby/test_gc_compact.rb +++ b/test/ruby/test_gc_compact.rb @@ -416,4 +416,32 @@ class TestGCCompact < Test::Unit::TestCase assert_include(ObjectSpace.dump(ary[0]), '"embedded":true') end; end + + def test_moving_objects_between_size_pools_keeps_shape_frozen_status + # [Bug #19536] + assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}") + begin; + class A + def add_ivars + @a = @b = @c = @d = 1 + end + + def set_a + @a = 10 + end + end + + a = A.new + a.add_ivars + a.freeze + + b = A.new + b.add_ivars + b.set_a # Set the inline cache in set_a + + GC.verify_compaction_references(expand_heap: true, toward: :empty) + + assert_raise(FrozenError) { a.set_a } + end; + end end