Reduce how often we call FindDexCache

Before host boot.oat -j4 optimizing compile:
real  1m17.792s
user  3m26.140s
sys 0m8.340s

After:
real  1m12.324s
user  3m22.718s
sys 0m8.320s

Change-Id: If18e9e79e06cdf1676692e5efacb682bf93889c3
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 603130a..850cca0 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -324,9 +324,13 @@
     DexToDexCompilationLevel dex_to_dex_compilation_level) {
   DCHECK(driver != nullptr);
   if (dex_to_dex_compilation_level != DexToDexCompilationLevel::kDontDexToDexCompile) {
-    art::DexCompilationUnit unit(nullptr, class_loader, art::Runtime::Current()->GetClassLinker(),
+    ScopedObjectAccess soa(Thread::Current());
+    StackHandleScope<1> hs(soa.Self());
+    ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+    art::DexCompilationUnit unit(nullptr, class_loader, class_linker,
                                  dex_file, code_item, class_def_idx, method_idx, access_flags,
-                                 driver->GetVerifiedMethod(&dex_file, method_idx));
+                                 driver->GetVerifiedMethod(&dex_file, method_idx),
+                                 hs.NewHandle(class_linker->FindDexCache(soa.Self(), dex_file)));
     art::optimizer::DexCompiler dex_compiler(*driver, unit, dex_to_dex_compilation_level);
     dex_compiler.Compile();
     if (dex_compiler.GetQuickenedInfo().empty()) {
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc
index 1cff8dc..39f8ee8 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -30,6 +30,7 @@
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "driver/dex_compilation_unit.h"
+#include "scoped_thread_state_change.h"
 #include "utils.h"
 
 namespace art {
@@ -1283,8 +1284,12 @@
       ifield_lowering_infos_.push_back(
           MirIFieldLoweringInfo(masked_field_idx, field_types[pos], is_quickened));
     }
-    MirIFieldLoweringInfo::Resolve(cu_->compiler_driver, GetCurrentDexCompilationUnit(),
-                                   ifield_lowering_infos_.data(), ifield_pos);
+    ScopedObjectAccess soa(Thread::Current());
+    MirIFieldLoweringInfo::Resolve(soa,
+                                   cu_->compiler_driver,
+                                   GetCurrentDexCompilationUnit(),
+                                   ifield_lowering_infos_.data(),
+                                   ifield_pos);
   }
 
   if (sfield_pos != max_refs) {
diff --git a/compiler/dex/mir_field_info.cc b/compiler/dex/mir_field_info.cc
index 4dfec17..13bbc3e 100644
--- a/compiler/dex/mir_field_info.cc
+++ b/compiler/dex/mir_field_info.cc
@@ -29,7 +29,8 @@
 
 namespace art {
 
-void MirIFieldLoweringInfo::Resolve(CompilerDriver* compiler_driver,
+void MirIFieldLoweringInfo::Resolve(const ScopedObjectAccess& soa,
+                                    CompilerDriver* compiler_driver,
                                     const DexCompilationUnit* mUnit,
                                     MirIFieldLoweringInfo* field_infos, size_t count) {
   if (kIsDebugBuild) {
@@ -44,7 +45,6 @@
 
   // We're going to resolve fields and check access in a tight loop. It's better to hold
   // the lock and needed references once than re-acquiring them again and again.
-  ScopedObjectAccess soa(Thread::Current());
   StackHandleScope<3> hs(soa.Self());
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit)));
   Handle<mirror::ClassLoader> class_loader(
diff --git a/compiler/dex/mir_field_info.h b/compiler/dex/mir_field_info.h
index 053029d..b6dc27d 100644
--- a/compiler/dex/mir_field_info.h
+++ b/compiler/dex/mir_field_info.h
@@ -26,6 +26,7 @@
 
 class CompilerDriver;
 class DexCompilationUnit;
+class ScopedObjectAccess;
 
 /*
  * Field info is calculated from the perspective of the compilation unit that accesses
@@ -133,9 +134,12 @@
   // For each requested instance field retrieve the field's declaring location (dex file, class
   // index and field index) and volatility and compute whether we can fast path the access
   // with IGET/IPUT. For fast path fields, retrieve the field offset.
-  static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
-                      MirIFieldLoweringInfo* field_infos, size_t count)
-      REQUIRES(!Locks::mutator_lock_);
+  static void Resolve(const ScopedObjectAccess& soa,
+                      CompilerDriver* compiler_driver,
+                      const DexCompilationUnit* mUnit,
+                      MirIFieldLoweringInfo* field_infos,
+                      size_t count)
+      SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Construct an unresolved instance field lowering info.
   MirIFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type, bool is_quickened)
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 3834242..7976a9a 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -699,16 +699,17 @@
 /* Parse a Dex method and insert it into the MIRGraph at the current insert point. */
 void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
                            InvokeType invoke_type ATTRIBUTE_UNUSED, uint16_t class_def_idx,
-                           uint32_t method_idx, jobject class_loader, const DexFile& dex_file) {
+                           uint32_t method_idx, jobject class_loader, const DexFile& dex_file,
+                           Handle<mirror::DexCache> dex_cache) {
   current_code_item_ = code_item;
   method_stack_.push_back(std::make_pair(current_method_, current_offset_));
   current_method_ = m_units_.size();
   current_offset_ = 0;
   // TODO: will need to snapshot stack image and use that as the mir context identification.
   m_units_.push_back(new (arena_) DexCompilationUnit(
-      cu_, class_loader, Runtime::Current()->GetClassLinker(), dex_file,
-      current_code_item_, class_def_idx, method_idx, access_flags,
-      cu_->compiler_driver->GetVerifiedMethod(&dex_file, method_idx)));
+      cu_, class_loader, Runtime::Current()->GetClassLinker(), dex_file, current_code_item_,
+      class_def_idx, method_idx, access_flags,
+      cu_->compiler_driver->GetVerifiedMethod(&dex_file, method_idx), dex_cache));
   const uint16_t* code_ptr = current_code_item_->insns_;
   const uint16_t* code_end =
       current_code_item_->insns_ + current_code_item_->insns_size_in_code_units_;
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 8bf709a..a9ebe9c 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -572,9 +572,14 @@
    * Parse dex method and add MIR at current insert point.  Returns id (which is
    * actually the index of the method in the m_units_ array).
    */
-  void InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
-                    InvokeType invoke_type, uint16_t class_def_idx,
-                    uint32_t method_idx, jobject class_loader, const DexFile& dex_file);
+  void InlineMethod(const DexFile::CodeItem* code_item,
+                    uint32_t access_flags,
+                    InvokeType invoke_type,
+                    uint16_t class_def_idx,
+                    uint32_t method_idx,
+                    jobject class_loader,
+                    const DexFile& dex_file,
+                    Handle<mirror::DexCache> dex_cache);
 
   /* Find existing block */
   BasicBlock* FindBlock(DexOffset code_offset,
diff --git a/compiler/dex/mir_method_info.cc b/compiler/dex/mir_method_info.cc
index 31c3808..658e7d6 100644
--- a/compiler/dex/mir_method_info.cc
+++ b/compiler/dex/mir_method_info.cc
@@ -112,7 +112,8 @@
           mUnit->GetCompilationUnit(), mUnit->GetClassLoader(), mUnit->GetClassLinker(),
           *it->target_dex_file_, nullptr /* code_item not used */, 0u /* class_def_idx not used */,
           it->target_method_idx_, 0u /* access_flags not used */,
-          nullptr /* verified_method not used */);
+          nullptr /* verified_method not used */,
+          current_dex_cache);
       resolved_method = compiler_driver->ResolveMethod(soa, current_dex_cache, class_loader, &cu,
                                                        it->target_method_idx_, invoke_type, false);
       if (resolved_method == nullptr) {
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 80b7ac1..eb4915b 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -17,6 +17,7 @@
 #include "base/bit_vector-inl.h"
 #include "base/logging.h"
 #include "base/scoped_arena_containers.h"
+#include "class_linker-inl.h"
 #include "dataflow_iterator-inl.h"
 #include "dex/verified_method.h"
 #include "dex_flags.h"
@@ -30,6 +31,7 @@
 #include "quick/dex_file_method_inliner.h"
 #include "quick/dex_file_to_method_inliner_map.h"
 #include "stack.h"
+#include "thread-inl.h"
 #include "type_inference.h"
 #include "utils.h"
 
@@ -1469,13 +1471,23 @@
 
   const MirMethodLoweringInfo& method_info = GetMethodLoweringInfo(invoke);
   MethodReference target = method_info.GetTargetMethod();
-  DexCompilationUnit inlined_unit(
-      cu_, cu_->class_loader, cu_->class_linker, *target.dex_file,
-      nullptr /* code_item not used */, 0u /* class_def_idx not used */, target.dex_method_index,
-      0u /* access_flags not used */, nullptr /* verified_method not used */);
+  ScopedObjectAccess soa(Thread::Current());
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::DexCache> dex_cache(
+      hs.NewHandle(cu_->class_linker->FindDexCache(hs.Self(), *target.dex_file)));
+  DexCompilationUnit inlined_unit(cu_,
+                                  cu_->class_loader,
+                                  cu_->class_linker,
+                                  *target.dex_file,
+                                  nullptr /* code_item not used */,
+                                  0u /* class_def_idx not used */,
+                                  target.dex_method_index,
+                                  0u /* access_flags not used */,
+                                  nullptr /* verified_method not used */,
+                                  dex_cache);
   DexMemAccessType type = IGetOrIPutMemAccessType(iget_or_iput->dalvikInsn.opcode);
   MirIFieldLoweringInfo inlined_field_info(field_idx, type, false);
-  MirIFieldLoweringInfo::Resolve(cu_->compiler_driver, &inlined_unit, &inlined_field_info, 1u);
+  MirIFieldLoweringInfo::Resolve(soa, cu_->compiler_driver, &inlined_unit, &inlined_field_info, 1u);
   DCHECK(inlined_field_info.IsResolved());
 
   uint32_t field_info_index = ifield_lowering_infos_.size();
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc
index 3642b82..b5ecf9c 100644
--- a/compiler/dex/quick/quick_compiler.cc
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -663,7 +663,8 @@
                                        uint16_t class_def_idx,
                                        uint32_t method_idx,
                                        jobject class_loader,
-                                       const DexFile& dex_file) const {
+                                       const DexFile& dex_file,
+                                       Handle<mirror::DexCache> dex_cache) const {
   if (kPoisonHeapReferences) {
     VLOG(compiler) << "Skipping method : " << PrettyMethod(method_idx, dex_file)
                    << "  Reason = Quick does not support heap poisoning.";
@@ -749,7 +750,7 @@
 
   /* Build the raw MIR graph */
   cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx,
-                             class_loader, dex_file);
+                             class_loader, dex_file, dex_cache);
 
   if (!CanCompileMethod(method_idx, dex_file, &cu)) {
     VLOG(compiler)  << cu.instruction_set << ": Cannot compile method : "
diff --git a/compiler/dex/quick/quick_compiler.h b/compiler/dex/quick/quick_compiler.h
index 4a39ab3..d512b25 100644
--- a/compiler/dex/quick/quick_compiler.h
+++ b/compiler/dex/quick/quick_compiler.h
@@ -21,6 +21,10 @@
 
 namespace art {
 
+namespace mirror {
+class DexCache;
+}
+
 class Compiler;
 class CompilerDriver;
 class Mir2Lir;
@@ -43,7 +47,8 @@
                           uint16_t class_def_idx,
                           uint32_t method_idx,
                           jobject class_loader,
-                          const DexFile& dex_file) const OVERRIDE;
+                          const DexFile& dex_file,
+                          Handle<mirror::DexCache> dex_cache) const OVERRIDE;
 
   CompiledMethod* JniCompile(uint32_t access_flags,
                              uint32_t method_idx,
diff --git a/compiler/dex/type_inference_test.cc b/compiler/dex/type_inference_test.cc
index eaa2bfa..872a8d6 100644
--- a/compiler/dex/type_inference_test.cc
+++ b/compiler/dex/type_inference_test.cc
@@ -252,7 +252,8 @@
     cu_.mir_graph->m_units_.push_back(new (cu_.mir_graph->arena_) DexCompilationUnit(
         &cu_, cu_.class_loader, cu_.class_linker, *cu_.dex_file, nullptr /* code_item not used */,
         0u /* class_def_idx not used */, 0u /* method_index not used */,
-        cu_.access_flags, nullptr /* verified_method not used */));
+        cu_.access_flags, nullptr /* verified_method not used */,
+        NullHandle<mirror::DexCache>()));
     cu_.mir_graph->current_method_ = 0u;
     code_item_ = static_cast<DexFile::CodeItem*>(
         cu_.arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc));