Fix race in artInvokeInterfaceTrampoline().
When artInvokeInterfaceTrampoline() didn't get a resolved
interface method, it was calling FindMethodFromCode<>()
where the interface method was resolved and then a virtual
method for it was looked up. It then tried to retrieve the
interface method from the DexCache where it would usualy be
found as it was just stored there by the method resolution.
However, another thread could have just evicted that entry.
Instead of adding another call to LookupResolvedMethod(),
use the fact that artInvokeInterfaceTrampoline() already
explicitly inlines all the FindMethodFromCode<>() except
for the interface method resolution, so we can simply do
the resolution and then take the existing path for the rest
of the work.
Test: m test-art-host-gtest
Test: testrunner.py --host
Bug: 30627598
Change-Id: I62ca9c4e108ab6a3ee700b55d3b19c8f0f63f1d2
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index a6c5d6c..be3e4f8 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -476,7 +476,7 @@
case kDirect:
return resolved_method;
case kVirtual: {
- mirror::Class* klass = (*this_object)->GetClass();
+ ObjPtr<mirror::Class> klass = (*this_object)->GetClass();
uint16_t vtable_index = resolved_method->GetMethodIndex();
if (access_check &&
(!klass->HasVTable() ||
@@ -509,7 +509,7 @@
// It is not an interface. If the referring class is in the class hierarchy of the
// referenced class in the bytecode, we use its super class. Otherwise, we throw
// a NoSuchMethodError.
- mirror::Class* super_class = nullptr;
+ ObjPtr<mirror::Class> super_class = nullptr;
if (method_reference_class->IsAssignableFrom(h_referring_class.Get())) {
super_class = h_referring_class->GetSuperClass();
}
@@ -554,11 +554,10 @@
case kInterface: {
uint32_t imt_index = ImTable::GetImtIndex(resolved_method);
PointerSize pointer_size = class_linker->GetImagePointerSize();
- ArtMethod* imt_method = (*this_object)->GetClass()->GetImt(pointer_size)->
- Get(imt_index, pointer_size);
+ ObjPtr<mirror::Class> klass = (*this_object)->GetClass();
+ ArtMethod* imt_method = klass->GetImt(pointer_size)->Get(imt_index, pointer_size);
if (!imt_method->IsRuntimeMethod()) {
if (kIsDebugBuild) {
- mirror::Class* klass = (*this_object)->GetClass();
ArtMethod* method = klass->FindVirtualMethodForInterface(
resolved_method, class_linker->GetImagePointerSize());
CHECK_EQ(imt_method, method) << ArtMethod::PrettyMethod(resolved_method) << " / "
@@ -568,7 +567,7 @@
}
return imt_method;
} else {
- ArtMethod* interface_method = (*this_object)->GetClass()->FindVirtualMethodForInterface(
+ ArtMethod* interface_method = klass->FindVirtualMethodForInterface(
resolved_method, class_linker->GetImagePointerSize());
if (UNLIKELY(interface_method == nullptr)) {
ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method,