Hash-based DexCache methods array.

Total boot*.art size for aosp_angler-userdebug:
  - arm64:
    - before: 11603968
    - after: 10129408 (-1.4MiB, -12.7%)
  - arm:
    - before: 8626176
    - after: 7888896 (-0.7MiB, -8.5%)

Test: m test-art-host-gtest
Test: testrunner.py --host
Test: Nexus 6P boots.
Test: testrunner.py --target
Test: Build aosp_mips64-eng
Bug: 30627598
Change-Id: I7f858605de5f074cbd7f0d9c4c072fbd44aee28f
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index f8bb417..4d258af 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -1116,6 +1116,7 @@
                          const std::vector<const DexFile*>* dex_files)
       : OatDexMethodVisitor(writer, offset),
         pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
+        class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
         dex_files_(dex_files),
         class_linker_(Runtime::Current()->GetClassLinker()) {}
 
@@ -1131,10 +1132,7 @@
     if (!IsImageClass()) {
       return true;
     }
-    ScopedObjectAccessUnchecked soa(Thread::Current());
-    StackHandleScope<1> hs(soa.Self());
-    Handle<mirror::DexCache> dex_cache = hs.NewHandle(
-        class_linker_->FindDexCache(Thread::Current(), *dex_file));
+    ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(Thread::Current(), *dex_file);
     const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
     mirror::Class* klass = dex_cache->GetResolvedType(class_def.class_idx_);
     if (klass != nullptr) {
@@ -1182,36 +1180,36 @@
       ++method_offsets_index_;
     }
 
-    // Unchecked as we hold mutator_lock_ on entry.
-    ScopedObjectAccessUnchecked soa(Thread::Current());
-    StackHandleScope<1> hs(soa.Self());
-    Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker_->FindDexCache(
-        Thread::Current(), *dex_file_)));
+    Thread* self = Thread::Current();
+    ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(self, *dex_file_);
     ArtMethod* method;
     if (writer_->HasBootImage()) {
       const InvokeType invoke_type = it.GetMethodInvokeType(
           dex_file_->GetClassDef(class_def_index_));
+      // Unchecked as we hold mutator_lock_ on entry.
+      ScopedObjectAccessUnchecked soa(self);
+      StackHandleScope<1> hs(self);
       method = class_linker_->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
           *dex_file_,
           it.GetMemberIndex(),
-          dex_cache,
+          hs.NewHandle(dex_cache),
           ScopedNullHandle<mirror::ClassLoader>(),
           nullptr,
           invoke_type);
       if (method == nullptr) {
         LOG(FATAL_WITHOUT_ABORT) << "Unexpected failure to resolve a method: "
             << dex_file_->PrettyMethod(it.GetMemberIndex(), true);
-        soa.Self()->AssertPendingException();
-        mirror::Throwable* exc = soa.Self()->GetException();
+        self->AssertPendingException();
+        mirror::Throwable* exc = self->GetException();
         std::string dump = exc->Dump();
         LOG(FATAL) << dump;
         UNREACHABLE();
       }
     } else {
-      // Should already have been resolved by the compiler, just peek into the dex cache.
+      // Should already have been resolved by the compiler.
       // It may not be resolved if the class failed to verify, in this case, don't set the
-      // entrypoint. This is not fatal since the dex cache will contain a resolution method.
-      method = dex_cache->GetResolvedMethod(it.GetMemberIndex(), pointer_size_);
+      // entrypoint. This is not fatal since we shall use a resolution method.
+      method = class_linker_->LookupResolvedMethod(it.GetMemberIndex(), dex_cache, class_loader_);
     }
     if (method != nullptr &&
         compiled_method != nullptr &&
@@ -1252,6 +1250,7 @@
 
  private:
   const PointerSize pointer_size_;
+  ObjPtr<mirror::ClassLoader> class_loader_;
   const std::vector<const DexFile*>* dex_files_;
   ClassLinker* const class_linker_;
   std::vector<std::pair<ArtMethod*, ArtMethod*>> methods_to_process_;
@@ -1471,7 +1470,8 @@
     ObjPtr<mirror::DexCache> dex_cache =
         (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(
             Thread::Current(), *ref.dex_file);
-    ArtMethod* method = dex_cache->GetResolvedMethod(ref.dex_method_index, pointer_size_);
+    ArtMethod* method =
+        class_linker_->LookupResolvedMethod(ref.dex_method_index, dex_cache, class_loader_);
     CHECK(method != nullptr);
     return method;
   }