diff options
-rw-r--r-- | test/ruby/test_shapes.rb | 32 | ||||
-rw-r--r-- | variable.c | 2 |
2 files changed, 32 insertions, 2 deletions
diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb index 1135daecbe..8755da9d25 100644 --- a/test/ruby/test_shapes.rb +++ b/test/ruby/test_shapes.rb @@ -318,7 +318,7 @@ class TestShapes < Test::Unit::TestCase end; end - def test_run_out_of_shape_generic_ivar_set + def test_run_out_of_shape_generic_instance_variable_set assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; class TooComplex < Hash @@ -345,6 +345,36 @@ class TestShapes < Test::Unit::TestCase end; end + def test_run_out_of_shape_generic_ivar_set + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + class Hi < String + def initialize + 8.times do |i| + instance_variable_set("@ivar_#{i}", i) + end + end + + def transition + @hi_transition ||= 1 + end + end + + a = Hi.new + + # Try to run out of shapes + o = Object.new + i = 0 + while RubyVM::Shape.shapes_available > 0 + o.instance_variable_set(:"@i#{i}", 1) + i += 1 + end + + assert_equal 1,a.transition + assert_equal 1,a.transition + end; + end + def test_run_out_of_shape_instance_variable_defined assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; diff --git a/variable.c b/variable.c index 414da14f11..d3ae9791e8 100644 --- a/variable.c +++ b/variable.c @@ -1516,7 +1516,7 @@ generic_ivar_set(VALUE obj, ID id, VALUE val) RUBY_ASSERT(index == shape->capacity); rb_shape_t *next_shape = rb_shape_transition_shape_capa(shape); - if (shape->type == SHAPE_OBJ_TOO_COMPLEX) { + if (next_shape->type == SHAPE_OBJ_TOO_COMPLEX) { rb_evict_ivars_to_hash(obj, shape); rb_complex_ivar_set(obj, id, val); FL_SET_RAW(obj, FL_EXIVAR); |