summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h11
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc115
2 files changed, 61 insertions, 65 deletions
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index a6c5d6c7aa..be3e4f811a 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -476,7 +476,7 @@ inline ArtMethod* FindMethodFromCode(uint32_t method_idx,
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 @@ inline ArtMethod* FindMethodFromCode(uint32_t method_idx,
// 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 @@ inline ArtMethod* FindMethodFromCode(uint32_t method_idx,
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 @@ inline ArtMethod* FindMethodFromCode(uint32_t method_idx,
}
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,
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 6250d9f56c..e08319d509 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -2483,43 +2483,16 @@ extern "C" TwoWordReturn artInvokeInterfaceTrampoline(ArtMethod* interface_metho
Thread* self,
ArtMethod** sp)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<mirror::Object> this_object(raw_this_object);
ScopedQuickEntrypointChecks sqec(self);
- StackHandleScope<1> hs(self);
- Handle<mirror::Class> cls(hs.NewHandle(this_object->GetClass()));
+ StackHandleScope<2> hs(self);
+ Handle<mirror::Object> this_object = hs.NewHandle(raw_this_object);
+ Handle<mirror::Class> cls = hs.NewHandle(this_object->GetClass());
ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
ArtMethod* method = nullptr;
ImTable* imt = cls->GetImt(kRuntimePointerSize);
- if (LIKELY(interface_method != nullptr)) {
- DCHECK_NE(interface_method->GetDexMethodIndex(), DexFile::kDexNoIndex);
- // If the interface method is already resolved, look whether we have a match in the
- // ImtConflictTable.
- ArtMethod* conflict_method = imt->Get(ImTable::GetImtIndex(interface_method),
- kRuntimePointerSize);
- if (LIKELY(conflict_method->IsRuntimeMethod())) {
- ImtConflictTable* current_table = conflict_method->GetImtConflictTable(kRuntimePointerSize);
- DCHECK(current_table != nullptr);
- method = current_table->Lookup(interface_method, kRuntimePointerSize);
- } else {
- // It seems we aren't really a conflict method!
- method = cls->FindVirtualMethodForInterface(interface_method, kRuntimePointerSize);
- }
- if (method != nullptr) {
- return GetTwoWordSuccessValue(
- reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode()),
- reinterpret_cast<uintptr_t>(method));
- }
-
- // No match, use the IfTable.
- method = cls->FindVirtualMethodForInterface(interface_method, kRuntimePointerSize);
- if (UNLIKELY(method == nullptr)) {
- ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(
- interface_method, this_object, caller_method);
- return GetTwoWordFailureValue(); // Failure.
- }
- } else {
+ if (UNLIKELY(interface_method == nullptr)) {
// The interface method is unresolved, so resolve it in the dex file of the caller.
// Fetch the dex_method_idx of the target interface method from the caller.
uint32_t dex_method_idx;
@@ -2538,50 +2511,74 @@ extern "C" TwoWordReturn artInvokeInterfaceTrampoline(ArtMethod* interface_metho
dex_method_idx = instr->VRegB_3rc();
}
- const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()
- ->GetDexFile();
+ const DexFile& dex_file = caller_method->GetDeclaringClass()->GetDexFile();
uint32_t shorty_len;
- const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(dex_method_idx),
- &shorty_len);
+ const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(dex_method_idx),
+ &shorty_len);
{
- // Remember the args in case a GC happens in FindMethodFromCode.
+ // Remember the args in case a GC happens in ClassLinker::ResolveMethod().
ScopedObjectAccessUnchecked soa(self->GetJniEnv());
RememberForGcArgumentVisitor visitor(sp, false, shorty, shorty_len, &soa);
visitor.VisitArguments();
- method = FindMethodFromCode<kInterface, false>(dex_method_idx,
- &this_object,
- caller_method,
- self);
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ interface_method = class_linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+ self, dex_method_idx, caller_method, kInterface);
visitor.FixupReferences();
}
- if (UNLIKELY(method == nullptr)) {
+ if (UNLIKELY(interface_method == nullptr)) {
CHECK(self->IsExceptionPending());
return GetTwoWordFailureValue(); // Failure.
}
- interface_method =
- caller_method->GetDexCacheResolvedMethod(dex_method_idx, kRuntimePointerSize);
- DCHECK(!interface_method->IsRuntimeMethod());
}
- // We arrive here if we have found an implementation, and it is not in the ImtConflictTable.
- // We create a new table with the new pair { interface_method, method }.
+ DCHECK(!interface_method->IsRuntimeMethod());
+ // Look whether we have a match in the ImtConflictTable.
uint32_t imt_index = ImTable::GetImtIndex(interface_method);
ArtMethod* conflict_method = imt->Get(imt_index, kRuntimePointerSize);
- if (conflict_method->IsRuntimeMethod()) {
- ArtMethod* new_conflict_method = Runtime::Current()->GetClassLinker()->AddMethodToConflictTable(
- cls.Get(),
- conflict_method,
- interface_method,
- method,
- /*force_new_conflict_method*/false);
- if (new_conflict_method != conflict_method) {
- // Update the IMT if we create a new conflict method. No fence needed here, as the
- // data is consistent.
- imt->Set(imt_index,
- new_conflict_method,
- kRuntimePointerSize);
+ if (LIKELY(conflict_method->IsRuntimeMethod())) {
+ ImtConflictTable* current_table = conflict_method->GetImtConflictTable(kRuntimePointerSize);
+ DCHECK(current_table != nullptr);
+ method = current_table->Lookup(interface_method, kRuntimePointerSize);
+ } else {
+ // It seems we aren't really a conflict method!
+ if (kIsDebugBuild) {
+ ArtMethod* m = cls->FindVirtualMethodForInterface(interface_method, kRuntimePointerSize);
+ CHECK_EQ(conflict_method, m)
+ << interface_method->PrettyMethod() << " / " << conflict_method->PrettyMethod() << " / "
+ << " / " << ArtMethod::PrettyMethod(m) << " / " << cls->PrettyClass();
}
+ method = conflict_method;
+ }
+ if (method != nullptr) {
+ return GetTwoWordSuccessValue(
+ reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode()),
+ reinterpret_cast<uintptr_t>(method));
+ }
+
+ // No match, use the IfTable.
+ method = cls->FindVirtualMethodForInterface(interface_method, kRuntimePointerSize);
+ if (UNLIKELY(method == nullptr)) {
+ ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(
+ interface_method, this_object.Get(), caller_method);
+ return GetTwoWordFailureValue(); // Failure.
+ }
+
+ // We arrive here if we have found an implementation, and it is not in the ImtConflictTable.
+ // We create a new table with the new pair { interface_method, method }.
+ DCHECK(conflict_method->IsRuntimeMethod());
+ ArtMethod* new_conflict_method = Runtime::Current()->GetClassLinker()->AddMethodToConflictTable(
+ cls.Get(),
+ conflict_method,
+ interface_method,
+ method,
+ /*force_new_conflict_method*/false);
+ if (new_conflict_method != conflict_method) {
+ // Update the IMT if we create a new conflict method. No fence needed here, as the
+ // data is consistent.
+ imt->Set(imt_index,
+ new_conflict_method,
+ kRuntimePointerSize);
}
const void* code = method->GetEntryPointFromQuickCompiledCode();