@@ -358,38 +358,40 @@ def test_remove_instance_variable
358358 def test_remove_instance_variable_re_embed
359359 assert_separately ( %w[ -robjspace ] , "#{ <<~"begin;" } \n #{ <<~'end;' } " )
360360 begin;
361- c = Class.new do
362- attr_reader :a, :b, :c
361+ # Determine the RVALUE pool's embed capacity from GC constants.
362+ rvalue_size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
363+ rbasic_size = GC::INTERNAL_CONSTANTS[:RBASIC_SIZE]
364+ embed_cap = (rvalue_size - rbasic_size) / RbConfig::SIZEOF["void*"]
363365
364- def initialize
365- @a = nil
366- @b = nil
367- @c = nil
368- end
369- end
366+ # Build a class whose initialize sets embed_cap ivars so objects
367+ # are allocated in the RVALUE pool with embedded storage.
368+ init_body = embed_cap.times.map { |i| "@v#{i} = nil" }.join("; ")
369+ c = Class.new { class_eval("def initialize; #{init_body}; end") }
370370
371371 o1 = c.new
372372 o2 = c.new
373373
374- o1.instance_variable_set(:@foo, 5)
375- o1.instance_variable_set(:@a, 0)
376- o1.instance_variable_set(:@b, 1)
377- o1.instance_variable_set(:@c, 2)
374+ # All embed_cap ivars fit - should be embedded
375+ embed_cap.times { |i| o1.instance_variable_set(:"@v#{i}", i) }
376+ assert_includes ObjectSpace.dump(o1), '"embedded":true'
377+
378+ # One more ivar overflows embed capacity
379+ o1.instance_variable_set(:@overflow, 99)
378380 refute_includes ObjectSpace.dump(o1), '"embedded":true'
379- o1.remove_instance_variable(:@foo)
381+
382+ # Remove the overflow ivar - should re-embed
383+ o1.remove_instance_variable(:@overflow)
380384 assert_includes ObjectSpace.dump(o1), '"embedded":true'
381385
382- o2.instance_variable_set(:@a, 0)
383- o2.instance_variable_set(:@b, 1)
384- o2.instance_variable_set(:@c, 2)
386+ # An object that never overflowed is also embedded
387+ embed_cap.times { |i| o2.instance_variable_set(:"@v#{i}", i) }
385388 assert_includes ObjectSpace.dump(o2), '"embedded":true'
386389
387- assert_equal(0, o1.a)
388- assert_equal(1, o1.b)
389- assert_equal(2, o1.c)
390- assert_equal(0, o2.a)
391- assert_equal(1, o2.b)
392- assert_equal(2, o2.c)
390+ # Verify values survived re-embedding
391+ embed_cap.times do |i|
392+ assert_equal(i, o1.instance_variable_get(:"@v#{i}"))
393+ assert_equal(i, o2.instance_variable_get(:"@v#{i}"))
394+ end
393395 end;
394396 end
395397
0 commit comments