Move FindDexMethodIndexInOtherDexFile into ArtMethod.
Move FindDexMethodIndexInOtherDexFile out of MethodHelper into ArtMethod in
preparation for the removal of MethodHelper.
Tidy ClassLinker::ResolveMethod so that all exception paths flow through the
exception pending assertion.
Tidy artQuickResolutionTrampoline to be more explicit about variable names and
only update the dex cache if necessary.
Change-Id: I3e48eb4f6c1291533067c1b53efe90c53bfcaea8
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4bd702d..52e6662 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1671,6 +1671,7 @@
LOG(FATAL) << "Failed to open dex file " << dex_file_location
<< " from within oat file " << oat_file.GetLocation()
<< " error '" << error_msg << "'";
+ UNREACHABLE();
}
CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
@@ -2393,6 +2394,7 @@
break;
default:
LOG(FATAL) << "Unknown descriptor: " << c;
+ UNREACHABLE();
}
}
}
@@ -2442,7 +2444,7 @@
}
DCHECK(!it.HasNext());
LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
- return 0;
+ UNREACHABLE();
}
const OatFile::OatMethod ClassLinker::FindOatMethodFor(mirror::ArtMethod* method, bool* found) {
@@ -3078,7 +3080,7 @@
LOG(ERROR) << "Registered dex file " << i << " = " << dex_cache->GetDexFile()->GetLocation();
}
LOG(FATAL) << "Failed to find DexCache for DexFile " << location;
- return nullptr;
+ UNREACHABLE();
}
void ClassLinker::FixupDexCaches(mirror::ArtMethod* resolution_method) {
@@ -3749,8 +3751,7 @@
LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
<< " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
<< klass->GetDescriptor(&temp);
-
- return false;
+ UNREACHABLE();
}
void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
@@ -5566,71 +5567,73 @@
}
// If we found something, check that it can be accessed by the referrer.
+ bool exception_generated = false;
if (resolved != nullptr && referrer.Get() != nullptr) {
mirror::Class* methods_class = resolved->GetDeclaringClass();
mirror::Class* referring_class = referrer->GetDeclaringClass();
if (!referring_class->CanAccess(methods_class)) {
ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
resolved, type);
- return nullptr;
+ exception_generated = true;
} else if (!referring_class->CanAccessMember(methods_class,
resolved->GetAccessFlags())) {
ThrowIllegalAccessErrorMethod(referring_class, resolved);
- return nullptr;
+ exception_generated = true;
}
}
-
- // Otherwise, throw an IncompatibleClassChangeError if we found something, and check interface
- // methods and throw if we find the method there. If we find nothing, throw a
- // NoSuchMethodError.
- switch (type) {
- case kDirect:
- case kStatic:
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
- } else {
- resolved = klass->FindInterfaceMethod(name, signature);
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
- } else {
- ThrowNoSuchMethodError(type, klass, name, signature);
- }
- }
- break;
- case kInterface:
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
- } else {
- resolved = klass->FindVirtualMethod(name, signature);
+ if (!exception_generated) {
+ // Otherwise, throw an IncompatibleClassChangeError if we found something, and check
+ // interface methods and throw if we find the method there. If we find nothing, throw a
+ // NoSuchMethodError.
+ switch (type) {
+ case kDirect:
+ case kStatic:
if (resolved != nullptr) {
ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
} else {
- ThrowNoSuchMethodError(type, klass, name, signature);
+ resolved = klass->FindInterfaceMethod(name, signature);
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+ } else {
+ ThrowNoSuchMethodError(type, klass, name, signature);
+ }
}
- }
- break;
- case kSuper:
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
- } else {
- ThrowNoSuchMethodError(type, klass, name, signature);
- }
- break;
- case kVirtual:
- if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
- } else {
- resolved = klass->FindInterfaceMethod(name, signature);
+ break;
+ case kInterface:
if (resolved != nullptr) {
- ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+ ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
+ } else {
+ resolved = klass->FindVirtualMethod(name, signature);
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
+ } else {
+ ThrowNoSuchMethodError(type, klass, name, signature);
+ }
+ }
+ break;
+ case kSuper:
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
} else {
ThrowNoSuchMethodError(type, klass, name, signature);
}
- }
- break;
+ break;
+ case kVirtual:
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
+ } else {
+ resolved = klass->FindInterfaceMethod(name, signature);
+ if (resolved != nullptr) {
+ ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+ } else {
+ ThrowNoSuchMethodError(type, klass, name, signature);
+ }
+ }
+ break;
+ }
}
}
- DCHECK(Thread::Current()->IsExceptionPending());
+ Thread::Current()->AssertPendingException();
return nullptr;
}
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index e3eb707..a176a87 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -22,7 +22,7 @@
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc/accounting/card_table-inl.h"
#include "interpreter/interpreter.h"
-#include "method_helper.h"
+#include "method_reference.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
@@ -642,7 +642,7 @@
// Convert proxy method into expected interface method.
mirror::ArtMethod* interface_method = proxy_method->FindOverriddenMethod();
- DCHECK(interface_method != NULL) << PrettyMethod(proxy_method);
+ DCHECK(interface_method != nullptr) << PrettyMethod(proxy_method);
DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
@@ -711,12 +711,12 @@
ClassLinker* linker = Runtime::Current()->GetClassLinker();
mirror::ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp);
InvokeType invoke_type;
- const DexFile* dex_file;
- uint32_t dex_method_idx;
- if (called->IsRuntimeMethod()) {
+ MethodReference called_method(nullptr, 0);
+ const bool called_method_known_on_entry = !called->IsRuntimeMethod();
+ if (!called_method_known_on_entry) {
uint32_t dex_pc = caller->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp));
const DexFile::CodeItem* code;
- dex_file = caller->GetDexFile();
+ called_method.dex_file = caller->GetDexFile();
code = caller->GetCodeItem();
CHECK_LT(dex_pc, code->insns_size_in_code_units_);
const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
@@ -764,33 +764,33 @@
is_range = true;
break;
default:
- LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
- // Avoid used uninitialized warnings.
- invoke_type = kDirect;
- is_range = false;
+ LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(nullptr);
+ UNREACHABLE();
}
- dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
+ called_method.dex_method_index = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
} else {
invoke_type = kStatic;
- dex_file = called->GetDexFile();
- dex_method_idx = called->GetDexMethodIndex();
+ called_method.dex_file = called->GetDexFile();
+ called_method.dex_method_index = called->GetDexMethodIndex();
}
uint32_t shorty_len;
const char* shorty =
- dex_file->GetMethodShorty(dex_file->GetMethodId(dex_method_idx), &shorty_len);
+ called_method.dex_file->GetMethodShorty(
+ called_method.dex_file->GetMethodId(called_method.dex_method_index), &shorty_len);
RememberForGcArgumentVisitor visitor(sp, invoke_type == kStatic, shorty, shorty_len, &soa);
visitor.VisitArguments();
self->EndAssertNoThreadSuspension(old_cause);
- bool virtual_or_interface = invoke_type == kVirtual || invoke_type == kInterface;
+ const bool virtual_or_interface = invoke_type == kVirtual || invoke_type == kInterface;
// Resolve method filling in dex cache.
- if (UNLIKELY(called->IsRuntimeMethod())) {
+ if (!called_method_known_on_entry) {
StackHandleScope<1> hs(self);
mirror::Object* dummy = nullptr;
HandleWrapper<mirror::Object> h_receiver(
hs.NewHandleWrapper(virtual_or_interface ? &receiver : &dummy));
- called = linker->ResolveMethod(self, dex_method_idx, &caller, invoke_type);
+ DCHECK_EQ(caller->GetDexFile(), called_method.dex_file);
+ called = linker->ResolveMethod(self, called_method.dex_method_index, &caller, invoke_type);
}
- const void* code = NULL;
+ const void* code = nullptr;
if (LIKELY(!self->IsExceptionPending())) {
// Incompatible class change should have been handled in resolve method.
CHECK(!called->CheckIncompatibleClassChange(invoke_type))
@@ -811,20 +811,23 @@
<< invoke_type << " " << orig_called->GetVtableIndex();
// We came here because of sharpening. Ensure the dex cache is up-to-date on the method index
- // of the sharpened method.
- if (called->HasSameDexCacheResolvedMethods(caller)) {
- caller->SetDexCacheResolvedMethod(called->GetDexMethodIndex(), called);
- } else {
+ // of the sharpened method avoiding dirtying the dex cache if possible.
+ uint32_t update_dex_cache_method_index = called_method.dex_method_index;
+ if (!called->HasSameDexCacheResolvedMethods(caller)) {
// Calling from one dex file to another, need to compute the method index appropriate to
// the caller's dex file. Since we get here only if the original called was a runtime
// method, we've got the correct dex_file and a dex_method_idx from above.
- DCHECK_EQ(caller->GetDexFile(), dex_file);
- StackHandleScope<1> hs(self);
- MethodHelper mh(hs.NewHandle(called));
- uint32_t method_index = mh.FindDexMethodIndexInOtherDexFile(*dex_file, dex_method_idx);
- if (method_index != DexFile::kDexNoIndex) {
- caller->SetDexCacheResolvedMethod(method_index, called);
- }
+ DCHECK(!called_method_known_on_entry);
+ DCHECK_EQ(caller->GetDexFile(), called_method.dex_file);
+ const DexFile* caller_dex_file = called_method.dex_file;
+ uint32_t caller_method_name_and_sig_index = called_method.dex_method_index;
+ update_dex_cache_method_index =
+ called->FindDexMethodIndexInOtherDexFile(*caller_dex_file,
+ caller_method_name_and_sig_index);
+ }
+ if ((update_dex_cache_method_index != DexFile::kDexNoIndex) &&
+ (caller->GetDexCacheResolvedMethod(update_dex_cache_method_index) != called)) {
+ caller->SetDexCacheResolvedMethod(update_dex_cache_method_index, called);
}
}
// Ensure that the called method's class is initialized.
@@ -846,7 +849,7 @@
DCHECK(called_class->IsErroneous());
}
}
- CHECK_EQ(code == NULL, self->IsExceptionPending());
+ CHECK_EQ(code == nullptr, self->IsExceptionPending());
// Fixup any locally saved objects may have moved during a GC.
visitor.FixupReferences();
// Place called method in callee-save frame to be placed as first argument to quick method.
@@ -1263,6 +1266,7 @@
break;
default:
LOG(FATAL) << "Unexpected type: " << cur_type_ << " in " << shorty;
+ UNREACHABLE();
}
}
@@ -1786,7 +1790,7 @@
visitor.FixupReferences();
}
- if (UNLIKELY(method == NULL)) {
+ if (UNLIKELY(method == nullptr)) {
CHECK(self->IsExceptionPending());
return GetTwoWordFailureValue(); // Failure.
}
@@ -1795,7 +1799,7 @@
const void* code = method->GetEntryPointFromQuickCompiledCode();
// When we return, the caller will branch to this address, so it had better not be 0!
- DCHECK(code != nullptr) << "Code was NULL in method: " << PrettyMethod(method)
+ DCHECK(code != nullptr) << "Code was null in method: " << PrettyMethod(method)
<< " location: "
<< method->GetDexFile()->GetLocation();
@@ -1881,7 +1885,7 @@
mirror::ArtMethod* method;
if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex)) {
method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
- if (UNLIKELY(method == NULL)) {
+ if (UNLIKELY(method == nullptr)) {
ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(interface_method, this_object,
caller_method);
return GetTwoWordFailureValue(); // Failure.
@@ -1901,7 +1905,7 @@
Instruction::Code instr_code = instr->Opcode();
CHECK(instr_code == Instruction::INVOKE_INTERFACE ||
instr_code == Instruction::INVOKE_INTERFACE_RANGE)
- << "Unexpected call into interface trampoline: " << instr->DumpString(NULL);
+ << "Unexpected call into interface trampoline: " << instr->DumpString(nullptr);
uint32_t dex_method_idx;
if (instr_code == Instruction::INVOKE_INTERFACE) {
dex_method_idx = instr->VRegB_35c();
@@ -1933,7 +1937,7 @@
const void* code = method->GetEntryPointFromQuickCompiledCode();
// When we return, the caller will branch to this address, so it had better not be 0!
- DCHECK(code != nullptr) << "Code was NULL in method: " << PrettyMethod(method)
+ DCHECK(code != nullptr) << "Code was null in method: " << PrettyMethod(method)
<< " location: " << method->GetDexFile()->GetLocation();
return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(code),
diff --git a/runtime/method_helper.cc b/runtime/method_helper.cc
index 81e1794..683d1bd 100644
--- a/runtime/method_helper.cc
+++ b/runtime/method_helper.cc
@@ -58,94 +58,8 @@
return true;
}
-template <template <class T> class HandleKind>
-uint32_t MethodHelperT<HandleKind>::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* method = GetMethod();
- const DexFile* dexfile = method->GetDexFile();
- if (dexfile == &other_dexfile) {
- return method->GetDexMethodIndex();
- }
- const DexFile::MethodId& mid = dexfile->GetMethodId(method->GetDexMethodIndex());
- const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
- const DexFile::StringId* other_descriptor =
- other_dexfile.FindStringId(mid_declaring_class_descriptor);
- if (other_descriptor != nullptr) {
- const DexFile::TypeId* other_type_id =
- other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor));
- if (other_type_id != nullptr) {
- const char* mid_name = dexfile->GetMethodName(mid);
- const DexFile::StringId* other_name = other_dexfile.FindStringId(mid_name);
- if (other_name != nullptr) {
- uint16_t other_return_type_idx;
- std::vector<uint16_t> other_param_type_idxs;
- bool success = other_dexfile.CreateTypeList(
- dexfile->GetMethodSignature(mid).ToString(), &other_return_type_idx,
- &other_param_type_idxs);
- if (success) {
- const DexFile::ProtoId* other_sig =
- other_dexfile.FindProtoId(other_return_type_idx, other_param_type_idxs);
- if (other_sig != nullptr) {
- const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
- *other_type_id, *other_name, *other_sig);
- if (other_mid != nullptr) {
- return other_dexfile.GetIndexForMethodId(*other_mid);
- }
- }
- }
- }
- }
- }
- return DexFile::kDexNoIndex;
-}
-
-template <template <typename> class HandleKind>
-uint32_t MethodHelperT<HandleKind>::FindDexMethodIndexInOtherDexFile(
- const DexFile& other_dexfile, uint32_t name_and_signature_idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* method = GetMethod();
- const DexFile* dexfile = method->GetDexFile();
- const uint32_t dex_method_idx = method->GetDexMethodIndex();
- const DexFile::MethodId& mid = dexfile->GetMethodId(dex_method_idx);
- const DexFile::MethodId& name_and_sig_mid = other_dexfile.GetMethodId(name_and_signature_idx);
- DCHECK_STREQ(dexfile->GetMethodName(mid), other_dexfile.GetMethodName(name_and_sig_mid));
- DCHECK_EQ(dexfile->GetMethodSignature(mid), other_dexfile.GetMethodSignature(name_and_sig_mid));
- if (dexfile == &other_dexfile) {
- return dex_method_idx;
- }
- const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
- const DexFile::StringId* other_descriptor =
- other_dexfile.FindStringId(mid_declaring_class_descriptor);
- if (other_descriptor != nullptr) {
- const DexFile::TypeId* other_type_id =
- other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor));
- if (other_type_id != nullptr) {
- const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
- *other_type_id, other_dexfile.GetStringId(name_and_sig_mid.name_idx_),
- other_dexfile.GetProtoId(name_and_sig_mid.proto_idx_));
- if (other_mid != nullptr) {
- return other_dexfile.GetIndexForMethodId(*other_mid);
- }
- }
- }
- return DexFile::kDexNoIndex;
-}
-
// Instantiate methods.
template
-uint32_t MethodHelperT<Handle>::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile);
-template
-uint32_t MethodHelperT<MutableHandle>::FindDexMethodIndexInOtherDexFile(
- const DexFile& other_dexfile);
-
-template
-uint32_t MethodHelperT<Handle>::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
- uint32_t name_and_signature_idx);
-template
-uint32_t MethodHelperT<MutableHandle>::FindDexMethodIndexInOtherDexFile(
- const DexFile& other_dexfile, uint32_t name_and_signature_idx);
-
-template
bool MethodHelperT<Handle>::HasSameSignatureWithDifferentClassLoaders<Handle>(Thread* self,
MethodHelperT<Handle>* other);
diff --git a/runtime/method_helper.h b/runtime/method_helper.h
index dc305d5..2630608 100644
--- a/runtime/method_helper.h
+++ b/runtime/method_helper.h
@@ -109,15 +109,6 @@
mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // The name_and_signature_idx MUST point to a MethodId with the same name and signature in the
- // other_dexfile, such as the method index used to resolve this method in the other_dexfile.
- uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
- uint32_t name_and_signature_idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
protected:
HandleKind<mirror::ArtMethod> method_;
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 4f5ca3f..40c2b2c 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -160,6 +160,35 @@
return result;
}
+uint32_t ArtMethod::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
+ uint32_t name_and_signature_idx) {
+ const DexFile* dexfile = GetDexFile();
+ const uint32_t dex_method_idx = GetDexMethodIndex();
+ const DexFile::MethodId& mid = dexfile->GetMethodId(dex_method_idx);
+ const DexFile::MethodId& name_and_sig_mid = other_dexfile.GetMethodId(name_and_signature_idx);
+ DCHECK_STREQ(dexfile->GetMethodName(mid), other_dexfile.GetMethodName(name_and_sig_mid));
+ DCHECK_EQ(dexfile->GetMethodSignature(mid), other_dexfile.GetMethodSignature(name_and_sig_mid));
+ if (dexfile == &other_dexfile) {
+ return dex_method_idx;
+ }
+ const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
+ const DexFile::StringId* other_descriptor =
+ other_dexfile.FindStringId(mid_declaring_class_descriptor);
+ if (other_descriptor != nullptr) {
+ const DexFile::TypeId* other_type_id =
+ other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor));
+ if (other_type_id != nullptr) {
+ const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
+ *other_type_id, other_dexfile.GetStringId(name_and_sig_mid.name_idx_),
+ other_dexfile.GetProtoId(name_and_sig_mid.proto_idx_));
+ if (other_mid != nullptr) {
+ return other_dexfile.GetIndexForMethodId(*other_mid);
+ }
+ }
+ }
+ return DexFile::kDexNoIndex;
+}
+
uint32_t ArtMethod::ToDexPc(const uintptr_t pc, bool abort_on_failure) {
if (IsPortableCompiled()) {
// Portable doesn't use the machine pc, we just use dex pc instead.
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 0466fe3..04f8efc 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -237,9 +237,17 @@
bool HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Find the method that this method overrides
+ // Find the method that this method overrides.
ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Find the method index for this method within other_dexfile. If this method isn't present then
+ // return DexFile::kDexNoIndex. The name_and_signature_idx MUST refer to a MethodId with the same
+ // name and signature in the other_dexfile, such as the method index used to resolve this method
+ // in the other_dexfile.
+ uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
+ uint32_t name_and_signature_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);