Add an ImtConflictTable to better resolve IMT conflicts.

- Attach a ImtConflictTable to conflict runtime ArtMethod.
- Initially 0, a new one will be created at the first hit of
  the conflict method.
- If the assembly code does not find a target method in the table,
  we will create a new one again, copying the data from the previous
  table and adding the new mapping.

Implemented for arm/arm64/x86/x64.

bug:27556801
bug:24769046

Change-Id: Ie74d1c77cf73d451a1142bdc5e3683f9f84bb4e7
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c1115da..99e38d9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -498,10 +498,11 @@
   object_array_string->SetComponentType(java_lang_String.Get());
   SetClassRoot(kJavaLangStringArrayClass, object_array_string.Get());
 
+  LinearAlloc* linear_alloc = runtime->GetLinearAlloc();
   // Create runtime resolution and imt conflict methods.
   runtime->SetResolutionMethod(runtime->CreateResolutionMethod());
-  runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod());
-  runtime->SetImtUnimplementedMethod(runtime->CreateImtConflictMethod());
+  runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod(linear_alloc));
+  runtime->SetImtUnimplementedMethod(runtime->CreateImtConflictMethod(linear_alloc));
 
   // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create
   // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses
@@ -5904,9 +5905,11 @@
   // Place method in imt if entry is empty, place conflict otherwise.
   if (*imt_ref == unimplemented_method) {
     *imt_ref = current_method;
-  } else if (*imt_ref != imt_conflict_method) {
+  } else if (!(*imt_ref)->IsRuntimeMethod()) {
     // If we are not a conflict and we have the same signature and name as the imt
     // entry, it must be that we overwrote a superclass vtable entry.
+    // Note that we have checked IsRuntimeMethod, as there may be multiple different
+    // conflict methods.
     MethodNameAndSignatureComparator imt_comparator(
         (*imt_ref)->GetInterfaceMethodIfProxy(image_pointer_size));
     if (imt_comparator.HasSameNameAndSignature(
@@ -5915,6 +5918,11 @@
     } else {
       *imt_ref = imt_conflict_method;
     }
+  } else {
+    // Place the default conflict method. Note that there may be an existing conflict
+    // method in the IMT, but it could be one tailored to the super class, with a
+    // specific ImtConflictTable.
+    *imt_ref = imt_conflict_method;
   }
 }
 
@@ -7654,12 +7662,12 @@
   return soa.Env()->NewGlobalRef(local_ref.get());
 }
 
-ArtMethod* ClassLinker::CreateRuntimeMethod() {
+ArtMethod* ClassLinker::CreateRuntimeMethod(LinearAlloc* linear_alloc) {
   const size_t method_alignment = ArtMethod::Alignment(image_pointer_size_);
   const size_t method_size = ArtMethod::Size(image_pointer_size_);
   LengthPrefixedArray<ArtMethod>* method_array = AllocArtMethodArray(
       Thread::Current(),
-      Runtime::Current()->GetLinearAlloc(),
+      linear_alloc,
       1);
   ArtMethod* method = &method_array->At(0, method_size, method_alignment);
   CHECK(method != nullptr);