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.