From 1064c63643f1d70ef7253acc1022fdbf4e903b70 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Fri, 1 Aug 2025 11:22:11 +0200 Subject: [PATCH] Fix rb_shape_transition_object_id transition to TOO_COMPLEX If `get_next_shape_internal` fail to return a shape, we must transitiont to a complex shape. `shape_transition_object_id` mistakenly didn't. Co-Authored-By: Peter Zhu --- gc.c | 2 -- shape.c | 1 + test/ruby/test_shapes.rb | 8 ++++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/gc.c b/gc.c index 37822dabb7..4af43edcc4 100644 --- a/gc.c +++ b/gc.c @@ -1897,8 +1897,6 @@ object_id0(VALUE obj) return object_id_get(obj, shape_id); } - // rb_shape_object_id_shape may lock if the current shape has - // multiple children. shape_id_t object_id_shape_id = rb_shape_transition_object_id(obj); id = generate_next_object_id(); diff --git a/shape.c b/shape.c index e296ab2d8f..6e1b49352f 100644 --- a/shape.c +++ b/shape.c @@ -716,6 +716,7 @@ shape_transition_object_id(shape_id_t original_shape_id) rb_shape_t *shape = get_next_shape_internal(RSHAPE(original_shape_id), id_object_id, SHAPE_OBJ_ID, &dont_care, true); if (!shape) { shape = RSHAPE(ROOT_SHAPE_WITH_OBJ_ID); + return transition_complex(shape_id(shape, original_shape_id) | SHAPE_ID_FL_HAS_OBJECT_ID); } RUBY_ASSERT(shape); diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb index a4cf23c6d5..ed55b95c3e 100644 --- a/test/ruby/test_shapes.rb +++ b/test/ruby/test_shapes.rb @@ -655,6 +655,14 @@ class TestShapes < Test::Unit::TestCase end def test_object_id_transition_too_complex + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + obj = Object.new + obj.instance_variable_set(:@a, 1) + RubyVM::Shape.exhaust_shapes + assert_equal obj.object_id, obj.object_id + end; + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; class Hi; end