ART: Make IndirectReferenceTable resizable

Allow backing table to be resized. This can be used for the local
reference table, where synchronization is not an issue.

Bug: 32125344
Test: m test-art-host
Change-Id: Iae3a933e330026231b17fdde44bcdd99c235dff1
diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc
index 1baec28..722b411 100644
--- a/runtime/indirect_reference_table_test.cc
+++ b/runtime/indirect_reference_table_test.cc
@@ -50,7 +50,10 @@
   ScopedObjectAccess soa(Thread::Current());
   static const size_t kTableMax = 20;
   std::string error_msg;
-  IndirectReferenceTable irt(kTableMax, kGlobal, &error_msg);
+  IndirectReferenceTable irt(kTableMax,
+                             kGlobal,
+                             IndirectReferenceTable::ResizableCapacity::kNo,
+                             &error_msg);
   ASSERT_TRUE(irt.IsValid()) << error_msg;
 
   mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
@@ -289,7 +292,10 @@
 
   // 1) Segment with holes (current_num_holes_ > 0), push new segment, add/remove reference.
   {
-    IndirectReferenceTable irt(kTableMax, kLocal, &error_msg);
+    IndirectReferenceTable irt(kTableMax,
+                               kGlobal,
+                               IndirectReferenceTable::ResizableCapacity::kNo,
+                               &error_msg);
     ASSERT_TRUE(irt.IsValid()) << error_msg;
 
     const IRTSegmentState cookie0 = kIRTFirstSegment;
@@ -317,7 +323,10 @@
 
   // 2) Segment with holes (current_num_holes_ > 0), pop segment, add/remove reference
   {
-    IndirectReferenceTable irt(kTableMax, kGlobal, &error_msg);
+    IndirectReferenceTable irt(kTableMax,
+                               kGlobal,
+                               IndirectReferenceTable::ResizableCapacity::kNo,
+                               &error_msg);
     ASSERT_TRUE(irt.IsValid()) << error_msg;
 
     const IRTSegmentState cookie0 = kIRTFirstSegment;
@@ -350,7 +359,10 @@
   // 3) Segment with holes (current_num_holes_ > 0), push new segment, pop segment, add/remove
   //    reference.
   {
-    IndirectReferenceTable irt(kTableMax, kGlobal, &error_msg);
+    IndirectReferenceTable irt(kTableMax,
+                               kGlobal,
+                               IndirectReferenceTable::ResizableCapacity::kNo,
+                               &error_msg);
     ASSERT_TRUE(irt.IsValid()) << error_msg;
 
     const IRTSegmentState cookie0 = kIRTFirstSegment;
@@ -386,7 +398,10 @@
 
   // 4) Empty segment, push new segment, create a hole, pop a segment, add/remove a reference.
   {
-    IndirectReferenceTable irt(kTableMax, kGlobal, &error_msg);
+    IndirectReferenceTable irt(kTableMax,
+                               kGlobal,
+                               IndirectReferenceTable::ResizableCapacity::kNo,
+                               &error_msg);
     ASSERT_TRUE(irt.IsValid()) << error_msg;
 
     const IRTSegmentState cookie0 = kIRTFirstSegment;
@@ -426,7 +441,10 @@
   // 5) Base segment, push new segment, create a hole, pop a segment, push new segment, add/remove
   //    reference
   {
-    IndirectReferenceTable irt(kTableMax, kGlobal, &error_msg);
+    IndirectReferenceTable irt(kTableMax,
+                               kGlobal,
+                               IndirectReferenceTable::ResizableCapacity::kNo,
+                               &error_msg);
     ASSERT_TRUE(irt.IsValid()) << error_msg;
 
     const IRTSegmentState cookie0 = kIRTFirstSegment;
@@ -461,4 +479,31 @@
   }
 }
 
+TEST_F(IndirectReferenceTableTest, Resize) {
+  ScopedObjectAccess soa(Thread::Current());
+  static const size_t kTableMax = 512;
+
+  mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
+  StackHandleScope<1> hs(soa.Self());
+  ASSERT_TRUE(c != nullptr);
+  Handle<mirror::Object> obj0 = hs.NewHandle(c->AllocObject(soa.Self()));
+  ASSERT_TRUE(obj0.Get() != nullptr);
+
+  std::string error_msg;
+  IndirectReferenceTable irt(kTableMax,
+                             kLocal,
+                             IndirectReferenceTable::ResizableCapacity::kYes,
+                             &error_msg);
+  ASSERT_TRUE(irt.IsValid()) << error_msg;
+
+  CheckDump(&irt, 0, 0);
+  const IRTSegmentState cookie = kIRTFirstSegment;
+
+  for (size_t i = 0; i != kTableMax + 1; ++i) {
+    irt.Add(cookie, obj0.Get());
+  }
+
+  EXPECT_EQ(irt.Capacity(), kTableMax + 1);
+}
+
 }  // namespace art