From 6c4fd432d0242647149906f7433a9f5025819d07 Mon Sep 17 00:00:00 2001
From: tenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
Date: Sat, 20 Apr 2019 01:59:34 +0000
Subject: [PATCH] Try harder to make objects move

Sometimes the objects we allocated may not get compacted.  This change
is to increase the likelyhood that they will move

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67623 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
---
 test/ruby/test_gc_compact.rb | 72 +++++++++++++++++++++---------------
 1 file changed, 42 insertions(+), 30 deletions(-)

diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb
index 16c62915fd..e2199e8d0d 100644
--- a/test/ruby/test_gc_compact.rb
+++ b/test/ruby/test_gc_compact.rb
@@ -14,12 +14,16 @@ class TestGCCompact < Test::Unit::TestCase
     list.count - same_count
   end
 
-  def big_list
-    1000.times.map {
-      # try to make some empty slots by allocating an object and discarding
-      Object.new
-      Object.new
-    } # likely next to each other
+  def big_list(level = 10)
+    if level > 0
+      big_list(level - 1)
+    else
+      1000.times.map {
+        # try to make some empty slots by allocating an object and discarding
+        Object.new
+        Object.new
+      } # likely next to each other
+    end
   end
 
   # Find an object that's allocated in a slot that had a previous
@@ -37,31 +41,39 @@ class TestGCCompact < Test::Unit::TestCase
     new_object
   end
 
+  def try_to_move_objects
+    10.times do
+      list_of_objects = big_list
+
+      ids       = list_of_objects.map(&:object_id) # store id in map
+      addresses = list_of_objects.map(&self.:memory_location)
+
+      assert_equal ids, addresses
+
+      # All object ids should be equal
+      assert_equal 0, assert_object_ids(list_of_objects) # should be 0
+
+      GC.verify_compaction_references
+
+      # Some should have moved
+      id_count = assert_object_ids(list_of_objects)
+      skip "couldn't get objects to move" if id_count == 0
+      assert_operator id_count, :>, 0
+
+      new_ids = list_of_objects.map(&:object_id)
+
+      # Object ids should not change after compaction
+      assert_equal ids, new_ids
+
+      new_tenant = find_object_in_recycled_slot(addresses)
+      return [list_of_objects, addresses, new_tenant] if new_tenant
+    end
+
+    flunk "Couldn't get objects to move"
+  end
+
   def test_find_collided_object
-    list_of_objects = big_list
-
-    ids       = list_of_objects.map(&:object_id) # store id in map
-    addresses = list_of_objects.map(&self.:memory_location)
-
-    assert_equal ids, addresses
-
-    # All object ids should be equal
-    assert_equal 0, assert_object_ids(list_of_objects) # should be 0
-
-    GC.verify_compaction_references
-
-    # Some should have moved
-    id_count = assert_object_ids(list_of_objects)
-    skip "couldn't get objects to move" if id_count == 0
-    assert_operator id_count, :>, 0
-
-    new_ids = list_of_objects.map(&:object_id)
-
-    # Object ids should not change after compaction
-    assert_equal ids, new_ids
-
-    new_tenant = find_object_in_recycled_slot(addresses)
-    assert new_tenant
+    list_of_objects, addresses, new_tenant = try_to_move_objects
 
     # This is the object that used to be in new_object's position
     previous_tenant = list_of_objects[addresses.index(memory_location(new_tenant))]