Add VerfiedMethod to DexCompilationUnit.

Avoid some mutex locking and map lookups.

Change-Id: I8e0486af77e38dcd065569572a6b985eb57f4f63
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 3368132..ff8fea0 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -176,8 +176,7 @@
   if (!kEnableCheckCastEllision || !PerformOptimizations()) {
     return inst;
   }
-  MethodReference referrer(&GetDexFile(), unit_.GetDexMethodIndex());
-  if (!driver_.IsSafeCast(referrer, dex_pc)) {
+  if (!driver_.IsSafeCast(&unit_, dex_pc)) {
     return inst;
   }
   // Ok, this is a safe cast. Since the "check-cast" instruction size is 2 code
@@ -272,15 +271,16 @@
 }  // namespace optimizer
 }  // namespace art
 
-extern "C" void ArtCompileDEX(art::CompilerDriver& compiler, const art::DexFile::CodeItem* code_item,
+extern "C" void ArtCompileDEX(art::CompilerDriver& driver, const art::DexFile::CodeItem* code_item,
                   uint32_t access_flags, art::InvokeType invoke_type,
                   uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
                   const art::DexFile& dex_file,
                   art::DexToDexCompilationLevel dex_to_dex_compilation_level) {
   if (dex_to_dex_compilation_level != art::kDontDexToDexCompile) {
     art::DexCompilationUnit unit(NULL, class_loader, art::Runtime::Current()->GetClassLinker(),
-                                 dex_file, code_item, class_def_idx, method_idx, access_flags);
-    art::optimizer::DexCompiler dex_compiler(compiler, unit, dex_to_dex_compilation_level);
+                                 dex_file, code_item, class_def_idx, method_idx, access_flags,
+                                 driver.GetVerifiedMethod(&dex_file, method_idx));
+    art::optimizer::DexCompiler dex_compiler(driver, unit, dex_to_dex_compilation_level);
     dex_compiler.Compile();
   }
 }
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 8c90edb..9dbb341 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -529,7 +529,8 @@
   current_offset_ = 0;
   // TODO: will need to snapshot stack image and use that as the mir context identification.
   m_units_.push_back(new DexCompilationUnit(cu_, class_loader, Runtime::Current()->GetClassLinker(),
-                     dex_file, current_code_item_, class_def_idx, method_idx, access_flags));
+                     dex_file, current_code_item_, class_def_idx, method_idx, access_flags,
+                     cu_->compiler_driver->GetVerifiedMethod(&dex_file, method_idx)));
   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/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index cb36813..7f19ea1 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -22,6 +22,7 @@
 #include "dex/quick/dex_file_method_inliner.h"
 #include "dex/quick/dex_file_to_method_inliner_map.h"
 #include "dex/verification_results.h"
+#include "dex/verified_method.h"
 #include "verifier/dex_gc_map.h"
 #include "verifier/method_verifier.h"
 
@@ -763,10 +764,10 @@
     }
   }
   MethodReference method_ref(cu_->dex_file, cu_->method_idx);
-  const std::vector<uint8_t>* gc_map_raw =
-      cu_->compiler_driver->GetVerificationResults()->GetDexGcMap(method_ref);
-  verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[0]);
-  DCHECK_EQ(gc_map_raw->size(), dex_gc_map.RawSize());
+  const std::vector<uint8_t>& gc_map_raw =
+      mir_graph_->GetCurrentDexCompilationUnit()->GetVerifiedMethod()->GetDexGcMap();
+  verifier::DexPcToReferenceMap dex_gc_map(&(gc_map_raw)[0]);
+  DCHECK_EQ(gc_map_raw.size(), dex_gc_map.RawSize());
   // Compute native offset to references size.
   NativePcToReferenceMapBuilder native_gc_map_builder(&native_gc_map_,
                                                       mapping_table.PcToDexSize(),
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index d8b9869..746c1db 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -1133,8 +1133,7 @@
   // Note: currently type_known_final is unused, as optimizing will only improve the performance
   // of the exception throw path.
   DexCompilationUnit* cu = mir_graph_->GetCurrentDexCompilationUnit();
-  const MethodReference mr(cu->GetDexFile(), cu->GetDexMethodIndex());
-  if (!needs_access_check && cu_->compiler_driver->IsSafeCast(mr, insn_idx)) {
+  if (!needs_access_check && cu_->compiler_driver->IsSafeCast(cu, insn_idx)) {
     // Verifier type analysis proved this check cast would never cause an exception.
     return;
   }
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 0a470a5..1f4122d 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -342,8 +342,8 @@
       bool is_safe = is_null;  // Always safe to store null.
       if (!is_safe) {
         // Check safety from verifier type information.
-        const MethodReference mr(cu_->dex_file, cu_->method_idx);
-        is_safe = cu_->compiler_driver->IsSafeCast(mr, mir->offset);
+        const DexCompilationUnit* unit = mir_graph_->GetCurrentDexCompilationUnit();
+        is_safe = cu_->compiler_driver->IsSafeCast(unit, mir->offset);
       }
       if (is_null || is_safe) {
         // Store of constant null doesn't require an assignability test and can be generated inline
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
index 8b4fa1a..edccec5 100644
--- a/compiler/dex/verification_results.cc
+++ b/compiler/dex/verification_results.cc
@@ -79,24 +79,6 @@
   return (it != verified_methods_.end()) ? it->second : nullptr;
 }
 
-const std::vector<uint8_t>* VerificationResults::GetDexGcMap(MethodReference ref) {
-  const VerifiedMethod* verified_method = GetVerifiedMethod(ref);
-  CHECK(verified_method != nullptr)
-    << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file);
-  return &verified_method->GetDexGcMap();
-}
-
-const MethodReference* VerificationResults::GetDevirtMap(const MethodReference& ref,
-                                                                    uint32_t dex_pc) {
-  const VerifiedMethod* verified_method = GetVerifiedMethod(ref);
-  return (verified_method != nullptr) ? verified_method->GetDevirtTarget(dex_pc) : nullptr;
-}
-
-bool VerificationResults::IsSafeCast(MethodReference ref, uint32_t pc) {
-  const VerifiedMethod* verified_method = GetVerifiedMethod(ref);
-  return (verified_method != nullptr) && (verified_method->IsSafeCast(pc));
-}
-
 void VerificationResults::AddRejectedClass(ClassReference ref) {
   {
     WriterMutexLock mu(Thread::Current(), rejected_classes_lock_);
diff --git a/compiler/dex/verification_results.h b/compiler/dex/verification_results.h
index e9cdb53..2eb0713 100644
--- a/compiler/dex/verification_results.h
+++ b/compiler/dex/verification_results.h
@@ -47,16 +47,6 @@
     const VerifiedMethod* GetVerifiedMethod(MethodReference ref)
         LOCKS_EXCLUDED(verified_methods_lock_);
 
-    const std::vector<uint8_t>* GetDexGcMap(MethodReference ref)
-        LOCKS_EXCLUDED(verified_methods_lock_);
-
-    const MethodReference* GetDevirtMap(const MethodReference& ref, uint32_t dex_pc)
-        LOCKS_EXCLUDED(verified_methods_lock_);
-
-    // Returns true if the cast can statically be verified to be redundant
-    // by using the check-cast elision peephole optimization in the verifier.
-    bool IsSafeCast(MethodReference ref, uint32_t pc) LOCKS_EXCLUDED(safecast_map_lock_);
-
     void AddRejectedClass(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_);
     bool IsClassRejected(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_);
 
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index f84e01f..d504a4e 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -28,6 +28,7 @@
 #include "dex_compilation_unit.h"
 #include "dex_file-inl.h"
 #include "dex/verification_results.h"
+#include "dex/verified_method.h"
 #include "jni_internal.h"
 #include "object_utils.h"
 #include "runtime.h"
@@ -1272,9 +1273,9 @@
         if (enableVerifierBasedSharpening && (*invoke_type == kVirtual ||
                                               *invoke_type == kInterface)) {
           // Did the verifier record a more precise invoke target based on its type information?
-          const MethodReference caller_method(mUnit->GetDexFile(), mUnit->GetDexMethodIndex());
+          DCHECK(mUnit->GetVerifiedMethod() != nullptr);
           const MethodReference* devirt_map_target =
-              verification_results_->GetDevirtMap(caller_method, dex_pc);
+              mUnit->GetVerifiedMethod()->GetDevirtTarget(dex_pc);
           if (devirt_map_target != NULL) {
             SirtRef<mirror::DexCache> target_dex_cache(soa.Self(), mUnit->GetClassLinker()->FindDexCache(*devirt_map_target->dex_file));
             SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()));
@@ -1321,8 +1322,15 @@
   return false;  // Incomplete knowledge needs slow path.
 }
 
-bool CompilerDriver::IsSafeCast(const MethodReference& mr, uint32_t dex_pc) {
-  bool result = verification_results_->IsSafeCast(mr, dex_pc);
+const VerifiedMethod* CompilerDriver::GetVerifiedMethod(const DexFile* dex_file,
+                                                        uint32_t method_idx) const {
+  MethodReference ref(dex_file, method_idx);
+  return verification_results_->GetVerifiedMethod(ref);
+}
+
+bool CompilerDriver::IsSafeCast(const DexCompilationUnit* mUnit, uint32_t dex_pc) {
+  DCHECK(mUnit->GetVerifiedMethod() != nullptr);
+  bool result = mUnit->GetVerifiedMethod()->IsSafeCast(dex_pc);
   if (result) {
     stats_->SafeCast();
   } else {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index f8aa868..a8110e7 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -45,6 +45,7 @@
 class OatWriter;
 class TimingLogger;
 class VerificationResults;
+class VerifiedMethod;
 
 enum CompilerBackend {
   kQuick,
@@ -213,7 +214,8 @@
                          uintptr_t* direct_code, uintptr_t* direct_method)
       LOCKS_EXCLUDED(Locks::mutator_lock_);
 
-  bool IsSafeCast(const MethodReference& mr, uint32_t dex_pc);
+  const VerifiedMethod* GetVerifiedMethod(const DexFile* dex_file, uint32_t method_idx) const;
+  bool IsSafeCast(const DexCompilationUnit* mUnit, uint32_t dex_pc);
 
   // Record patch information for later fix up.
   void AddCodePatch(const DexFile* dex_file,
diff --git a/compiler/driver/dex_compilation_unit.cc b/compiler/driver/dex_compilation_unit.cc
index c441d09..840b0ad 100644
--- a/compiler/driver/dex_compilation_unit.cc
+++ b/compiler/driver/dex_compilation_unit.cc
@@ -31,7 +31,8 @@
       code_item_(cu->code_item),
       class_def_idx_(cu->class_def_idx),
       dex_method_idx_(cu->method_idx),
-      access_flags_(cu->access_flags) {
+      access_flags_(cu->access_flags),
+      verified_method_(cu_->compiler_driver->GetVerifiedMethod(cu->dex_file, cu->method_idx)) {
 }
 
 DexCompilationUnit::DexCompilationUnit(CompilationUnit* cu,
@@ -41,7 +42,8 @@
                                        const DexFile::CodeItem* code_item,
                                        uint16_t class_def_idx,
                                        uint32_t method_idx,
-                                       uint32_t access_flags)
+                                       uint32_t access_flags,
+                                       const VerifiedMethod* verified_method)
     : cu_(cu),
       class_loader_(class_loader),
       class_linker_(class_linker),
@@ -49,7 +51,8 @@
       code_item_(code_item),
       class_def_idx_(class_def_idx),
       dex_method_idx_(method_idx),
-      access_flags_(access_flags) {
+      access_flags_(access_flags),
+      verified_method_(verified_method) {
 }
 
 const std::string& DexCompilationUnit::GetSymbol() {
diff --git a/compiler/driver/dex_compilation_unit.h b/compiler/driver/dex_compilation_unit.h
index 3df50ff..84f5799 100644
--- a/compiler/driver/dex_compilation_unit.h
+++ b/compiler/driver/dex_compilation_unit.h
@@ -29,6 +29,7 @@
 }  // namespace mirror
 class ClassLinker;
 struct CompilationUnit;
+class VerifiedMethod;
 
 class DexCompilationUnit {
  public:
@@ -36,7 +37,8 @@
 
   DexCompilationUnit(CompilationUnit* cu, jobject class_loader, ClassLinker* class_linker,
                      const DexFile& dex_file, const DexFile::CodeItem* code_item,
-                     uint16_t class_def_idx, uint32_t method_idx, uint32_t access_flags);
+                     uint16_t class_def_idx, uint32_t method_idx, uint32_t access_flags,
+                     const VerifiedMethod* verified_method);
 
   CompilationUnit* GetCompilationUnit() const {
     return cu_;
@@ -96,6 +98,10 @@
     return ((access_flags_ & kAccSynchronized) != 0);
   }
 
+  const VerifiedMethod* GetVerifiedMethod() const {
+    return verified_method_;
+  }
+
   const std::string& GetSymbol();
 
  private:
@@ -111,6 +117,7 @@
   const uint16_t class_def_idx_;
   const uint32_t dex_method_idx_;
   const uint32_t access_flags_;
+  const VerifiedMethod* const verified_method_;
 
   std::string symbol_;
 };
diff --git a/compiler/llvm/compiler_llvm.cc b/compiler/llvm/compiler_llvm.cc
index 8f996fa..94408bb 100644
--- a/compiler/llvm/compiler_llvm.cc
+++ b/compiler/llvm/compiler_llvm.cc
@@ -21,6 +21,7 @@
 #include "class_linker.h"
 #include "compiled_method.h"
 #include "dex/verification_results.h"
+#include "dex/verified_method.h"
 #include "driver/compiler_driver.h"
 #include "driver/dex_compilation_unit.h"
 #include "globals.h"
@@ -153,11 +154,9 @@
 
   cunit->Materialize();
 
-  MethodReference mref(dex_compilation_unit->GetDexFile(),
-                       dex_compilation_unit->GetDexMethodIndex());
   return new CompiledMethod(*compiler_driver_, compiler_driver_->GetInstructionSet(),
                             cunit->GetElfObject(),
-                            *compiler_driver_->GetVerificationResults()->GetDexGcMap(mref),
+                            dex_compilation_unit->GetVerifiedMethod()->GetDexGcMap(),
                             cunit->GetDexCompilationUnit()->GetSymbol());
 }
 
@@ -214,7 +213,7 @@
 
   art::DexCompilationUnit dex_compilation_unit(
     NULL, class_loader, class_linker, dex_file, code_item,
-    class_def_idx, method_idx, access_flags);
+    class_def_idx, method_idx, access_flags, driver.GetVerifiedMethod(&dex_file, method_idx));
   art::llvm::CompilerLLVM* compiler_llvm = ContextOf(driver);
   art::CompiledMethod* result = compiler_llvm->CompileDexMethod(&dex_compilation_unit, invoke_type);
   return result;
@@ -226,8 +225,8 @@
   art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
 
   art::DexCompilationUnit dex_compilation_unit(
-    NULL, NULL, class_linker, dex_file, NULL,
-    0, method_idx, access_flags);
+      nullptr, nullptr, class_linker, dex_file, nullptr,
+      0, method_idx, access_flags, nullptr);
 
   art::llvm::CompilerLLVM* compiler_llvm = ContextOf(driver);
   art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&dex_compilation_unit);