Speed up method lookup in a different dex file.
Use already known name and proto.
Change-Id: I4505b81724bd6a0f3cf21ee6fed44774d38c4e15
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 402d4f4..61e9fbb 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1200,7 +1200,7 @@
if (no_guarantee_of_dex_cache_entry) {
// See if the method is also declared in this dex cache.
uint32_t dex_method_idx = MethodHelper(method).FindDexMethodIndexInOtherDexFile(
- *target_method->dex_file);
+ *target_method->dex_file, target_method->dex_method_index);
if (dex_method_idx != DexFile::kDexNoIndex) {
target_method->dex_method_index = dex_method_idx;
} else {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 9f30190..f9486c3 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -561,9 +561,11 @@
caller->GetDexCacheResolvedMethods()->Set(called->GetDexMethodIndex(), called);
} else {
// Calling from one dex file to another, need to compute the method index appropriate to
- // the caller's dex file.
+ // 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(&MethodHelper(caller).GetDexFile() == dex_file);
uint32_t method_index =
- MethodHelper(called).FindDexMethodIndexInOtherDexFile(MethodHelper(caller).GetDexFile());
+ MethodHelper(called).FindDexMethodIndexInOtherDexFile(*dex_file, dex_method_idx);
if (method_index != DexFile::kDexNoIndex) {
caller->GetDexCacheResolvedMethods()->Set(method_index, called);
}
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 0451f5d..a981fab 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -607,6 +607,37 @@
return DexFile::kDexNoIndex;
}
+ // 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_) {
+ const DexFile& dexfile = GetDexFile();
+ const DexFile::MethodId& mid = dexfile.GetMethodId(method_->GetDexMethodIndex());
+ 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 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 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;
+ }
+
private:
// Set the method_ field, for proxy methods looking up the interface method via the resolved
// methods table.