Merge "AOT inlined method lookup should stay within dex file." into pi-dev
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 270bce2..137eb4f 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -70,45 +70,41 @@
   }
 
   // Find which method did the call in the inlining hierarchy.
-  ArtMethod* caller = outer_method;
-  if (inlining_depth != 0) {
-    caller = GetResolvedMethod(outer_method,
-                               method_info,
-                               inline_info,
-                               encoding,
-                               inlining_depth - 1);
-  }
-
-  // Lookup the declaring class of the inlined method.
-  ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache();
-  ArtMethod* inlined_method = dex_cache->GetResolvedMethod(method_index, kRuntimePointerSize);
-  if (inlined_method != nullptr) {
-    DCHECK(!inlined_method->IsRuntimeMethod());
-    return inlined_method;
-  }
-  // TODO: Use ClassLoader::LookupResolvedMethod() instead.
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  const DexFile::MethodId& method_id = dex_file->GetMethodId(method_index);
-  const char* descriptor = dex_file->StringByTypeIdx(method_id.class_idx_);
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Thread* self = Thread::Current();
-  mirror::ClassLoader* class_loader = caller->GetDeclaringClass()->GetClassLoader();
-  mirror::Class* klass = class_linker->LookupClass(self, descriptor, class_loader);
-  if (klass == nullptr) {
-    LOG(FATAL) << "Could not find an inlined method from an .oat file: the class " << descriptor
-               << " was not found in the class loader of " << caller->PrettyMethod() << ". "
-               << "This must be due to playing wrongly with class loaders";
+  ArtMethod* method = outer_method;
+  for (uint32_t depth = 0, end = inlining_depth + 1u; depth != end; ++depth) {
+    DCHECK(!inline_info.EncodesArtMethodAtDepth(encoding, depth));
+    DCHECK_NE(inline_info.GetDexPcAtDepth(encoding, depth), static_cast<uint32_t>(-1));
+    method_index = inline_info.GetMethodIndexAtDepth(encoding, method_info, depth);
+    ArtMethod* inlined_method = class_linker->LookupResolvedMethod(method_index,
+                                                                   method->GetDexCache(),
+                                                                   method->GetClassLoader());
+    if (UNLIKELY(inlined_method == nullptr)) {
+      LOG(FATAL) << "Could not find an inlined method from an .oat file: "
+                 << method->GetDexFile()->PrettyMethod(method_index) << " . "
+                 << "This must be due to duplicate classes or playing wrongly with class loaders";
+      UNREACHABLE();
+    }
+    DCHECK(!inlined_method->IsRuntimeMethod());
+    if (UNLIKELY(inlined_method->GetDexFile() != method->GetDexFile())) {
+      // TODO: We could permit inlining within a multi-dex oat file and the boot image,
+      // even going back from boot image methods to the same oat file. However, this is
+      // not currently implemented in the compiler. Therefore crossing dex file boundary
+      // indicates that the inlined definition is not the same as the one used at runtime.
+      LOG(FATAL) << "Inlined method resolution crossed dex file boundary: from "
+                 << method->PrettyMethod()
+                 << " in " << method->GetDexFile()->GetLocation() << "/"
+                 << static_cast<const void*>(method->GetDexFile())
+                 << " to " << inlined_method->PrettyMethod()
+                 << " in " << inlined_method->GetDexFile()->GetLocation() << "/"
+                 << static_cast<const void*>(inlined_method->GetDexFile()) << ". "
+                 << "This must be due to duplicate classes or playing wrongly with class loaders";
+      UNREACHABLE();
+    }
+    method = inlined_method;
   }
 
-  inlined_method = class_linker->FindResolvedMethod(klass, dex_cache, class_loader, method_index);
-  if (inlined_method == nullptr) {
-    LOG(FATAL) << "Could not find an inlined method from an .oat file: the class " << descriptor
-               << " does not have " << dex_file->GetMethodName(method_id)
-               << dex_file->GetMethodSignature(method_id) << " declared. "
-               << "This must be due to duplicate classes or playing wrongly with class loaders";
-  }
-
-  return inlined_method;
+  return method;
 }
 
 ALWAYS_INLINE inline mirror::Class* CheckObjectAlloc(mirror::Class* klass,