Remove #include "oat_file.h" from class_linker.h .

Refactor the OatClass and OatMethod related functions from
ClassLinker to OatFile and ArtMethod, respectively. Refactor
the remaining ClassLinker dependencies on OatFile to break
the #include dependency and reduce incremental build times.

Test: m test-art-host
Change-Id: Iebc5b9f81b48fbcf79821cc827a5d7c4a0261bf6
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index c97c328..937dcee 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -283,7 +283,9 @@
       // Ensure that we won't be accidentally calling quick compiled code when -Xint.
       if (kIsDebugBuild && runtime->GetInstrumentation()->IsForcedInterpretOnly()) {
         CHECK(!runtime->UseJitCompilation());
-        const void* oat_quick_code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor(this);
+        const void* oat_quick_code = (IsNative() || !IsInvokable() || IsProxyMethod())
+            ? nullptr
+            : GetOatMethodQuickCode(runtime->GetClassLinker()->GetImagePointerSize());
         CHECK(oat_quick_code == nullptr || oat_quick_code != GetEntryPointFromQuickCompiledCode())
             << "Don't call compiled code when -Xint " << PrettyMethod(this);
       }
@@ -360,6 +362,80 @@
   return annotations::IsMethodAnnotationPresent(this, annotation_handle, visibility);
 }
 
+static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
+                                                 uint16_t class_def_idx,
+                                                 uint32_t method_idx) {
+  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx);
+  const uint8_t* class_data = dex_file.GetClassData(class_def);
+  CHECK(class_data != nullptr);
+  ClassDataItemIterator it(dex_file, class_data);
+  // Skip fields
+  while (it.HasNextStaticField()) {
+    it.Next();
+  }
+  while (it.HasNextInstanceField()) {
+    it.Next();
+  }
+  // Process methods
+  size_t class_def_method_index = 0;
+  while (it.HasNextDirectMethod()) {
+    if (it.GetMemberIndex() == method_idx) {
+      return class_def_method_index;
+    }
+    class_def_method_index++;
+    it.Next();
+  }
+  while (it.HasNextVirtualMethod()) {
+    if (it.GetMemberIndex() == method_idx) {
+      return class_def_method_index;
+    }
+    class_def_method_index++;
+    it.Next();
+  }
+  DCHECK(!it.HasNext());
+  LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
+  UNREACHABLE();
+}
+
+static const OatFile::OatMethod FindOatMethodFor(ArtMethod* method,
+                                                 PointerSize pointer_size,
+                                                 bool* found)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  // Although we overwrite the trampoline of non-static methods, we may get here via the resolution
+  // method for direct methods (or virtual methods made direct).
+  mirror::Class* declaring_class = method->GetDeclaringClass();
+  size_t oat_method_index;
+  if (method->IsStatic() || method->IsDirect()) {
+    // Simple case where the oat method index was stashed at load time.
+    oat_method_index = method->GetMethodIndex();
+  } else {
+    // Compute the oat_method_index by search for its position in the declared virtual methods.
+    oat_method_index = declaring_class->NumDirectMethods();
+    bool found_virtual = false;
+    for (ArtMethod& art_method : declaring_class->GetVirtualMethods(pointer_size)) {
+      // Check method index instead of identity in case of duplicate method definitions.
+      if (method->GetDexMethodIndex() == art_method.GetDexMethodIndex()) {
+        found_virtual = true;
+        break;
+      }
+      oat_method_index++;
+    }
+    CHECK(found_virtual) << "Didn't find oat method index for virtual method: "
+                         << PrettyMethod(method);
+  }
+  DCHECK_EQ(oat_method_index,
+            GetOatMethodIndexFromMethodIndex(*declaring_class->GetDexCache()->GetDexFile(),
+                                             method->GetDeclaringClass()->GetDexClassDefIndex(),
+                                             method->GetDexMethodIndex()));
+  OatFile::OatClass oat_class = OatFile::FindOatClass(*declaring_class->GetDexCache()->GetDexFile(),
+                                                      declaring_class->GetDexClassDefIndex(),
+                                                      found);
+  if (!(*found)) {
+    return OatFile::OatMethod::Invalid();
+  }
+  return oat_class.GetOatMethod(oat_method_index);
+}
+
 bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {
   auto* dex_cache = GetDexCache();
   auto* dex_file = dex_cache->GetDexFile();
@@ -386,10 +462,9 @@
   return true;
 }
 
-const uint8_t* ArtMethod::GetQuickenedInfo() {
+const uint8_t* ArtMethod::GetQuickenedInfo(PointerSize pointer_size) {
   bool found = false;
-  OatFile::OatMethod oat_method =
-      Runtime::Current()->GetClassLinker()->FindOatMethodFor(this, &found);
+  OatFile::OatMethod oat_method = FindOatMethodFor(this, pointer_size, &found);
   if (!found || (oat_method.GetQuickCode() != nullptr)) {
     return nullptr;
   }
@@ -433,7 +508,7 @@
   }
 
   // Check whether the pc is in the JIT code cache.
-  jit::Jit* jit = Runtime::Current()->GetJit();
+  jit::Jit* jit = runtime->GetJit();
   if (jit != nullptr) {
     jit::JitCodeCache* code_cache = jit->GetCodeCache();
     OatQuickMethodHeader* method_header = code_cache->LookupMethodHeader(pc, this);
@@ -452,7 +527,8 @@
 
   // The code has to be in an oat file.
   bool found;
-  OatFile::OatMethod oat_method = class_linker->FindOatMethodFor(this, &found);
+  OatFile::OatMethod oat_method =
+      FindOatMethodFor(this, class_linker->GetImagePointerSize(), &found);
   if (!found) {
     if (class_linker->IsQuickResolutionStub(existing_entry_point)) {
       // We are running the generic jni stub, but the entry point of the method has not
@@ -491,15 +567,29 @@
   return method_header;
 }
 
+const void* ArtMethod::GetOatMethodQuickCode(PointerSize pointer_size) {
+  bool found;
+  OatFile::OatMethod oat_method = FindOatMethodFor(this, pointer_size, &found);
+  if (found) {
+    return oat_method.GetQuickCode();
+  }
+  return nullptr;
+}
+
 bool ArtMethod::HasAnyCompiledCode() {
+  if (IsNative() || !IsInvokable() || IsProxyMethod()) {
+    return false;
+  }
+
   // Check whether the JIT has compiled it.
-  jit::Jit* jit = Runtime::Current()->GetJit();
+  Runtime* runtime = Runtime::Current();
+  jit::Jit* jit = runtime->GetJit();
   if (jit != nullptr && jit->GetCodeCache()->ContainsMethod(this)) {
     return true;
   }
 
   // Check whether we have AOT code.
-  return Runtime::Current()->GetClassLinker()->GetOatMethodQuickCodeFor(this) != nullptr;
+  return GetOatMethodQuickCode(runtime->GetClassLinker()->GetImagePointerSize()) != nullptr;
 }
 
 void ArtMethod::CopyFrom(ArtMethod* src, PointerSize image_pointer_size) {