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);