ART: Wire up DexToDexCompiler without extern

The extern declaration actually had the wrong signature, a parameter
was missing, and we never noticed.

Remove the function field and extern. Add a header for the compiler.
Use the header file.

Change-Id: Ia4d4dd86211da6045709a45c7bf8430471d1b62b
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 3947078..4944915 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -171,6 +171,7 @@
   dex/quick/mips/mips_lir.h \
   dex/quick/resource_mask.h \
   dex/compiler_enums.h \
+  dex/dex_to_dex_compiler.h \
   dex/global_value_numbering.h \
   dex/pass_me.h \
   driver/compiler_driver.h \
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 4b56b69..603130a 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "dex_to_dex_compiler.h"
+
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "base/logging.h"
@@ -65,7 +67,7 @@
   }
 
   bool PerformOptimizations() const {
-    return dex_to_dex_compilation_level_ >= kOptimize;
+    return dex_to_dex_compilation_level_ >= DexToDexCompilationLevel::kOptimize;
   }
 
   // Compiles a RETURN-VOID into a RETURN-VOID-BARRIER within a constructor where
@@ -108,7 +110,7 @@
 };
 
 void DexCompiler::Compile() {
-  DCHECK_GE(dex_to_dex_compilation_level_, kRequired);
+  DCHECK_GE(dex_to_dex_compilation_level_, DexToDexCompilationLevel::kRequired);
   const DexFile::CodeItem* code_item = unit_.GetCodeItem();
   const uint16_t* insns = code_item->insns_;
   const uint32_t insns_size = code_item->insns_size_in_code_units_;
@@ -310,21 +312,22 @@
   }
 }
 
-extern "C" CompiledMethod* ArtCompileDEX(
-    art::CompilerDriver& driver,
-    const art::DexFile::CodeItem* code_item,
+CompiledMethod* ArtCompileDEX(
+    CompilerDriver* driver,
+    const DexFile::CodeItem* code_item,
     uint32_t access_flags,
-    art::InvokeType invoke_type ATTRIBUTE_UNUSED,
+    InvokeType invoke_type ATTRIBUTE_UNUSED,
     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) {
+    const DexFile& dex_file,
+    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(),
                                  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);
+                                 driver->GetVerifiedMethod(&dex_file, method_idx));
+    art::optimizer::DexCompiler dex_compiler(*driver, unit, dex_to_dex_compilation_level);
     dex_compiler.Compile();
     if (dex_compiler.GetQuickenedInfo().empty()) {
       // No need to create a CompiledMethod if there are no quickened opcodes.
@@ -337,13 +340,13 @@
       builder.PushBackUnsigned(info.dex_pc);
       builder.PushBackUnsigned(info.dex_member_index);
     }
-    InstructionSet instruction_set = driver.GetInstructionSet();
+    InstructionSet instruction_set = driver->GetInstructionSet();
     if (instruction_set == kThumb2) {
       // Don't use the thumb2 instruction set to avoid the one off code delta.
       instruction_set = kArm;
     }
     return CompiledMethod::SwapAllocCompiledMethod(
-        &driver,
+        driver,
         instruction_set,
         ArrayRef<const uint8_t>(),                   // no code
         0,
diff --git a/compiler/dex/dex_to_dex_compiler.h b/compiler/dex/dex_to_dex_compiler.h
new file mode 100644
index 0000000..3fad6d4
--- /dev/null
+++ b/compiler/dex/dex_to_dex_compiler.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_DEX_DEX_TO_DEX_COMPILER_H_
+#define ART_COMPILER_DEX_DEX_TO_DEX_COMPILER_H_
+
+#include "jni.h"
+
+#include "dex_file.h"
+#include "invoke_type.h"
+
+namespace art {
+
+class CompiledMethod;
+class CompilerDriver;
+
+namespace optimizer {
+
+enum class DexToDexCompilationLevel {
+  kDontDexToDexCompile,   // Only meaning wrt image time interpretation.
+  kRequired,              // Dex-to-dex compilation required for correctness.
+  kOptimize               // Perform required transformation and peep-hole optimizations.
+};
+std::ostream& operator<<(std::ostream& os, const DexToDexCompilationLevel& rhs);
+
+CompiledMethod* ArtCompileDEX(CompilerDriver* driver,
+                              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,
+                              DexToDexCompilationLevel dex_to_dex_compilation_level);
+
+}  // namespace optimizer
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_DEX_TO_DEX_COMPILER_H_
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index affa52a..299b995 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -39,6 +39,7 @@
 #include "compiler_driver-inl.h"
 #include "dex_compilation_unit.h"
 #include "dex_file-inl.h"
+#include "dex/dex_to_dex_compiler.h"
 #include "dex/verification_results.h"
 #include "dex/verified_method.h"
 #include "dex/quick/dex_file_method_inliner.h"
@@ -334,16 +335,6 @@
   DISALLOW_COPY_AND_ASSIGN(AOTCompilationStats);
 };
 
-
-extern "C" art::CompiledMethod* ArtCompileDEX(art::CompilerDriver& compiler,
-                                              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);
-
 CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
                                VerificationResults* verification_results,
                                DexFileToMethodInlinerMap* method_inliner_map,
@@ -394,8 +385,6 @@
   DCHECK(verification_results_ != nullptr);
   DCHECK(method_inliner_map_ != nullptr);
 
-  dex_to_dex_compiler_ = reinterpret_cast<DexToDexCompilerFn>(ArtCompileDEX);
-
   compiler_->Init();
 
   CHECK_EQ(image_, image_classes_.get() != nullptr);
@@ -508,13 +497,14 @@
   }
 }
 
-DexToDexCompilationLevel CompilerDriver::GetDexToDexCompilationlevel(
-    Thread* self, Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file,
-    const DexFile::ClassDef& class_def) {
+static optimizer::DexToDexCompilationLevel GetDexToDexCompilationLevel(
+    Thread* self, const CompilerDriver& driver, Handle<mirror::ClassLoader> class_loader,
+    const DexFile& dex_file, const DexFile::ClassDef& class_def)
+    SHARED_REQUIRES(Locks::mutator_lock_) {
   auto* const runtime = Runtime::Current();
-  if (runtime->UseJit() || GetCompilerOptions().VerifyAtRuntime()) {
+  if (runtime->UseJit() || driver.GetCompilerOptions().VerifyAtRuntime()) {
     // Verify at runtime shouldn't dex to dex since we didn't resolve of verify.
-    return kDontDexToDexCompile;
+    return optimizer::DexToDexCompilationLevel::kDontDexToDexCompile;
   }
   const char* descriptor = dex_file.GetClassDescriptor(class_def);
   ClassLinker* class_linker = runtime->GetClassLinker();
@@ -522,7 +512,7 @@
   if (klass == nullptr) {
     CHECK(self->IsExceptionPending());
     self->ClearException();
-    return kDontDexToDexCompile;
+    return optimizer::DexToDexCompilationLevel::kDontDexToDexCompile;
   }
   // DexToDex at the kOptimize level may introduce quickened opcodes, which replace symbolic
   // references with actual offsets. We cannot re-verify such instructions.
@@ -532,14 +522,142 @@
   // optimize when a class has been fully verified before.
   if (klass->IsVerified()) {
     // Class is verified so we can enable DEX-to-DEX compilation for performance.
-    return kOptimize;
+    return optimizer::DexToDexCompilationLevel::kOptimize;
   } else if (klass->IsCompileTimeVerified()) {
     // Class verification has soft-failed. Anyway, ensure at least correctness.
     DCHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime);
-    return kRequired;
+    return optimizer::DexToDexCompilationLevel::kRequired;
   } else {
     // Class verification has failed: do not run DEX-to-DEX compilation.
-    return kDontDexToDexCompile;
+    return optimizer::DexToDexCompilationLevel::kDontDexToDexCompile;
+  }
+}
+
+static optimizer::DexToDexCompilationLevel GetDexToDexCompilationLevel(
+    Thread* self,
+    const CompilerDriver& driver,
+    jobject jclass_loader,
+    const DexFile& dex_file,
+    const DexFile::ClassDef& class_def) {
+  ScopedObjectAccess soa(self);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::ClassLoader> class_loader(
+      hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+  return GetDexToDexCompilationLevel(self, driver, class_loader, dex_file, class_def);
+}
+
+// Does the runtime for the InstructionSet provide an implementation returned by
+// GetQuickGenericJniStub allowing down calls that aren't compiled using a JNI compiler?
+static bool InstructionSetHasGenericJniStub(InstructionSet isa) {
+  switch (isa) {
+    case kArm:
+    case kArm64:
+    case kThumb2:
+    case kMips:
+    case kMips64:
+    case kX86:
+    case kX86_64: return true;
+    default: return false;
+  }
+}
+
+static void CompileMethod(Thread* self,
+                          CompilerDriver* driver,
+                          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,
+                          optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level,
+                          bool compilation_enabled)
+    REQUIRES(!driver->compiled_methods_lock_) {
+  DCHECK(driver != nullptr);
+  CompiledMethod* compiled_method = nullptr;
+  uint64_t start_ns = kTimeCompileMethod ? NanoTime() : 0;
+  MethodReference method_ref(&dex_file, method_idx);
+
+  if ((access_flags & kAccNative) != 0) {
+    // Are we interpreting only and have support for generic JNI down calls?
+    if (!driver->GetCompilerOptions().IsCompilationEnabled() &&
+        InstructionSetHasGenericJniStub(driver->GetInstructionSet())) {
+      // Leaving this empty will trigger the generic JNI version
+    } else {
+      compiled_method = driver->GetCompiler()->JniCompile(access_flags, method_idx, dex_file);
+      CHECK(compiled_method != nullptr);
+    }
+  } else if ((access_flags & kAccAbstract) != 0) {
+    // Abstract methods don't have code.
+  } else {
+    bool has_verified_method = driver->GetVerificationResults()
+        ->GetVerifiedMethod(method_ref) != nullptr;
+    bool compile = compilation_enabled &&
+        // Basic checks, e.g., not <clinit>.
+        driver->GetVerificationResults()
+            ->IsCandidateForCompilation(method_ref, access_flags) &&
+        // Did not fail to create VerifiedMethod metadata.
+        has_verified_method &&
+        // Is eligable for compilation by methods-to-compile filter.
+        driver->IsMethodToCompile(method_ref);
+    if (compile) {
+      // NOTE: if compiler declines to compile this method, it will return null.
+      compiled_method = driver->GetCompiler()->Compile(code_item, access_flags, invoke_type,
+                                                       class_def_idx, method_idx, class_loader,
+                                                       dex_file);
+    }
+    if (compiled_method == nullptr &&
+        dex_to_dex_compilation_level != optimizer::DexToDexCompilationLevel::kDontDexToDexCompile) {
+      // TODO: add a command-line option to disable DEX-to-DEX compilation ?
+      // Do not optimize if a VerifiedMethod is missing. SafeCast elision, for example, relies on
+      // it.
+      compiled_method = optimizer::ArtCompileDEX(
+          driver,
+          code_item,
+          access_flags,
+          invoke_type,
+          class_def_idx,
+          method_idx,
+          class_loader,
+          dex_file,
+          has_verified_method
+              ? dex_to_dex_compilation_level
+              : optimizer::DexToDexCompilationLevel::kRequired);
+    }
+  }
+  if (kTimeCompileMethod) {
+    uint64_t duration_ns = NanoTime() - start_ns;
+    if (duration_ns > MsToNs(driver->GetCompiler()->GetMaximumCompilationTimeBeforeWarning())) {
+      LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
+                   << " took " << PrettyDuration(duration_ns);
+    }
+  }
+
+  if (compiled_method != nullptr) {
+    // Count non-relative linker patches.
+    size_t non_relative_linker_patch_count = 0u;
+    for (const LinkerPatch& patch : compiled_method->GetPatches()) {
+      if (!patch.IsPcRelative()) {
+        ++non_relative_linker_patch_count;
+      }
+    }
+    bool compile_pic = driver->GetCompilerOptions().GetCompilePic();  // Off by default
+    // When compiling with PIC, there should be zero non-relative linker patches
+    CHECK(!compile_pic || non_relative_linker_patch_count == 0u);
+
+    driver->AddCompiledMethod(method_ref, compiled_method, non_relative_linker_patch_count);
+  }
+
+  // Done compiling, delete the verified method to reduce native memory usage. Do not delete in
+  // optimizing compiler, which may need the verified method again for inlining.
+  if (driver->GetCompilerKind() != Compiler::kOptimizing) {
+    driver->GetVerificationResults()->RemoveVerifiedMethod(method_ref);
+  }
+
+  if (self->IsExceptionPending()) {
+    ScopedObjectAccess soa(self);
+    LOG(FATAL) << "Unexpected exception compiling: " << PrettyMethod(method_idx, dex_file) << "\n"
+        << self->GetException()->Dump();
   }
 }
 
@@ -570,24 +688,30 @@
   PreCompile(jclass_loader, dex_files, thread_pool.get(), timings);
 
   // Can we run DEX-to-DEX compiler on this class ?
-  DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile;
-  {
-    ScopedObjectAccess soa(self);
-    const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
-    StackHandleScope<1> hs(soa.Self());
-    Handle<mirror::ClassLoader> class_loader(
-        hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
-    dex_to_dex_compilation_level = GetDexToDexCompilationlevel(self, class_loader, *dex_file,
-                                                               class_def);
-  }
-  CompileMethod(self, code_item, access_flags, invoke_type, class_def_idx, method_idx,
-                jclass_loader, *dex_file, dex_to_dex_compilation_level, true);
+  optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level =
+      GetDexToDexCompilationLevel(self,
+                                  *this,
+                                  jclass_loader,
+                                  *dex_file,
+                                  dex_file->GetClassDef(class_def_idx));
+
+  CompileMethod(self,
+                this,
+                code_item,
+                access_flags,
+                invoke_type,
+                class_def_idx,
+                method_idx,
+                jclass_loader,
+                *dex_file,
+                dex_to_dex_compilation_level,
+                true);
 
   self->GetJniEnv()->DeleteGlobalRef(jclass_loader);
   self->TransitionFromSuspendedToRunnable();
 }
 
-CompiledMethod* CompilerDriver::CompileMethod(Thread* self, ArtMethod* method) {
+CompiledMethod* CompilerDriver::CompileArtMethod(Thread* self, ArtMethod* method) {
   const uint32_t method_idx = method->GetDexMethodIndex();
   const uint32_t access_flags = method->GetAccessFlags();
   const InvokeType invoke_type = method->GetInvokeType();
@@ -598,12 +722,21 @@
   const DexFile* dex_file = method->GetDexFile();
   const uint16_t class_def_idx = method->GetClassDefIndex();
   const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
-  DexToDexCompilationLevel dex_to_dex_compilation_level =
-      GetDexToDexCompilationlevel(self, class_loader, *dex_file, class_def);
+  optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level =
+      GetDexToDexCompilationLevel(self, *this, class_loader, *dex_file, class_def);
   const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
   self->TransitionFromRunnableToSuspended(kNative);
-  CompileMethod(self, code_item, access_flags, invoke_type, class_def_idx, method_idx,
-                jclass_loader, *dex_file, dex_to_dex_compilation_level, true);
+  CompileMethod(self,
+                this,
+                code_item,
+                access_flags,
+                invoke_type,
+                class_def_idx,
+                method_idx,
+                jclass_loader,
+                *dex_file,
+                dex_to_dex_compilation_level,
+                true);
   auto* compiled_method = GetCompiledMethod(MethodReference(dex_file, method_idx));
   self->TransitionFromSuspendedToRunnable();
   return compiled_method;
@@ -2237,15 +2370,9 @@
     CompilerDriver* const driver = manager_->GetCompiler();
 
     // Can we run DEX-to-DEX compiler on this class ?
-    DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile;
-    {
-      ScopedObjectAccess soa(self);
-      StackHandleScope<1> hs(soa.Self());
-      Handle<mirror::ClassLoader> class_loader(
-          hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
-      dex_to_dex_compilation_level = driver->GetDexToDexCompilationlevel(
-          soa.Self(), class_loader, dex_file, class_def);
-    }
+    optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level =
+        GetDexToDexCompilationLevel(self, *driver, jclass_loader, dex_file, class_def);
+
     ClassDataItemIterator it(dex_file, class_data);
     // Skip fields
     while (it.HasNextStaticField()) {
@@ -2269,10 +2396,10 @@
         continue;
       }
       previous_direct_method_idx = method_idx;
-      driver->CompileMethod(self, it.GetMethodCodeItem(), it.GetMethodAccessFlags(),
-                            it.GetMethodInvokeType(class_def), class_def_index,
-                            method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level,
-                            compilation_enabled);
+      CompileMethod(self, driver, it.GetMethodCodeItem(), it.GetMethodAccessFlags(),
+                    it.GetMethodInvokeType(class_def), class_def_index,
+                    method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level,
+                    compilation_enabled);
       it.Next();
     }
     // Compile virtual methods
@@ -2286,10 +2413,10 @@
         continue;
       }
       previous_virtual_method_idx = method_idx;
-      driver->CompileMethod(self, it.GetMethodCodeItem(), it.GetMethodAccessFlags(),
-                            it.GetMethodInvokeType(class_def), class_def_index,
-                            method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level,
-                            compilation_enabled);
+      CompileMethod(self, driver, it.GetMethodCodeItem(), it.GetMethodAccessFlags(),
+                    it.GetMethodInvokeType(class_def), class_def_index,
+                    method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level,
+                    compilation_enabled);
       it.Next();
     }
     DCHECK(!it.HasNext());
@@ -2309,112 +2436,18 @@
   context.ForAll(0, dex_file.NumClassDefs(), &visitor, thread_count_);
 }
 
-// Does the runtime for the InstructionSet provide an implementation returned by
-// GetQuickGenericJniStub allowing down calls that aren't compiled using a JNI compiler?
-static bool InstructionSetHasGenericJniStub(InstructionSet isa) {
-  switch (isa) {
-    case kArm:
-    case kArm64:
-    case kThumb2:
-    case kMips:
-    case kMips64:
-    case kX86:
-    case kX86_64: return true;
-    default: return false;
+void CompilerDriver::AddCompiledMethod(const MethodReference& method_ref,
+                                       CompiledMethod* const compiled_method,
+                                       size_t non_relative_linker_patch_count) {
+  DCHECK(GetCompiledMethod(method_ref) == nullptr)
+      << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file);
+  {
+    MutexLock mu(Thread::Current(), compiled_methods_lock_);
+    compiled_methods_.Put(method_ref, compiled_method);
+    non_relative_linker_patch_count_ += non_relative_linker_patch_count;
   }
-}
-
-void CompilerDriver::CompileMethod(Thread* self, 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,
-                                   DexToDexCompilationLevel dex_to_dex_compilation_level,
-                                   bool compilation_enabled) {
-  CompiledMethod* compiled_method = nullptr;
-  uint64_t start_ns = kTimeCompileMethod ? NanoTime() : 0;
-  MethodReference method_ref(&dex_file, method_idx);
-
-  if ((access_flags & kAccNative) != 0) {
-    // Are we interpreting only and have support for generic JNI down calls?
-    if (!compiler_options_->IsCompilationEnabled() &&
-        InstructionSetHasGenericJniStub(instruction_set_)) {
-      // Leaving this empty will trigger the generic JNI version
-    } else {
-      compiled_method = compiler_->JniCompile(access_flags, method_idx, dex_file);
-      CHECK(compiled_method != nullptr);
-    }
-  } else if ((access_flags & kAccAbstract) != 0) {
-    // Abstract methods don't have code.
-  } else {
-    bool has_verified_method = verification_results_->GetVerifiedMethod(method_ref) != nullptr;
-    bool compile = compilation_enabled &&
-                   // Basic checks, e.g., not <clinit>.
-                   verification_results_->IsCandidateForCompilation(method_ref, access_flags) &&
-                   // Did not fail to create VerifiedMethod metadata.
-                   has_verified_method &&
-                   // Is eligable for compilation by methods-to-compile filter.
-                   IsMethodToCompile(method_ref);
-    if (compile) {
-      // NOTE: if compiler declines to compile this method, it will return null.
-      compiled_method = compiler_->Compile(code_item, access_flags, invoke_type, class_def_idx,
-                                           method_idx, class_loader, dex_file);
-    }
-    if (compiled_method == nullptr && dex_to_dex_compilation_level != kDontDexToDexCompile) {
-      // TODO: add a command-line option to disable DEX-to-DEX compilation ?
-      // Do not optimize if a VerifiedMethod is missing. SafeCast elision, for example, relies on
-      // it.
-      compiled_method = (*dex_to_dex_compiler_)(
-          *this,
-          code_item,
-          access_flags,
-          invoke_type,
-          class_def_idx,
-          method_idx,
-          class_loader,
-          dex_file,
-          has_verified_method ? dex_to_dex_compilation_level : kRequired);
-    }
-  }
-  if (kTimeCompileMethod) {
-    uint64_t duration_ns = NanoTime() - start_ns;
-    if (duration_ns > MsToNs(compiler_->GetMaximumCompilationTimeBeforeWarning())) {
-      LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
-                   << " took " << PrettyDuration(duration_ns);
-    }
-  }
-
-  if (compiled_method != nullptr) {
-    // Count non-relative linker patches.
-    size_t non_relative_linker_patch_count = 0u;
-    for (const LinkerPatch& patch : compiled_method->GetPatches()) {
-      if (!patch.IsPcRelative()) {
-        ++non_relative_linker_patch_count;
-      }
-    }
-    bool compile_pic = GetCompilerOptions().GetCompilePic();  // Off by default
-    // When compiling with PIC, there should be zero non-relative linker patches
-    CHECK(!compile_pic || non_relative_linker_patch_count == 0u);
-
-    DCHECK(GetCompiledMethod(method_ref) == nullptr) << PrettyMethod(method_idx, dex_file);
-    {
-      MutexLock mu(self, compiled_methods_lock_);
-      compiled_methods_.Put(method_ref, compiled_method);
-      non_relative_linker_patch_count_ += non_relative_linker_patch_count;
-    }
-    DCHECK(GetCompiledMethod(method_ref) != nullptr) << PrettyMethod(method_idx, dex_file);
-  }
-
-  // Done compiling, delete the verified method to reduce native memory usage. Do not delete in
-  // optimizing compiler, which may need the verified method again for inlining.
-  if (compiler_kind_ != Compiler::kOptimizing) {
-    verification_results_->RemoveVerifiedMethod(method_ref);
-  }
-
-  if (self->IsExceptionPending()) {
-    ScopedObjectAccess soa(self);
-    LOG(FATAL) << "Unexpected exception compiling: " << PrettyMethod(method_idx, dex_file) << "\n"
-        << self->GetException()->Dump();
-  }
+  DCHECK(GetCompiledMethod(method_ref) != nullptr)
+      << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file);
 }
 
 void CompilerDriver::RemoveCompiledMethod(const MethodReference& method_ref) {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 88e03a2..4de9c73 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -80,13 +80,6 @@
   kQuickAbi
 };
 
-enum DexToDexCompilationLevel {
-  kDontDexToDexCompile,   // Only meaning wrt image time interpretation.
-  kRequired,              // Dex-to-dex compilation required for correctness.
-  kOptimize               // Perform required transformation and peep-hole optimizations.
-};
-std::ostream& operator<<(std::ostream& os, const DexToDexCompilationLevel& rhs);
-
 static constexpr bool kUseMurmur3Hash = true;
 
 class CompilerDriver {
@@ -116,7 +109,7 @@
                   TimingLogger* timings)
       REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);
 
-  CompiledMethod* CompileMethod(Thread* self, ArtMethod*)
+  CompiledMethod* CompileArtMethod(Thread* self, ArtMethod*)
       SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!compiled_methods_lock_) WARN_UNUSED;
 
   // Compile a single Method.
@@ -185,6 +178,11 @@
   size_t GetNonRelativeLinkerPatchCount() const
       REQUIRES(!compiled_methods_lock_);
 
+  // Add a compiled method.
+  void AddCompiledMethod(const MethodReference& method_ref,
+                         CompiledMethod* const compiled_method,
+                         size_t non_relative_linker_patch_count)
+      REQUIRES(!compiled_methods_lock_);
   // Remove and delete a compiled method.
   void RemoveCompiledMethod(const MethodReference& method_ref) REQUIRES(!compiled_methods_lock_);
 
@@ -476,6 +474,10 @@
     had_hard_verifier_failure_ = true;
   }
 
+  Compiler::Kind GetCompilerKind() {
+    return compiler_kind_;
+  }
+
  private:
   // Return whether the declaring class of `resolved_member` is
   // available to `referrer_class` for read or write access using two
@@ -546,10 +548,6 @@
       SHARED_REQUIRES(Locks::mutator_lock_);
 
  private:
-  DexToDexCompilationLevel GetDexToDexCompilationlevel(
-      Thread* self, Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file,
-      const DexFile::ClassDef& class_def) SHARED_REQUIRES(Locks::mutator_lock_);
-
   void PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files,
                   ThreadPool* thread_pool, TimingLogger* timings)
       REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);
@@ -599,12 +597,6 @@
                       const std::vector<const DexFile*>& dex_files,
                       ThreadPool* thread_pool, TimingLogger* timings)
       REQUIRES(!Locks::mutator_lock_);
-  void CompileMethod(Thread* self, 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,
-                     DexToDexCompilationLevel dex_to_dex_compilation_level,
-                     bool compilation_enabled)
-      REQUIRES(!compiled_methods_lock_);
 
   // Swap pool and allocator used for native allocations. May be file-backed. Needs to be first
   // as other fields rely on this.
@@ -634,8 +626,13 @@
   ClassTable compiled_classes_ GUARDED_BY(compiled_classes_lock_);
 
   typedef SafeMap<const MethodReference, CompiledMethod*, MethodReferenceComparator> MethodTable;
-  // All method references that this compiler has compiled.
+
+ public:
+  // Lock is public so that non-members can have lock annotations.
   mutable Mutex compiled_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+
+ private:
+  // All method references that this compiler has compiled.
   MethodTable compiled_methods_ GUARDED_BY(compiled_methods_lock_);
   // Number of non-relative patches in all compiled methods. These patches need space
   // in the .oat_patches ELF section if requested in the compiler options.
@@ -675,15 +672,6 @@
   typedef void (*CompilerCallbackFn)(CompilerDriver& driver);
   typedef MutexLock* (*CompilerMutexLockFn)(CompilerDriver& driver);
 
-  typedef CompiledMethod* (*DexToDexCompilerFn)(
-      CompilerDriver& driver,
-      const DexFile::CodeItem* code_item,
-      uint32_t access_flags, InvokeType invoke_type,
-      uint32_t class_dex_idx, uint32_t method_idx,
-      jobject class_loader, const DexFile& dex_file,
-      DexToDexCompilationLevel dex_to_dex_compilation_level);
-  DexToDexCompilerFn dex_to_dex_compiler_;
-
   void* compiler_context_;
 
   bool support_boot_image_fixup_;
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index c95bac2..4215f3c 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -153,7 +153,7 @@
   CompiledMethod* compiled_method = nullptr;
   {
     TimingLogger::ScopedTiming t2("Compiling", &logger);
-    compiled_method = compiler_driver_->CompileMethod(self, method);
+    compiled_method = compiler_driver_->CompileArtMethod(self, method);
   }
   {
     TimingLogger::ScopedTiming t2("TrimMaps", &logger);