Merge "ART: Clean up compiler"
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 5c5163d..6e48bdf 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -48,6 +48,7 @@
 	dex/quick/mips/target_mips.cc \
 	dex/quick/mips/utility_mips.cc \
 	dex/quick/mir_to_lir.cc \
+	dex/quick/quick_compiler.cc \
 	dex/quick/ralloc_util.cc \
 	dex/quick/resource_mask.cc \
 	dex/quick/x86/assemble_x86.cc \
@@ -62,6 +63,7 @@
 	dex/mir_method_info.cc \
 	dex/mir_optimization.cc \
 	dex/bb_optimizations.cc \
+	dex/compiler_ir.cc \
 	dex/post_opt_passes.cc \
 	dex/pass_driver_me_opts.cc \
 	dex/pass_driver_me_post_opt.cc \
@@ -82,6 +84,7 @@
 	jni/quick/x86_64/calling_convention_x86_64.cc \
 	jni/quick/calling_convention.cc \
 	jni/quick/jni_compiler.cc \
+	llvm/llvm_compiler.cc \
 	optimizing/builder.cc \
 	optimizing/code_generator.cc \
 	optimizing/code_generator_arm.cc \
@@ -116,7 +119,6 @@
 	utils/x86_64/managed_register_x86_64.cc \
 	utils/scoped_arena_allocator.cc \
 	buffered_output_stream.cc \
-	compilers.cc \
 	compiler.cc \
 	elf_fixup.cc \
 	elf_patcher.cc \
diff --git a/compiler/compiler.cc b/compiler/compiler.cc
index a832c31..fbfd8e6 100644
--- a/compiler/compiler.cc
+++ b/compiler/compiler.cc
@@ -15,14 +15,12 @@
  */
 
 #include "compiler.h"
-#include "compilers.h"
-#include "driver/compiler_driver.h"
-#include "mirror/art_method-inl.h"
 
-#ifdef ART_USE_PORTABLE_COMPILER
-#include "dex/portable/mir_to_gbc.h"
-#include "elf_writer_mclinker.h"
-#endif
+#include "base/logging.h"
+#include "dex/quick/quick_compiler.h"
+#include "driver/compiler_driver.h"
+#include "llvm/llvm_compiler.h"
+#include "optimizing/optimizing_compiler.h"
 
 namespace art {
 
@@ -60,137 +58,21 @@
   return nullptr;
 }
 
-
-#ifdef ART_USE_PORTABLE_COMPILER
-
-extern "C" void ArtInitCompilerContext(art::CompilerDriver* driver);
-
-extern "C" void ArtUnInitCompilerContext(art::CompilerDriver* driver);
-
-extern "C" art::CompiledMethod* ArtCompileMethod(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);
-
-extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver* driver,
-                                                        uint32_t access_flags, uint32_t method_idx,
-                                                        const art::DexFile& dex_file);
-
-extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver* driver,
-                                               std::string const& filename);
-
-
-class LLVMCompiler FINAL : public Compiler {
- public:
-  explicit LLVMCompiler(CompilerDriver* driver) : Compiler(driver, 1000) {}
-
-  void Init() const OVERRIDE {
-    ArtInitCompilerContext(GetCompilerDriver());
-  }
-
-  void UnInit() const OVERRIDE {
-    ArtUnInitCompilerContext(GetCompilerDriver());
-  }
-
-  CompiledMethod* Compile(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) const OVERRIDE {
-    CompiledMethod* method = TryCompileWithSeaIR(code_item,
-                                                 access_flags,
-                                                 invoke_type,
-                                                 class_def_idx,
-                                                 method_idx,
-                                                 class_loader,
-                                                 dex_file);
-    if (method != nullptr) {
-      return method;
-    }
-
-    return ArtCompileMethod(GetCompilerDriver(),
-                            code_item,
-                            access_flags,
-                            invoke_type,
-                            class_def_idx,
-                            method_idx,
-                            class_loader,
-                            dex_file);
-  }
-
-  CompiledMethod* JniCompile(uint32_t access_flags,
-                             uint32_t method_idx,
-                             const DexFile& dex_file) const OVERRIDE {
-    return ArtLLVMJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
-  }
-
-  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
-    return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
-  }
-
-  bool WriteElf(art::File* file,
-                OatWriter* oat_writer,
-                const std::vector<const art::DexFile*>& dex_files,
-                const std::string& android_root,
-                bool is_host, const CompilerDriver& driver) const
-      OVERRIDE
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return art::ElfWriterMclinker::Create(
-        file, oat_writer, dex_files, android_root, is_host, driver);
-  }
-
-  Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
-    return PortableCodeGenerator(
-        cu, cu->mir_graph.get(), &cu->arena,
-        reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
-  }
-
-  void InitCompilationUnit(CompilationUnit& cu) const {
-      // Fused long branches not currently useful in bitcode.
-    cu.disable_opt |=
-        (1 << kBranchFusing) |
-        (1 << kSuppressExceptionEdges);
-  }
-
-  bool IsPortable() const OVERRIDE {
-    return true;
-  }
-
-  void SetBitcodeFileName(const CompilerDriver& driver, const std::string& filename) {
-    typedef void (*SetBitcodeFileNameFn)(const CompilerDriver&, const std::string&);
-
-    SetBitcodeFileNameFn set_bitcode_file_name =
-      reinterpret_cast<SetBitcodeFileNameFn>(compilerLLVMSetBitcodeFileName);
-
-    set_bitcode_file_name(driver, filename);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LLVMCompiler);
-};
-#endif
-
 Compiler* Compiler::Create(CompilerDriver* driver, Compiler::Kind kind) {
   switch (kind) {
     case kQuick:
-      return new QuickCompiler(driver);
-      break;
+      return CreateQuickCompiler(driver);
+
     case kOptimizing:
-      return new OptimizingCompiler(driver);
-      break;
+      return CreateOptimizingCompiler(driver);
+
     case kPortable:
-#ifdef ART_USE_PORTABLE_COMPILER
-      return new LLVMCompiler(driver);
-#else
-      LOG(FATAL) << "Portable compiler not compiled";
-#endif
-      break;
+      {
+        Compiler* compiler = CreateLLVMCompiler(driver);
+        CHECK(compiler != nullptr) << "Portable compiler not compiled";
+        return compiler;
+      }
+
     default:
       LOG(FATAL) << "UNREACHABLE";
   }
diff --git a/compiler/compiler.h b/compiler/compiler.h
index 4caebf3..05fa858 100644
--- a/compiler/compiler.h
+++ b/compiler/compiler.h
@@ -26,13 +26,19 @@
 struct CompilationUnit;
 class CompilerDriver;
 class CompiledMethod;
-class MIRGraph;
 class OatWriter;
 
 namespace mirror {
   class ArtMethod;
 }
 
+// Base class for compiler-specific thread-local storage for compiler worker threads
+class CompilerTls {
+  public:
+    CompilerTls() {}
+    ~CompilerTls() {}
+};
+
 class Compiler {
  public:
   enum Kind {
@@ -47,6 +53,9 @@
 
   virtual void UnInit() const = 0;
 
+  virtual bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, CompilationUnit* cu)
+      const = 0;
+
   virtual CompiledMethod* Compile(const DexFile::CodeItem* code_item,
                                   uint32_t access_flags,
                                   InvokeType invoke_type,
@@ -109,6 +118,10 @@
     return nullptr;
   }
 
+  virtual CompilerTls* CreateNewCompilerTls() {
+    return nullptr;
+  }
+
  protected:
   explicit Compiler(CompilerDriver* driver, uint64_t warning) :
       driver_(driver), maximum_compilation_time_before_warning_(warning) {
diff --git a/compiler/compilers.cc b/compiler/compilers.cc
deleted file mode 100644
index 5cf846f..0000000
--- a/compiler/compilers.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include "compilers.h"
-
-#include "dex/mir_graph.h"
-#include "dex/quick/mir_to_lir.h"
-#include "elf_writer_quick.h"
-#include "mirror/art_method-inl.h"
-
-namespace art {
-
-extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver* driver);
-extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver* driver);
-extern "C" art::CompiledMethod* ArtQuickCompileMethod(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);
-
-extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver* driver,
-                                                         uint32_t access_flags, uint32_t method_idx,
-                                                         const art::DexFile& dex_file);
-
-void QuickCompiler::Init() const {
-  ArtInitQuickCompilerContext(GetCompilerDriver());
-}
-
-void QuickCompiler::UnInit() const {
-  ArtUnInitQuickCompilerContext(GetCompilerDriver());
-}
-
-CompiledMethod* QuickCompiler::Compile(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) const {
-  CompiledMethod* method = TryCompileWithSeaIR(code_item,
-                                               access_flags,
-                                               invoke_type,
-                                               class_def_idx,
-                                               method_idx,
-                                               class_loader,
-                                               dex_file);
-  if (method != nullptr) {
-    return method;
-  }
-
-  return ArtQuickCompileMethod(GetCompilerDriver(),
-                               code_item,
-                               access_flags,
-                               invoke_type,
-                               class_def_idx,
-                               method_idx,
-                               class_loader,
-                               dex_file);
-}
-
-CompiledMethod* QuickCompiler::JniCompile(uint32_t access_flags,
-                                          uint32_t method_idx,
-                                          const DexFile& dex_file) const {
-  return ArtQuickJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
-}
-
-uintptr_t QuickCompiler::GetEntryPointOf(mirror::ArtMethod* method) const {
-  return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
-}
-
-bool QuickCompiler::WriteElf(art::File* file,
-                             OatWriter* oat_writer,
-                             const std::vector<const art::DexFile*>& dex_files,
-                             const std::string& android_root,
-                             bool is_host) const {
-  return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host,
-                                     *GetCompilerDriver());
-}
-
-Backend* QuickCompiler::GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
-  Mir2Lir* mir_to_lir = nullptr;
-  switch (cu->instruction_set) {
-    case kThumb2:
-      mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
-      break;
-    case kArm64:
-      mir_to_lir = Arm64CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
-      break;
-    case kMips:
-      mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
-      break;
-    case kX86:
-      // Fall-through.
-    case kX86_64:
-      mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
-      break;
-    default:
-      LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
-  }
-
-  /* The number of compiler temporaries depends on backend so set it up now if possible */
-  if (mir_to_lir) {
-    size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps();
-    bool set_max = cu->mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps);
-    CHECK(set_max);
-  }
-  return mir_to_lir;
-}
-
-CompiledMethod* OptimizingCompiler::Compile(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) const {
-  CompiledMethod* method = TryCompile(code_item, access_flags, invoke_type, class_def_idx,
-                                      method_idx, class_loader, dex_file);
-  if (method != nullptr) {
-    return method;
-  }
-
-  return QuickCompiler::Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx,
-                                class_loader, dex_file);
-}
-
-}  // namespace art
diff --git a/compiler/compilers.h b/compiler/compilers.h
deleted file mode 100644
index 151bf6f..0000000
--- a/compiler/compilers.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2014 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_COMPILERS_H_
-#define ART_COMPILER_COMPILERS_H_
-
-#include "compiler.h"
-
-namespace art {
-
-class QuickCompiler : public Compiler {
- public:
-  explicit QuickCompiler(CompilerDriver* driver) : Compiler(driver, 100) {}
-
-  void Init() const OVERRIDE;
-
-  void UnInit() const OVERRIDE;
-
-  CompiledMethod* Compile(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) const OVERRIDE;
-
-  CompiledMethod* JniCompile(uint32_t access_flags,
-                             uint32_t method_idx,
-                             const DexFile& dex_file) const OVERRIDE;
-
-  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const OVERRIDE
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  bool WriteElf(art::File* file,
-                OatWriter* oat_writer,
-                const std::vector<const art::DexFile*>& dex_files,
-                const std::string& android_root,
-                bool is_host) const
-    OVERRIDE
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const OVERRIDE;
-
-  void InitCompilationUnit(CompilationUnit& cu) const OVERRIDE {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuickCompiler);
-};
-
-class OptimizingCompiler FINAL : public QuickCompiler {
- public:
-  explicit OptimizingCompiler(CompilerDriver* driver);
-
-  CompiledMethod* Compile(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) const OVERRIDE;
-
-  CompiledMethod* TryCompile(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) const;
-
- private:
-  std::unique_ptr<std::ostream> visualizer_output_;
-
-  DISALLOW_COPY_AND_ASSIGN(OptimizingCompiler);
-};
-
-}  // namespace art
-
-#endif  // ART_COMPILER_COMPILERS_H_
diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h
index 7395324..4d6cdf6 100644
--- a/compiler/dex/bb_optimizations.h
+++ b/compiler/dex/bb_optimizations.h
@@ -17,6 +17,7 @@
 #ifndef ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
 #define ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
 
+#include "base/casts.h"
 #include "compiler_internals.h"
 #include "pass_me.h"
 
diff --git a/compiler/dex/compiler_internals.h b/compiler/dex/compiler_internals.h
index 9dd0272..2019f0b 100644
--- a/compiler/dex/compiler_internals.h
+++ b/compiler/dex/compiler_internals.h
@@ -23,14 +23,9 @@
 #include <stdio.h>
 
 #include "base/logging.h"
-#include "class_linker.h"
-#include "driver/compiler_driver.h"
-#include "quick/mir_to_lir.h"
 #include "mir_graph.h"
 #include "compiler_ir.h"
-#include "frontend.h"
-#include "monitor.h"
-#include "thread.h"
+#include "frontend.h"  // Debug flags.
 #include "utils.h"
 
 #endif  // ART_COMPILER_DEX_COMPILER_INTERNALS_H_
diff --git a/compiler/dex/compiler_ir.cc b/compiler/dex/compiler_ir.cc
new file mode 100644
index 0000000..7a5b114
--- /dev/null
+++ b/compiler/dex/compiler_ir.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "compiler_ir.h"
+
+#include "backend.h"
+#include "frontend.h"
+#include "mir_graph.h"
+
+namespace art {
+
+CompilationUnit::CompilationUnit(ArenaPool* pool)
+  : compiler_driver(nullptr),
+    class_linker(nullptr),
+    dex_file(nullptr),
+    class_loader(nullptr),
+    class_def_idx(0),
+    method_idx(0),
+    code_item(nullptr),
+    access_flags(0),
+    invoke_type(kDirect),
+    shorty(nullptr),
+    disable_opt(0),
+    enable_debug(0),
+    verbose(false),
+    compiler(nullptr),
+    instruction_set(kNone),
+    target64(false),
+    num_dalvik_registers(0),
+    insns(nullptr),
+    num_ins(0),
+    num_outs(0),
+    num_regs(0),
+    compiler_flip_match(false),
+    arena(pool),
+    arena_stack(pool),
+    mir_graph(nullptr),
+    cg(nullptr),
+    timings("QuickCompiler", true, false),
+    print_pass(false) {
+}
+
+CompilationUnit::~CompilationUnit() {
+}
+
+void CompilationUnit::StartTimingSplit(const char* label) {
+  if (compiler_driver->GetDumpPasses()) {
+    timings.StartTiming(label);
+  }
+}
+
+void CompilationUnit::NewTimingSplit(const char* label) {
+  if (compiler_driver->GetDumpPasses()) {
+    timings.EndTiming();
+    timings.StartTiming(label);
+  }
+}
+
+void CompilationUnit::EndTiming() {
+  if (compiler_driver->GetDumpPasses()) {
+    timings.EndTiming();
+    if (enable_debug & (1 << kDebugTimings)) {
+      LOG(INFO) << "TIMINGS " << PrettyMethod(method_idx, *dex_file);
+      LOG(INFO) << Dumpable<TimingLogger>(timings);
+    }
+  }
+}
+
+}  // namespace art
diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h
index 66fb608..67bf88a 100644
--- a/compiler/dex/compiler_ir.h
+++ b/compiler/dex/compiler_ir.h
@@ -20,22 +20,24 @@
 #include <vector>
 
 #include "compiler_enums.h"
-#include "dex/quick/mir_to_lir.h"
-#include "dex_instruction.h"
 #include "driver/compiler_driver.h"
-#include "driver/dex_compilation_unit.h"
-#include "safe_map.h"
 #include "utils/scoped_arena_allocator.h"
 #include "base/timing_logger.h"
 #include "utils/arena_allocator.h"
 
 namespace art {
 
-struct ArenaMemBlock;
 class Backend;
-struct Memstats;
+class ClassLinker;
 class MIRGraph;
-class Mir2Lir;
+
+/*
+ * TODO: refactoring pass to move these (and other) typedefs towards usage style of runtime to
+ * add type safety (see runtime/offsets.h).
+ */
+typedef uint32_t DexOffset;          // Dex offset in code units.
+typedef uint16_t NarrowDexOffset;    // For use in structs, Dex offsets range from 0 .. 0xffff.
+typedef uint32_t CodeOffset;         // Native code offset in bytes.
 
 struct CompilationUnit {
   explicit CompilationUnit(ArenaPool* pool);
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index c44a116..078ddf1 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
+#include "frontend.h"
+
 #include <cstdint>
 
+#include "backend.h"
 #include "compiler.h"
 #include "compiler_internals.h"
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
-#include "dataflow_iterator-inl.h"
-#include "leb128.h"
 #include "mirror/object.h"
 #include "pass_driver_me_opts.h"
 #include "runtime.h"
@@ -32,14 +33,6 @@
 
 namespace art {
 
-extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver* driver) {
-  CHECK(driver->GetCompilerContext() == nullptr);
-}
-
-extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver* driver) {
-  CHECK(driver->GetCompilerContext() == nullptr);
-}
-
 /* Default optimizer/debug setting for the compiler. */
 static uint32_t kCompilerOptimizerDisableFlags = 0 |  // Disable specific optimizations
   // (1 << kLoadStoreElimination) |
@@ -81,542 +74,8 @@
   // (1 << kDebugCodegenDump) |
   0;
 
-COMPILE_ASSERT(0U == static_cast<size_t>(kNone), kNone_not_0);
-COMPILE_ASSERT(1U == static_cast<size_t>(kArm), kArm_not_1);
-COMPILE_ASSERT(2U == static_cast<size_t>(kArm64), kArm64_not_2);
-COMPILE_ASSERT(3U == static_cast<size_t>(kThumb2), kThumb2_not_3);
-COMPILE_ASSERT(4U == static_cast<size_t>(kX86), kX86_not_4);
-COMPILE_ASSERT(5U == static_cast<size_t>(kX86_64), kX86_64_not_5);
-COMPILE_ASSERT(6U == static_cast<size_t>(kMips), kMips_not_6);
-COMPILE_ASSERT(7U == static_cast<size_t>(kMips64), kMips64_not_7);
-
-// Additional disabled optimizations (over generally disabled) per instruction set.
-static constexpr uint32_t kDisabledOptimizationsPerISA[] = {
-    // 0 = kNone.
-    ~0U,
-    // 1 = kArm, unused (will use kThumb2).
-    ~0U,
-    // 2 = kArm64.
-    0,
-    // 3 = kThumb2.
-    0,
-    // 4 = kX86.
-    (1 << kLoadStoreElimination) |
-    0,
-    // 5 = kX86_64.
-    (1 << kLoadStoreElimination) |
-    0,
-    // 6 = kMips.
-    (1 << kLoadStoreElimination) |
-    (1 << kLoadHoisting) |
-    (1 << kSuppressLoads) |
-    (1 << kNullCheckElimination) |
-    (1 << kPromoteRegs) |
-    (1 << kTrackLiveTemps) |
-    (1 << kSafeOptimizations) |
-    (1 << kBBOpt) |
-    (1 << kMatch) |
-    (1 << kPromoteCompilerTemps) |
-    0,
-    // 7 = kMips64.
-    ~0U
-};
-COMPILE_ASSERT(sizeof(kDisabledOptimizationsPerISA) == 8 * sizeof(uint32_t), kDisabledOpts_unexp);
-
-// Supported shorty types per instruction set. nullptr means that all are available.
-// Z : boolean
-// B : byte
-// S : short
-// C : char
-// I : int
-// J : long
-// F : float
-// D : double
-// L : reference(object, array)
-// V : void
-static const char* kSupportedTypes[] = {
-    // 0 = kNone.
-    "",
-    // 1 = kArm, unused (will use kThumb2).
-    "",
-    // 2 = kArm64.
-    nullptr,
-    // 3 = kThumb2.
-    nullptr,
-    // 4 = kX86.
-    nullptr,
-    // 5 = kX86_64.
-    nullptr,
-    // 6 = kMips.
-    nullptr,
-    // 7 = kMips64.
-    ""
-};
-COMPILE_ASSERT(sizeof(kSupportedTypes) == 8 * sizeof(char*), kSupportedTypes_unexp);
-
-static int kAllOpcodes[] = {
-    Instruction::NOP,
-    Instruction::MOVE,
-    Instruction::MOVE_FROM16,
-    Instruction::MOVE_16,
-    Instruction::MOVE_WIDE,
-    Instruction::MOVE_WIDE_FROM16,
-    Instruction::MOVE_WIDE_16,
-    Instruction::MOVE_OBJECT,
-    Instruction::MOVE_OBJECT_FROM16,
-    Instruction::MOVE_OBJECT_16,
-    Instruction::MOVE_RESULT,
-    Instruction::MOVE_RESULT_WIDE,
-    Instruction::MOVE_RESULT_OBJECT,
-    Instruction::MOVE_EXCEPTION,
-    Instruction::RETURN_VOID,
-    Instruction::RETURN,
-    Instruction::RETURN_WIDE,
-    Instruction::RETURN_OBJECT,
-    Instruction::CONST_4,
-    Instruction::CONST_16,
-    Instruction::CONST,
-    Instruction::CONST_HIGH16,
-    Instruction::CONST_WIDE_16,
-    Instruction::CONST_WIDE_32,
-    Instruction::CONST_WIDE,
-    Instruction::CONST_WIDE_HIGH16,
-    Instruction::CONST_STRING,
-    Instruction::CONST_STRING_JUMBO,
-    Instruction::CONST_CLASS,
-    Instruction::MONITOR_ENTER,
-    Instruction::MONITOR_EXIT,
-    Instruction::CHECK_CAST,
-    Instruction::INSTANCE_OF,
-    Instruction::ARRAY_LENGTH,
-    Instruction::NEW_INSTANCE,
-    Instruction::NEW_ARRAY,
-    Instruction::FILLED_NEW_ARRAY,
-    Instruction::FILLED_NEW_ARRAY_RANGE,
-    Instruction::FILL_ARRAY_DATA,
-    Instruction::THROW,
-    Instruction::GOTO,
-    Instruction::GOTO_16,
-    Instruction::GOTO_32,
-    Instruction::PACKED_SWITCH,
-    Instruction::SPARSE_SWITCH,
-    Instruction::CMPL_FLOAT,
-    Instruction::CMPG_FLOAT,
-    Instruction::CMPL_DOUBLE,
-    Instruction::CMPG_DOUBLE,
-    Instruction::CMP_LONG,
-    Instruction::IF_EQ,
-    Instruction::IF_NE,
-    Instruction::IF_LT,
-    Instruction::IF_GE,
-    Instruction::IF_GT,
-    Instruction::IF_LE,
-    Instruction::IF_EQZ,
-    Instruction::IF_NEZ,
-    Instruction::IF_LTZ,
-    Instruction::IF_GEZ,
-    Instruction::IF_GTZ,
-    Instruction::IF_LEZ,
-    Instruction::UNUSED_3E,
-    Instruction::UNUSED_3F,
-    Instruction::UNUSED_40,
-    Instruction::UNUSED_41,
-    Instruction::UNUSED_42,
-    Instruction::UNUSED_43,
-    Instruction::AGET,
-    Instruction::AGET_WIDE,
-    Instruction::AGET_OBJECT,
-    Instruction::AGET_BOOLEAN,
-    Instruction::AGET_BYTE,
-    Instruction::AGET_CHAR,
-    Instruction::AGET_SHORT,
-    Instruction::APUT,
-    Instruction::APUT_WIDE,
-    Instruction::APUT_OBJECT,
-    Instruction::APUT_BOOLEAN,
-    Instruction::APUT_BYTE,
-    Instruction::APUT_CHAR,
-    Instruction::APUT_SHORT,
-    Instruction::IGET,
-    Instruction::IGET_WIDE,
-    Instruction::IGET_OBJECT,
-    Instruction::IGET_BOOLEAN,
-    Instruction::IGET_BYTE,
-    Instruction::IGET_CHAR,
-    Instruction::IGET_SHORT,
-    Instruction::IPUT,
-    Instruction::IPUT_WIDE,
-    Instruction::IPUT_OBJECT,
-    Instruction::IPUT_BOOLEAN,
-    Instruction::IPUT_BYTE,
-    Instruction::IPUT_CHAR,
-    Instruction::IPUT_SHORT,
-    Instruction::SGET,
-    Instruction::SGET_WIDE,
-    Instruction::SGET_OBJECT,
-    Instruction::SGET_BOOLEAN,
-    Instruction::SGET_BYTE,
-    Instruction::SGET_CHAR,
-    Instruction::SGET_SHORT,
-    Instruction::SPUT,
-    Instruction::SPUT_WIDE,
-    Instruction::SPUT_OBJECT,
-    Instruction::SPUT_BOOLEAN,
-    Instruction::SPUT_BYTE,
-    Instruction::SPUT_CHAR,
-    Instruction::SPUT_SHORT,
-    Instruction::INVOKE_VIRTUAL,
-    Instruction::INVOKE_SUPER,
-    Instruction::INVOKE_DIRECT,
-    Instruction::INVOKE_STATIC,
-    Instruction::INVOKE_INTERFACE,
-    Instruction::RETURN_VOID_BARRIER,
-    Instruction::INVOKE_VIRTUAL_RANGE,
-    Instruction::INVOKE_SUPER_RANGE,
-    Instruction::INVOKE_DIRECT_RANGE,
-    Instruction::INVOKE_STATIC_RANGE,
-    Instruction::INVOKE_INTERFACE_RANGE,
-    Instruction::UNUSED_79,
-    Instruction::UNUSED_7A,
-    Instruction::NEG_INT,
-    Instruction::NOT_INT,
-    Instruction::NEG_LONG,
-    Instruction::NOT_LONG,
-    Instruction::NEG_FLOAT,
-    Instruction::NEG_DOUBLE,
-    Instruction::INT_TO_LONG,
-    Instruction::INT_TO_FLOAT,
-    Instruction::INT_TO_DOUBLE,
-    Instruction::LONG_TO_INT,
-    Instruction::LONG_TO_FLOAT,
-    Instruction::LONG_TO_DOUBLE,
-    Instruction::FLOAT_TO_INT,
-    Instruction::FLOAT_TO_LONG,
-    Instruction::FLOAT_TO_DOUBLE,
-    Instruction::DOUBLE_TO_INT,
-    Instruction::DOUBLE_TO_LONG,
-    Instruction::DOUBLE_TO_FLOAT,
-    Instruction::INT_TO_BYTE,
-    Instruction::INT_TO_CHAR,
-    Instruction::INT_TO_SHORT,
-    Instruction::ADD_INT,
-    Instruction::SUB_INT,
-    Instruction::MUL_INT,
-    Instruction::DIV_INT,
-    Instruction::REM_INT,
-    Instruction::AND_INT,
-    Instruction::OR_INT,
-    Instruction::XOR_INT,
-    Instruction::SHL_INT,
-    Instruction::SHR_INT,
-    Instruction::USHR_INT,
-    Instruction::ADD_LONG,
-    Instruction::SUB_LONG,
-    Instruction::MUL_LONG,
-    Instruction::DIV_LONG,
-    Instruction::REM_LONG,
-    Instruction::AND_LONG,
-    Instruction::OR_LONG,
-    Instruction::XOR_LONG,
-    Instruction::SHL_LONG,
-    Instruction::SHR_LONG,
-    Instruction::USHR_LONG,
-    Instruction::ADD_FLOAT,
-    Instruction::SUB_FLOAT,
-    Instruction::MUL_FLOAT,
-    Instruction::DIV_FLOAT,
-    Instruction::REM_FLOAT,
-    Instruction::ADD_DOUBLE,
-    Instruction::SUB_DOUBLE,
-    Instruction::MUL_DOUBLE,
-    Instruction::DIV_DOUBLE,
-    Instruction::REM_DOUBLE,
-    Instruction::ADD_INT_2ADDR,
-    Instruction::SUB_INT_2ADDR,
-    Instruction::MUL_INT_2ADDR,
-    Instruction::DIV_INT_2ADDR,
-    Instruction::REM_INT_2ADDR,
-    Instruction::AND_INT_2ADDR,
-    Instruction::OR_INT_2ADDR,
-    Instruction::XOR_INT_2ADDR,
-    Instruction::SHL_INT_2ADDR,
-    Instruction::SHR_INT_2ADDR,
-    Instruction::USHR_INT_2ADDR,
-    Instruction::ADD_LONG_2ADDR,
-    Instruction::SUB_LONG_2ADDR,
-    Instruction::MUL_LONG_2ADDR,
-    Instruction::DIV_LONG_2ADDR,
-    Instruction::REM_LONG_2ADDR,
-    Instruction::AND_LONG_2ADDR,
-    Instruction::OR_LONG_2ADDR,
-    Instruction::XOR_LONG_2ADDR,
-    Instruction::SHL_LONG_2ADDR,
-    Instruction::SHR_LONG_2ADDR,
-    Instruction::USHR_LONG_2ADDR,
-    Instruction::ADD_FLOAT_2ADDR,
-    Instruction::SUB_FLOAT_2ADDR,
-    Instruction::MUL_FLOAT_2ADDR,
-    Instruction::DIV_FLOAT_2ADDR,
-    Instruction::REM_FLOAT_2ADDR,
-    Instruction::ADD_DOUBLE_2ADDR,
-    Instruction::SUB_DOUBLE_2ADDR,
-    Instruction::MUL_DOUBLE_2ADDR,
-    Instruction::DIV_DOUBLE_2ADDR,
-    Instruction::REM_DOUBLE_2ADDR,
-    Instruction::ADD_INT_LIT16,
-    Instruction::RSUB_INT,
-    Instruction::MUL_INT_LIT16,
-    Instruction::DIV_INT_LIT16,
-    Instruction::REM_INT_LIT16,
-    Instruction::AND_INT_LIT16,
-    Instruction::OR_INT_LIT16,
-    Instruction::XOR_INT_LIT16,
-    Instruction::ADD_INT_LIT8,
-    Instruction::RSUB_INT_LIT8,
-    Instruction::MUL_INT_LIT8,
-    Instruction::DIV_INT_LIT8,
-    Instruction::REM_INT_LIT8,
-    Instruction::AND_INT_LIT8,
-    Instruction::OR_INT_LIT8,
-    Instruction::XOR_INT_LIT8,
-    Instruction::SHL_INT_LIT8,
-    Instruction::SHR_INT_LIT8,
-    Instruction::USHR_INT_LIT8,
-    Instruction::IGET_QUICK,
-    Instruction::IGET_WIDE_QUICK,
-    Instruction::IGET_OBJECT_QUICK,
-    Instruction::IPUT_QUICK,
-    Instruction::IPUT_WIDE_QUICK,
-    Instruction::IPUT_OBJECT_QUICK,
-    Instruction::INVOKE_VIRTUAL_QUICK,
-    Instruction::INVOKE_VIRTUAL_RANGE_QUICK,
-    Instruction::UNUSED_EB,
-    Instruction::UNUSED_EC,
-    Instruction::UNUSED_ED,
-    Instruction::UNUSED_EE,
-    Instruction::UNUSED_EF,
-    Instruction::UNUSED_F0,
-    Instruction::UNUSED_F1,
-    Instruction::UNUSED_F2,
-    Instruction::UNUSED_F3,
-    Instruction::UNUSED_F4,
-    Instruction::UNUSED_F5,
-    Instruction::UNUSED_F6,
-    Instruction::UNUSED_F7,
-    Instruction::UNUSED_F8,
-    Instruction::UNUSED_F9,
-    Instruction::UNUSED_FA,
-    Instruction::UNUSED_FB,
-    Instruction::UNUSED_FC,
-    Instruction::UNUSED_FD,
-    Instruction::UNUSED_FE,
-    Instruction::UNUSED_FF,
-    // ----- ExtendedMIROpcode -----
-    kMirOpPhi,
-    kMirOpCopy,
-    kMirOpFusedCmplFloat,
-    kMirOpFusedCmpgFloat,
-    kMirOpFusedCmplDouble,
-    kMirOpFusedCmpgDouble,
-    kMirOpFusedCmpLong,
-    kMirOpNop,
-    kMirOpNullCheck,
-    kMirOpRangeCheck,
-    kMirOpDivZeroCheck,
-    kMirOpCheck,
-    kMirOpCheckPart2,
-    kMirOpSelect,
-};
-
-// Unsupported opcodes. nullptr can be used when everything is supported. Size of the lists is
-// recorded below.
-static const int* kUnsupportedOpcodes[] = {
-    // 0 = kNone.
-    kAllOpcodes,
-    // 1 = kArm, unused (will use kThumb2).
-    kAllOpcodes,
-    // 2 = kArm64.
-    nullptr,
-    // 3 = kThumb2.
-    nullptr,
-    // 4 = kX86.
-    nullptr,
-    // 5 = kX86_64.
-    nullptr,
-    // 6 = kMips.
-    nullptr,
-    // 7 = kMips64.
-    kAllOpcodes
-};
-COMPILE_ASSERT(sizeof(kUnsupportedOpcodes) == 8 * sizeof(int*), kUnsupportedOpcodes_unexp);
-
-// Size of the arrays stored above.
-static const size_t kUnsupportedOpcodesSize[] = {
-    // 0 = kNone.
-    arraysize(kAllOpcodes),
-    // 1 = kArm, unused (will use kThumb2).
-    arraysize(kAllOpcodes),
-    // 2 = kArm64.
-    0,
-    // 3 = kThumb2.
-    0,
-    // 4 = kX86.
-    0,
-    // 5 = kX86_64.
-    0,
-    // 6 = kMips.
-    0,
-    // 7 = kMips64.
-    arraysize(kAllOpcodes),
-};
-COMPILE_ASSERT(sizeof(kUnsupportedOpcodesSize) == 8 * sizeof(size_t),
-               kUnsupportedOpcodesSize_unexp);
-
-// The maximum amount of Dalvik register in a method for which we will start compiling. Tries to
-// avoid an abort when we need to manage more SSA registers than we can.
-static constexpr size_t kMaxAllowedDalvikRegisters = INT16_MAX / 2;
-
-CompilationUnit::CompilationUnit(ArenaPool* pool)
-  : compiler_driver(nullptr),
-    class_linker(nullptr),
-    dex_file(nullptr),
-    class_loader(nullptr),
-    class_def_idx(0),
-    method_idx(0),
-    code_item(nullptr),
-    access_flags(0),
-    invoke_type(kDirect),
-    shorty(nullptr),
-    disable_opt(0),
-    enable_debug(0),
-    verbose(false),
-    compiler(nullptr),
-    instruction_set(kNone),
-    target64(false),
-    num_dalvik_registers(0),
-    insns(nullptr),
-    num_ins(0),
-    num_outs(0),
-    num_regs(0),
-    compiler_flip_match(false),
-    arena(pool),
-    arena_stack(pool),
-    mir_graph(nullptr),
-    cg(nullptr),
-    timings("QuickCompiler", true, false),
-    print_pass(false) {
-}
-
-CompilationUnit::~CompilationUnit() {
-}
-
-void CompilationUnit::StartTimingSplit(const char* label) {
-  if (compiler_driver->GetDumpPasses()) {
-    timings.StartTiming(label);
-  }
-}
-
-void CompilationUnit::NewTimingSplit(const char* label) {
-  if (compiler_driver->GetDumpPasses()) {
-    timings.EndTiming();
-    timings.StartTiming(label);
-  }
-}
-
-void CompilationUnit::EndTiming() {
-  if (compiler_driver->GetDumpPasses()) {
-    timings.EndTiming();
-    if (enable_debug & (1 << kDebugTimings)) {
-      LOG(INFO) << "TIMINGS " << PrettyMethod(method_idx, *dex_file);
-      LOG(INFO) << Dumpable<TimingLogger>(timings);
-    }
-  }
-}
-
-static bool CanCompileShorty(const char* shorty, InstructionSet instruction_set) {
-  const char* supported_types = kSupportedTypes[instruction_set];
-  if (supported_types == nullptr) {
-    // Everything available.
-    return true;
-  }
-
-  uint32_t shorty_size = strlen(shorty);
-  CHECK_GE(shorty_size, 1u);
-
-  for (uint32_t i = 0; i < shorty_size; i++) {
-    if (strchr(supported_types, shorty[i]) == nullptr) {
-      return false;
-    }
-  }
-  return true;
-};
-
-// Skip the method that we do not support currently.
-static bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file,
-                             CompilationUnit& cu) {
-  // This is a limitation in mir_graph. See MirGraph::SetNumSSARegs.
-  if (cu.num_dalvik_registers > kMaxAllowedDalvikRegisters) {
-    VLOG(compiler) << "Too many dalvik registers : " << cu.num_dalvik_registers;
-    return false;
-  }
-
-  // Check whether we do have limitations at all.
-  if (kSupportedTypes[cu.instruction_set] == nullptr &&
-      kUnsupportedOpcodesSize[cu.instruction_set] == 0U) {
-    return true;
-  }
-
-  // Check if we can compile the prototype.
-  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
-  if (!CanCompileShorty(shorty, cu.instruction_set)) {
-    VLOG(compiler) << "Unsupported shorty : " << shorty;
-    return false;
-  }
-
-  const int *unsupport_list = kUnsupportedOpcodes[cu.instruction_set];
-  int unsupport_list_size = kUnsupportedOpcodesSize[cu.instruction_set];
-
-  for (unsigned int idx = 0; idx < cu.mir_graph->GetNumBlocks(); idx++) {
-    BasicBlock* bb = cu.mir_graph->GetBasicBlock(idx);
-    if (bb == NULL) continue;
-    if (bb->block_type == kDead) continue;
-    for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
-      int opcode = mir->dalvikInsn.opcode;
-      // Check if we support the byte code.
-      if (std::find(unsupport_list, unsupport_list + unsupport_list_size,
-                    opcode) != unsupport_list + unsupport_list_size) {
-        if (!MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
-          VLOG(compiler) << "Unsupported dalvik byte code : "
-              << mir->dalvikInsn.opcode;
-        } else {
-          VLOG(compiler) << "Unsupported extended MIR opcode : "
-              << MIRGraph::extended_mir_op_names_[opcode - kMirOpFirst];
-        }
-        return false;
-      }
-      // Check if it invokes a prototype that we cannot support.
-      if (Instruction::INVOKE_VIRTUAL == opcode ||
-          Instruction::INVOKE_SUPER == opcode ||
-          Instruction::INVOKE_DIRECT == opcode ||
-          Instruction::INVOKE_STATIC == opcode ||
-          Instruction::INVOKE_INTERFACE == opcode) {
-        uint32_t invoke_method_idx = mir->dalvikInsn.vB;
-        const char* invoke_method_shorty = dex_file.GetMethodShorty(
-            dex_file.GetMethodId(invoke_method_idx));
-        if (!CanCompileShorty(invoke_method_shorty, cu.instruction_set)) {
-          VLOG(compiler) << "Unsupported to invoke '"
-              << PrettyMethod(invoke_method_idx, dex_file)
-              << "' with shorty : " << invoke_method_shorty;
-          return false;
-        }
-      }
-    }
-  }
-  return true;
-}
-
 static CompiledMethod* CompileMethod(CompilerDriver& driver,
-                                     Compiler* compiler,
+                                     const Compiler* compiler,
                                      const DexFile::CodeItem* code_item,
                                      uint32_t access_flags, InvokeType invoke_type,
                                      uint16_t class_def_idx, uint32_t method_idx,
@@ -687,9 +146,6 @@
 
   compiler->InitCompilationUnit(cu);
 
-  // Disable optimizations according to instruction set.
-  cu.disable_opt |= kDisabledOptimizationsPerISA[cu.instruction_set];
-
   cu.StartTimingSplit("BuildMIRGraph");
   cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena));
 
@@ -709,7 +165,7 @@
   cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx,
                               class_loader, dex_file);
 
-  if (!CanCompileMethod(method_idx, dex_file, cu)) {
+  if (!compiler->CanCompileMethod(method_idx, dex_file, &cu)) {
     VLOG(compiler)  << cu.instruction_set << ": Cannot compile method : "
         << PrettyMethod(method_idx, dex_file);
     return nullptr;
@@ -791,8 +247,8 @@
   return result;
 }
 
-CompiledMethod* CompileOneMethod(CompilerDriver& driver,
-                                 Compiler* compiler,
+CompiledMethod* CompileOneMethod(CompilerDriver* driver,
+                                 const Compiler* compiler,
                                  const DexFile::CodeItem* code_item,
                                  uint32_t access_flags,
                                  InvokeType invoke_type,
@@ -801,22 +257,8 @@
                                  jobject class_loader,
                                  const DexFile& dex_file,
                                  void* compilation_unit) {
-  return CompileMethod(driver, compiler, code_item, access_flags, invoke_type, class_def_idx,
+  return CompileMethod(*driver, compiler, code_item, access_flags, invoke_type, class_def_idx,
                        method_idx, class_loader, dex_file, compilation_unit);
 }
 
 }  // namespace art
-
-extern "C" art::CompiledMethod*
-    ArtQuickCompileMethod(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) {
-  // TODO: check method fingerprint here to determine appropriate backend type.  Until then, use
-  // build default.
-  art::Compiler* compiler = driver.GetCompiler();
-  return art::CompileOneMethod(driver, compiler, code_item, access_flags, invoke_type,
-                               class_def_idx, method_idx, class_loader, dex_file,
-                               NULL /* use thread llvm_info */);
-}
diff --git a/compiler/dex/frontend.h b/compiler/dex/frontend.h
index f4cbdfb..51b6d68 100644
--- a/compiler/dex/frontend.h
+++ b/compiler/dex/frontend.h
@@ -20,16 +20,11 @@
 #include "dex_file.h"
 #include "invoke_type.h"
 
-namespace llvm {
-  class Module;
-  class LLVMContext;
-}
-
 namespace art {
-namespace llvm {
-  class IntrinsicHelper;
-  class IRBuilder;
-}
+
+class CompiledMethod;
+class Compiler;
+class CompilerDriver;
 
 /*
  * Assembly is an iterative process, and usually terminates within
@@ -81,48 +76,17 @@
   kDebugCodegenDump
 };
 
-class LLVMInfo {
-  public:
-    LLVMInfo();
-    ~LLVMInfo();
-
-    ::llvm::LLVMContext* GetLLVMContext() {
-      return llvm_context_.get();
-    }
-
-    ::llvm::Module* GetLLVMModule() {
-      return llvm_module_;
-    }
-
-    art::llvm::IntrinsicHelper* GetIntrinsicHelper() {
-      return intrinsic_helper_.get();
-    }
-
-    art::llvm::IRBuilder* GetIRBuilder() {
-      return ir_builder_.get();
-    }
-
-  private:
-    std::unique_ptr< ::llvm::LLVMContext> llvm_context_;
-    ::llvm::Module* llvm_module_;  // Managed by context_.
-    std::unique_ptr<art::llvm::IntrinsicHelper> intrinsic_helper_;
-    std::unique_ptr<art::llvm::IRBuilder> ir_builder_;
-};
-
-class CompiledMethod;
-class CompilerDriver;
+CompiledMethod* CompileOneMethod(CompilerDriver* driver,
+                                 const Compiler* compiler,
+                                 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* compilation_unit);
 
 }  // namespace art
 
-extern "C" art::CompiledMethod* ArtCompileMethod(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);
-
-
-
 #endif  // ART_COMPILER_DEX_FRONTEND_H_
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 574b6ea..963a586 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -29,6 +29,7 @@
 #include "dex/quick/dex_file_method_inliner.h"
 #include "leb128.h"
 #include "pass_driver_me_post_opt.h"
+#include "stack.h"
 #include "utils/scoped_arena_containers.h"
 
 namespace art {
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 3de4e3d..3d713d4 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -19,9 +19,10 @@
 
 #include <stdint.h>
 
+#include "compiler_ir.h"
 #include "dex_file.h"
 #include "dex_instruction.h"
-#include "compiler_ir.h"
+#include "driver/dex_compilation_unit.h"
 #include "invoke_type.h"
 #include "mir_field_info.h"
 #include "mir_method_info.h"
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index d37e9b6..870edbd 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -22,6 +22,7 @@
 #include "dex/global_value_numbering.h"
 #include "dex/quick/dex_file_method_inliner.h"
 #include "dex/quick/dex_file_to_method_inliner_map.h"
+#include "stack.h"
 #include "utils/scoped_arena_containers.h"
 
 namespace art {
diff --git a/compiler/dex/portable/mir_to_gbc.h b/compiler/dex/portable/mir_to_gbc.h
index e97634c..4459eb6 100644
--- a/compiler/dex/portable/mir_to_gbc.h
+++ b/compiler/dex/portable/mir_to_gbc.h
@@ -32,8 +32,46 @@
 #include "llvm/llvm_compilation_unit.h"
 #include "safe_map.h"
 
+namespace llvm {
+  class Module;
+  class LLVMContext;
+}
+
 namespace art {
 
+namespace llvm {
+  class IntrinsicHelper;
+  class IRBuilder;
+}
+
+class LLVMInfo {
+  public:
+    LLVMInfo();
+    ~LLVMInfo();
+
+    ::llvm::LLVMContext* GetLLVMContext() {
+      return llvm_context_.get();
+    }
+
+    ::llvm::Module* GetLLVMModule() {
+      return llvm_module_;
+    }
+
+    art::llvm::IntrinsicHelper* GetIntrinsicHelper() {
+      return intrinsic_helper_.get();
+    }
+
+    art::llvm::IRBuilder* GetIRBuilder() {
+      return ir_builder_.get();
+    }
+
+  private:
+    std::unique_ptr< ::llvm::LLVMContext> llvm_context_;
+    ::llvm::Module* llvm_module_;  // Managed by context_.
+    std::unique_ptr<art::llvm::IntrinsicHelper> intrinsic_helper_;
+    std::unique_ptr<art::llvm::IRBuilder> ir_builder_;
+};
+
 struct BasicBlock;
 struct CallInfo;
 struct CompilationUnit;
diff --git a/compiler/dex/post_opt_passes.h b/compiler/dex/post_opt_passes.h
index a1b0df4..550d254 100644
--- a/compiler/dex/post_opt_passes.h
+++ b/compiler/dex/post_opt_passes.h
@@ -17,6 +17,7 @@
 #ifndef ART_COMPILER_DEX_POST_OPT_PASSES_H_
 #define ART_COMPILER_DEX_POST_OPT_PASSES_H_
 
+#include "dex/quick/mir_to_lir.h"
 #include "compiler_internals.h"
 #include "pass_me.h"
 
diff --git a/compiler/dex/quick/arm/backend_arm.h b/compiler/dex/quick/arm/backend_arm.h
new file mode 100644
index 0000000..42a9bca
--- /dev/null
+++ b/compiler/dex/quick/arm/backend_arm.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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_QUICK_ARM_BACKEND_ARM_H_
+#define ART_COMPILER_DEX_QUICK_ARM_BACKEND_ARM_H_
+
+namespace art {
+
+struct CompilationUnit;
+class Mir2Lir;
+class MIRGraph;
+class ArenaAllocator;
+
+Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
+                          ArenaAllocator* const arena);
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_QUICK_ARM_BACKEND_ARM_H_
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index cd6c9cc..66a98ba 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -19,6 +19,7 @@
 
 #include "arm_lir.h"
 #include "dex/compiler_internals.h"
+#include "dex/quick/mir_to_lir.h"
 
 namespace art {
 
diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc
index 0509ad3..0be478d 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -20,6 +20,7 @@
 
 #include <string>
 
+#include "backend_arm.h"
 #include "dex/compiler_internals.h"
 #include "dex/quick/mir_to_lir-inl.h"
 
diff --git a/compiler/dex/quick/arm64/backend_arm64.h b/compiler/dex/quick/arm64/backend_arm64.h
new file mode 100644
index 0000000..53650c4
--- /dev/null
+++ b/compiler/dex/quick/arm64/backend_arm64.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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_QUICK_ARM64_BACKEND_ARM64_H_
+#define ART_COMPILER_DEX_QUICK_ARM64_BACKEND_ARM64_H_
+
+namespace art {
+
+struct CompilationUnit;
+class Mir2Lir;
+class MIRGraph;
+class ArenaAllocator;
+
+Mir2Lir* Arm64CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
+                            ArenaAllocator* const arena);
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_QUICK_ARM64_BACKEND_ARM64_H_
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index be10dd7..cc3f90a 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -19,6 +19,7 @@
 
 #include "arm64_lir.h"
 #include "dex/compiler_internals.h"
+#include "dex/quick/mir_to_lir.h"
 
 #include <map>
 
diff --git a/compiler/dex/quick/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc
index 685f8d5..bb21c7f 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -20,6 +20,7 @@
 
 #include <string>
 
+#include "backend_arm64.h"
 #include "dex/compiler_internals.h"
 #include "dex/quick/mir_to_lir-inl.h"
 #include "dex/reg_storage_eq.h"
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 5e0ba15..ffcce7d 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -25,8 +25,10 @@
 #include "thread.h"
 #include "thread-inl.h"
 #include "dex/mir_graph.h"
+#include "dex/quick/mir_to_lir.h"
 #include "dex_instruction.h"
 #include "dex_instruction-inl.h"
+#include "driver/dex_compilation_unit.h"
 #include "verifier/method_verifier.h"
 #include "verifier/method_verifier-inl.h"
 
diff --git a/compiler/dex/quick/mips/backend_mips.h b/compiler/dex/quick/mips/backend_mips.h
new file mode 100644
index 0000000..f65e984
--- /dev/null
+++ b/compiler/dex/quick/mips/backend_mips.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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_QUICK_MIPS_BACKEND_MIPS_H_
+#define ART_COMPILER_DEX_QUICK_MIPS_BACKEND_MIPS_H_
+
+namespace art {
+
+struct CompilationUnit;
+class Mir2Lir;
+class MIRGraph;
+class ArenaAllocator;
+
+Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
+                           ArenaAllocator* const arena);
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_QUICK_MIPS_BACKEND_MIPS_H_
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index 43cbde7..9f1af69 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -18,6 +18,7 @@
 #define ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_
 
 #include "dex/compiler_internals.h"
+#include "dex/quick/mir_to_lir.h"
 #include "mips_lir.h"
 
 namespace art {
diff --git a/compiler/dex/quick/mips/target_mips.cc b/compiler/dex/quick/mips/target_mips.cc
index bc91fbc..9c4426f 100644
--- a/compiler/dex/quick/mips/target_mips.cc
+++ b/compiler/dex/quick/mips/target_mips.cc
@@ -20,6 +20,7 @@
 
 #include <string>
 
+#include "backend_mips.h"
 #include "dex/compiler_internals.h"
 #include "dex/quick/mir_to_lir-inl.h"
 #include "mips_lir.h"
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 8e73728..64ef48d 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -38,14 +38,6 @@
 
 namespace art {
 
-/*
- * TODO: refactoring pass to move these (and other) typdefs towards usage style of runtime to
- * add type safety (see runtime/offsets.h).
- */
-typedef uint32_t DexOffset;          // Dex offset in code units.
-typedef uint16_t NarrowDexOffset;    // For use in structs, Dex offsets range from 0 .. 0xffff.
-typedef uint32_t CodeOffset;         // Native code offset in bytes.
-
 // Set to 1 to measure cost of suspend check.
 #define NO_SUSPEND 0
 
@@ -187,16 +179,6 @@
   int32_t operands[5];           // [0..4] = [dest, src1, src2, extra, extra2].
 };
 
-// Target-specific initialization.
-Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
-                          ArenaAllocator* const arena);
-Mir2Lir* Arm64CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
-                            ArenaAllocator* const arena);
-Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
-                          ArenaAllocator* const arena);
-Mir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
-                          ArenaAllocator* const arena);
-
 // Utility macros to traverse the LIR list.
 #define NEXT_LIR(lir) (lir->next)
 #define PREV_LIR(lir) (lir->prev)
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc
new file mode 100644
index 0000000..4fea1f0
--- /dev/null
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -0,0 +1,650 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "quick_compiler.h"
+
+#include <cstdint>
+
+#include "compiler.h"
+#include "dex/frontend.h"
+#include "dex/mir_graph.h"
+#include "dex/quick/mir_to_lir.h"
+#include "driver/compiler_driver.h"
+#include "elf_writer_quick.h"
+#include "jni/quick/jni_compiler.h"
+#include "mirror/art_method-inl.h"
+#include "base/logging.h"
+
+// Specific compiler backends.
+#include "dex/quick/arm/backend_arm.h"
+#include "dex/quick/arm64/backend_arm64.h"
+#include "dex/quick/mips/backend_mips.h"
+#include "dex/quick/x86/backend_x86.h"
+
+namespace art {
+
+class QuickCompiler : public Compiler {
+ public:
+  explicit QuickCompiler(CompilerDriver* driver) : Compiler(driver, 100) {}
+
+  void Init() const OVERRIDE;
+
+  void UnInit() const OVERRIDE;
+
+  bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, CompilationUnit* cu) const
+      OVERRIDE;
+
+  CompiledMethod* Compile(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) const OVERRIDE;
+
+  CompiledMethod* JniCompile(uint32_t access_flags,
+                             uint32_t method_idx,
+                             const DexFile& dex_file) const OVERRIDE;
+
+  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const OVERRIDE
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  bool WriteElf(art::File* file,
+                OatWriter* oat_writer,
+                const std::vector<const art::DexFile*>& dex_files,
+                const std::string& android_root,
+                bool is_host) const
+    OVERRIDE
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const OVERRIDE;
+
+  void InitCompilationUnit(CompilationUnit& cu) const OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(QuickCompiler);
+};
+
+COMPILE_ASSERT(0U == static_cast<size_t>(kNone), kNone_not_0);
+COMPILE_ASSERT(1U == static_cast<size_t>(kArm), kArm_not_1);
+COMPILE_ASSERT(2U == static_cast<size_t>(kArm64), kArm64_not_2);
+COMPILE_ASSERT(3U == static_cast<size_t>(kThumb2), kThumb2_not_3);
+COMPILE_ASSERT(4U == static_cast<size_t>(kX86), kX86_not_4);
+COMPILE_ASSERT(5U == static_cast<size_t>(kX86_64), kX86_64_not_5);
+COMPILE_ASSERT(6U == static_cast<size_t>(kMips), kMips_not_6);
+COMPILE_ASSERT(7U == static_cast<size_t>(kMips64), kMips64_not_7);
+
+// Additional disabled optimizations (over generally disabled) per instruction set.
+static constexpr uint32_t kDisabledOptimizationsPerISA[] = {
+    // 0 = kNone.
+    ~0U,
+    // 1 = kArm, unused (will use kThumb2).
+    ~0U,
+    // 2 = kArm64.
+    0,
+    // 3 = kThumb2.
+    0,
+    // 4 = kX86.
+    (1 << kLoadStoreElimination) |
+    0,
+    // 5 = kX86_64.
+    (1 << kLoadStoreElimination) |
+    0,
+    // 6 = kMips.
+    (1 << kLoadStoreElimination) |
+    (1 << kLoadHoisting) |
+    (1 << kSuppressLoads) |
+    (1 << kNullCheckElimination) |
+    (1 << kPromoteRegs) |
+    (1 << kTrackLiveTemps) |
+    (1 << kSafeOptimizations) |
+    (1 << kBBOpt) |
+    (1 << kMatch) |
+    (1 << kPromoteCompilerTemps) |
+    0,
+    // 7 = kMips64.
+    ~0U
+};
+COMPILE_ASSERT(sizeof(kDisabledOptimizationsPerISA) == 8 * sizeof(uint32_t), kDisabledOpts_unexp);
+
+// Supported shorty types per instruction set. nullptr means that all are available.
+// Z : boolean
+// B : byte
+// S : short
+// C : char
+// I : int
+// J : long
+// F : float
+// D : double
+// L : reference(object, array)
+// V : void
+static const char* kSupportedTypes[] = {
+    // 0 = kNone.
+    "",
+    // 1 = kArm, unused (will use kThumb2).
+    "",
+    // 2 = kArm64.
+    nullptr,
+    // 3 = kThumb2.
+    nullptr,
+    // 4 = kX86.
+    nullptr,
+    // 5 = kX86_64.
+    nullptr,
+    // 6 = kMips.
+    nullptr,
+    // 7 = kMips64.
+    ""
+};
+COMPILE_ASSERT(sizeof(kSupportedTypes) == 8 * sizeof(char*), kSupportedTypes_unexp);
+
+static int kAllOpcodes[] = {
+    Instruction::NOP,
+    Instruction::MOVE,
+    Instruction::MOVE_FROM16,
+    Instruction::MOVE_16,
+    Instruction::MOVE_WIDE,
+    Instruction::MOVE_WIDE_FROM16,
+    Instruction::MOVE_WIDE_16,
+    Instruction::MOVE_OBJECT,
+    Instruction::MOVE_OBJECT_FROM16,
+    Instruction::MOVE_OBJECT_16,
+    Instruction::MOVE_RESULT,
+    Instruction::MOVE_RESULT_WIDE,
+    Instruction::MOVE_RESULT_OBJECT,
+    Instruction::MOVE_EXCEPTION,
+    Instruction::RETURN_VOID,
+    Instruction::RETURN,
+    Instruction::RETURN_WIDE,
+    Instruction::RETURN_OBJECT,
+    Instruction::CONST_4,
+    Instruction::CONST_16,
+    Instruction::CONST,
+    Instruction::CONST_HIGH16,
+    Instruction::CONST_WIDE_16,
+    Instruction::CONST_WIDE_32,
+    Instruction::CONST_WIDE,
+    Instruction::CONST_WIDE_HIGH16,
+    Instruction::CONST_STRING,
+    Instruction::CONST_STRING_JUMBO,
+    Instruction::CONST_CLASS,
+    Instruction::MONITOR_ENTER,
+    Instruction::MONITOR_EXIT,
+    Instruction::CHECK_CAST,
+    Instruction::INSTANCE_OF,
+    Instruction::ARRAY_LENGTH,
+    Instruction::NEW_INSTANCE,
+    Instruction::NEW_ARRAY,
+    Instruction::FILLED_NEW_ARRAY,
+    Instruction::FILLED_NEW_ARRAY_RANGE,
+    Instruction::FILL_ARRAY_DATA,
+    Instruction::THROW,
+    Instruction::GOTO,
+    Instruction::GOTO_16,
+    Instruction::GOTO_32,
+    Instruction::PACKED_SWITCH,
+    Instruction::SPARSE_SWITCH,
+    Instruction::CMPL_FLOAT,
+    Instruction::CMPG_FLOAT,
+    Instruction::CMPL_DOUBLE,
+    Instruction::CMPG_DOUBLE,
+    Instruction::CMP_LONG,
+    Instruction::IF_EQ,
+    Instruction::IF_NE,
+    Instruction::IF_LT,
+    Instruction::IF_GE,
+    Instruction::IF_GT,
+    Instruction::IF_LE,
+    Instruction::IF_EQZ,
+    Instruction::IF_NEZ,
+    Instruction::IF_LTZ,
+    Instruction::IF_GEZ,
+    Instruction::IF_GTZ,
+    Instruction::IF_LEZ,
+    Instruction::UNUSED_3E,
+    Instruction::UNUSED_3F,
+    Instruction::UNUSED_40,
+    Instruction::UNUSED_41,
+    Instruction::UNUSED_42,
+    Instruction::UNUSED_43,
+    Instruction::AGET,
+    Instruction::AGET_WIDE,
+    Instruction::AGET_OBJECT,
+    Instruction::AGET_BOOLEAN,
+    Instruction::AGET_BYTE,
+    Instruction::AGET_CHAR,
+    Instruction::AGET_SHORT,
+    Instruction::APUT,
+    Instruction::APUT_WIDE,
+    Instruction::APUT_OBJECT,
+    Instruction::APUT_BOOLEAN,
+    Instruction::APUT_BYTE,
+    Instruction::APUT_CHAR,
+    Instruction::APUT_SHORT,
+    Instruction::IGET,
+    Instruction::IGET_WIDE,
+    Instruction::IGET_OBJECT,
+    Instruction::IGET_BOOLEAN,
+    Instruction::IGET_BYTE,
+    Instruction::IGET_CHAR,
+    Instruction::IGET_SHORT,
+    Instruction::IPUT,
+    Instruction::IPUT_WIDE,
+    Instruction::IPUT_OBJECT,
+    Instruction::IPUT_BOOLEAN,
+    Instruction::IPUT_BYTE,
+    Instruction::IPUT_CHAR,
+    Instruction::IPUT_SHORT,
+    Instruction::SGET,
+    Instruction::SGET_WIDE,
+    Instruction::SGET_OBJECT,
+    Instruction::SGET_BOOLEAN,
+    Instruction::SGET_BYTE,
+    Instruction::SGET_CHAR,
+    Instruction::SGET_SHORT,
+    Instruction::SPUT,
+    Instruction::SPUT_WIDE,
+    Instruction::SPUT_OBJECT,
+    Instruction::SPUT_BOOLEAN,
+    Instruction::SPUT_BYTE,
+    Instruction::SPUT_CHAR,
+    Instruction::SPUT_SHORT,
+    Instruction::INVOKE_VIRTUAL,
+    Instruction::INVOKE_SUPER,
+    Instruction::INVOKE_DIRECT,
+    Instruction::INVOKE_STATIC,
+    Instruction::INVOKE_INTERFACE,
+    Instruction::RETURN_VOID_BARRIER,
+    Instruction::INVOKE_VIRTUAL_RANGE,
+    Instruction::INVOKE_SUPER_RANGE,
+    Instruction::INVOKE_DIRECT_RANGE,
+    Instruction::INVOKE_STATIC_RANGE,
+    Instruction::INVOKE_INTERFACE_RANGE,
+    Instruction::UNUSED_79,
+    Instruction::UNUSED_7A,
+    Instruction::NEG_INT,
+    Instruction::NOT_INT,
+    Instruction::NEG_LONG,
+    Instruction::NOT_LONG,
+    Instruction::NEG_FLOAT,
+    Instruction::NEG_DOUBLE,
+    Instruction::INT_TO_LONG,
+    Instruction::INT_TO_FLOAT,
+    Instruction::INT_TO_DOUBLE,
+    Instruction::LONG_TO_INT,
+    Instruction::LONG_TO_FLOAT,
+    Instruction::LONG_TO_DOUBLE,
+    Instruction::FLOAT_TO_INT,
+    Instruction::FLOAT_TO_LONG,
+    Instruction::FLOAT_TO_DOUBLE,
+    Instruction::DOUBLE_TO_INT,
+    Instruction::DOUBLE_TO_LONG,
+    Instruction::DOUBLE_TO_FLOAT,
+    Instruction::INT_TO_BYTE,
+    Instruction::INT_TO_CHAR,
+    Instruction::INT_TO_SHORT,
+    Instruction::ADD_INT,
+    Instruction::SUB_INT,
+    Instruction::MUL_INT,
+    Instruction::DIV_INT,
+    Instruction::REM_INT,
+    Instruction::AND_INT,
+    Instruction::OR_INT,
+    Instruction::XOR_INT,
+    Instruction::SHL_INT,
+    Instruction::SHR_INT,
+    Instruction::USHR_INT,
+    Instruction::ADD_LONG,
+    Instruction::SUB_LONG,
+    Instruction::MUL_LONG,
+    Instruction::DIV_LONG,
+    Instruction::REM_LONG,
+    Instruction::AND_LONG,
+    Instruction::OR_LONG,
+    Instruction::XOR_LONG,
+    Instruction::SHL_LONG,
+    Instruction::SHR_LONG,
+    Instruction::USHR_LONG,
+    Instruction::ADD_FLOAT,
+    Instruction::SUB_FLOAT,
+    Instruction::MUL_FLOAT,
+    Instruction::DIV_FLOAT,
+    Instruction::REM_FLOAT,
+    Instruction::ADD_DOUBLE,
+    Instruction::SUB_DOUBLE,
+    Instruction::MUL_DOUBLE,
+    Instruction::DIV_DOUBLE,
+    Instruction::REM_DOUBLE,
+    Instruction::ADD_INT_2ADDR,
+    Instruction::SUB_INT_2ADDR,
+    Instruction::MUL_INT_2ADDR,
+    Instruction::DIV_INT_2ADDR,
+    Instruction::REM_INT_2ADDR,
+    Instruction::AND_INT_2ADDR,
+    Instruction::OR_INT_2ADDR,
+    Instruction::XOR_INT_2ADDR,
+    Instruction::SHL_INT_2ADDR,
+    Instruction::SHR_INT_2ADDR,
+    Instruction::USHR_INT_2ADDR,
+    Instruction::ADD_LONG_2ADDR,
+    Instruction::SUB_LONG_2ADDR,
+    Instruction::MUL_LONG_2ADDR,
+    Instruction::DIV_LONG_2ADDR,
+    Instruction::REM_LONG_2ADDR,
+    Instruction::AND_LONG_2ADDR,
+    Instruction::OR_LONG_2ADDR,
+    Instruction::XOR_LONG_2ADDR,
+    Instruction::SHL_LONG_2ADDR,
+    Instruction::SHR_LONG_2ADDR,
+    Instruction::USHR_LONG_2ADDR,
+    Instruction::ADD_FLOAT_2ADDR,
+    Instruction::SUB_FLOAT_2ADDR,
+    Instruction::MUL_FLOAT_2ADDR,
+    Instruction::DIV_FLOAT_2ADDR,
+    Instruction::REM_FLOAT_2ADDR,
+    Instruction::ADD_DOUBLE_2ADDR,
+    Instruction::SUB_DOUBLE_2ADDR,
+    Instruction::MUL_DOUBLE_2ADDR,
+    Instruction::DIV_DOUBLE_2ADDR,
+    Instruction::REM_DOUBLE_2ADDR,
+    Instruction::ADD_INT_LIT16,
+    Instruction::RSUB_INT,
+    Instruction::MUL_INT_LIT16,
+    Instruction::DIV_INT_LIT16,
+    Instruction::REM_INT_LIT16,
+    Instruction::AND_INT_LIT16,
+    Instruction::OR_INT_LIT16,
+    Instruction::XOR_INT_LIT16,
+    Instruction::ADD_INT_LIT8,
+    Instruction::RSUB_INT_LIT8,
+    Instruction::MUL_INT_LIT8,
+    Instruction::DIV_INT_LIT8,
+    Instruction::REM_INT_LIT8,
+    Instruction::AND_INT_LIT8,
+    Instruction::OR_INT_LIT8,
+    Instruction::XOR_INT_LIT8,
+    Instruction::SHL_INT_LIT8,
+    Instruction::SHR_INT_LIT8,
+    Instruction::USHR_INT_LIT8,
+    Instruction::IGET_QUICK,
+    Instruction::IGET_WIDE_QUICK,
+    Instruction::IGET_OBJECT_QUICK,
+    Instruction::IPUT_QUICK,
+    Instruction::IPUT_WIDE_QUICK,
+    Instruction::IPUT_OBJECT_QUICK,
+    Instruction::INVOKE_VIRTUAL_QUICK,
+    Instruction::INVOKE_VIRTUAL_RANGE_QUICK,
+    Instruction::UNUSED_EB,
+    Instruction::UNUSED_EC,
+    Instruction::UNUSED_ED,
+    Instruction::UNUSED_EE,
+    Instruction::UNUSED_EF,
+    Instruction::UNUSED_F0,
+    Instruction::UNUSED_F1,
+    Instruction::UNUSED_F2,
+    Instruction::UNUSED_F3,
+    Instruction::UNUSED_F4,
+    Instruction::UNUSED_F5,
+    Instruction::UNUSED_F6,
+    Instruction::UNUSED_F7,
+    Instruction::UNUSED_F8,
+    Instruction::UNUSED_F9,
+    Instruction::UNUSED_FA,
+    Instruction::UNUSED_FB,
+    Instruction::UNUSED_FC,
+    Instruction::UNUSED_FD,
+    Instruction::UNUSED_FE,
+    Instruction::UNUSED_FF,
+    // ----- ExtendedMIROpcode -----
+    kMirOpPhi,
+    kMirOpCopy,
+    kMirOpFusedCmplFloat,
+    kMirOpFusedCmpgFloat,
+    kMirOpFusedCmplDouble,
+    kMirOpFusedCmpgDouble,
+    kMirOpFusedCmpLong,
+    kMirOpNop,
+    kMirOpNullCheck,
+    kMirOpRangeCheck,
+    kMirOpDivZeroCheck,
+    kMirOpCheck,
+    kMirOpCheckPart2,
+    kMirOpSelect,
+};
+
+// Unsupported opcodes. nullptr can be used when everything is supported. Size of the lists is
+// recorded below.
+static const int* kUnsupportedOpcodes[] = {
+    // 0 = kNone.
+    kAllOpcodes,
+    // 1 = kArm, unused (will use kThumb2).
+    kAllOpcodes,
+    // 2 = kArm64.
+    nullptr,
+    // 3 = kThumb2.
+    nullptr,
+    // 4 = kX86.
+    nullptr,
+    // 5 = kX86_64.
+    nullptr,
+    // 6 = kMips.
+    nullptr,
+    // 7 = kMips64.
+    kAllOpcodes
+};
+COMPILE_ASSERT(sizeof(kUnsupportedOpcodes) == 8 * sizeof(int*), kUnsupportedOpcodes_unexp);
+
+// Size of the arrays stored above.
+static const size_t kUnsupportedOpcodesSize[] = {
+    // 0 = kNone.
+    arraysize(kAllOpcodes),
+    // 1 = kArm, unused (will use kThumb2).
+    arraysize(kAllOpcodes),
+    // 2 = kArm64.
+    0,
+    // 3 = kThumb2.
+    0,
+    // 4 = kX86.
+    0,
+    // 5 = kX86_64.
+    0,
+    // 6 = kMips.
+    0,
+    // 7 = kMips64.
+    arraysize(kAllOpcodes),
+};
+COMPILE_ASSERT(sizeof(kUnsupportedOpcodesSize) == 8 * sizeof(size_t),
+               kUnsupportedOpcodesSize_unexp);
+
+// The maximum amount of Dalvik register in a method for which we will start compiling. Tries to
+// avoid an abort when we need to manage more SSA registers than we can.
+static constexpr size_t kMaxAllowedDalvikRegisters = INT16_MAX / 2;
+
+static bool CanCompileShorty(const char* shorty, InstructionSet instruction_set) {
+  const char* supported_types = kSupportedTypes[instruction_set];
+  if (supported_types == nullptr) {
+    // Everything available.
+    return true;
+  }
+
+  uint32_t shorty_size = strlen(shorty);
+  CHECK_GE(shorty_size, 1u);
+
+  for (uint32_t i = 0; i < shorty_size; i++) {
+    if (strchr(supported_types, shorty[i]) == nullptr) {
+      return false;
+    }
+  }
+  return true;
+};
+
+// Skip the method that we do not support currently.
+bool QuickCompiler::CanCompileMethod(uint32_t method_idx, const DexFile& dex_file,
+                                     CompilationUnit* cu) const {
+  // This is a limitation in mir_graph. See MirGraph::SetNumSSARegs.
+  if (cu->num_dalvik_registers > kMaxAllowedDalvikRegisters) {
+    VLOG(compiler) << "Too many dalvik registers : " << cu->num_dalvik_registers;
+    return false;
+  }
+
+  // Check whether we do have limitations at all.
+  if (kSupportedTypes[cu->instruction_set] == nullptr &&
+      kUnsupportedOpcodesSize[cu->instruction_set] == 0U) {
+    return true;
+  }
+
+  // Check if we can compile the prototype.
+  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
+  if (!CanCompileShorty(shorty, cu->instruction_set)) {
+    VLOG(compiler) << "Unsupported shorty : " << shorty;
+    return false;
+  }
+
+  const int *unsupport_list = kUnsupportedOpcodes[cu->instruction_set];
+  int unsupport_list_size = kUnsupportedOpcodesSize[cu->instruction_set];
+
+  for (unsigned int idx = 0; idx < cu->mir_graph->GetNumBlocks(); idx++) {
+    BasicBlock* bb = cu->mir_graph->GetBasicBlock(idx);
+    if (bb == NULL) continue;
+    if (bb->block_type == kDead) continue;
+    for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
+      int opcode = mir->dalvikInsn.opcode;
+      // Check if we support the byte code.
+      if (std::find(unsupport_list, unsupport_list + unsupport_list_size,
+                    opcode) != unsupport_list + unsupport_list_size) {
+        if (!MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
+          VLOG(compiler) << "Unsupported dalvik byte code : "
+              << mir->dalvikInsn.opcode;
+        } else {
+          VLOG(compiler) << "Unsupported extended MIR opcode : "
+              << MIRGraph::extended_mir_op_names_[opcode - kMirOpFirst];
+        }
+        return false;
+      }
+      // Check if it invokes a prototype that we cannot support.
+      if (Instruction::INVOKE_VIRTUAL == opcode ||
+          Instruction::INVOKE_SUPER == opcode ||
+          Instruction::INVOKE_DIRECT == opcode ||
+          Instruction::INVOKE_STATIC == opcode ||
+          Instruction::INVOKE_INTERFACE == opcode) {
+        uint32_t invoke_method_idx = mir->dalvikInsn.vB;
+        const char* invoke_method_shorty = dex_file.GetMethodShorty(
+            dex_file.GetMethodId(invoke_method_idx));
+        if (!CanCompileShorty(invoke_method_shorty, cu->instruction_set)) {
+          VLOG(compiler) << "Unsupported to invoke '"
+              << PrettyMethod(invoke_method_idx, dex_file)
+              << "' with shorty : " << invoke_method_shorty;
+          return false;
+        }
+      }
+    }
+  }
+  return true;
+}
+
+void QuickCompiler::InitCompilationUnit(CompilationUnit& cu) const {
+  // Disable optimizations according to instruction set.
+  cu.disable_opt |= kDisabledOptimizationsPerISA[cu.instruction_set];
+}
+
+void QuickCompiler::Init() const {
+  CHECK(GetCompilerDriver()->GetCompilerContext() == nullptr);
+}
+
+void QuickCompiler::UnInit() const {
+  CHECK(GetCompilerDriver()->GetCompilerContext() == nullptr);
+}
+
+CompiledMethod* QuickCompiler::Compile(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) const {
+  CompiledMethod* method = TryCompileWithSeaIR(code_item,
+                                               access_flags,
+                                               invoke_type,
+                                               class_def_idx,
+                                               method_idx,
+                                               class_loader,
+                                               dex_file);
+  if (method != nullptr) {
+    return method;
+  }
+
+  // TODO: check method fingerprint here to determine appropriate backend type.  Until then, use
+  // build default.
+  CompilerDriver* driver = GetCompilerDriver();
+  return CompileOneMethod(driver, this, code_item, access_flags, invoke_type, class_def_idx,
+                          method_idx, class_loader, dex_file, nullptr /* use thread llvm_info */);
+}
+
+CompiledMethod* QuickCompiler::JniCompile(uint32_t access_flags,
+                                          uint32_t method_idx,
+                                          const DexFile& dex_file) const {
+  return ArtQuickJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
+}
+
+uintptr_t QuickCompiler::GetEntryPointOf(mirror::ArtMethod* method) const {
+  return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
+}
+
+bool QuickCompiler::WriteElf(art::File* file,
+                             OatWriter* oat_writer,
+                             const std::vector<const art::DexFile*>& dex_files,
+                             const std::string& android_root,
+                             bool is_host) const {
+  return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host,
+                                     *GetCompilerDriver());
+}
+
+Backend* QuickCompiler::GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
+  Mir2Lir* mir_to_lir = nullptr;
+  switch (cu->instruction_set) {
+    case kThumb2:
+      mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+      break;
+    case kArm64:
+      mir_to_lir = Arm64CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+      break;
+    case kMips:
+      mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+      break;
+    case kX86:
+      // Fall-through.
+    case kX86_64:
+      mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+      break;
+    default:
+      LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
+  }
+
+  /* The number of compiler temporaries depends on backend so set it up now if possible */
+  if (mir_to_lir) {
+    size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps();
+    bool set_max = cu->mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps);
+    CHECK(set_max);
+  }
+  return mir_to_lir;
+}
+
+
+Compiler* CreateQuickCompiler(CompilerDriver* driver) {
+  return new QuickCompiler(driver);
+}
+
+}  // namespace art
diff --git a/compiler/dex/quick/quick_compiler.h b/compiler/dex/quick/quick_compiler.h
new file mode 100644
index 0000000..10de5fb
--- /dev/null
+++ b/compiler/dex/quick/quick_compiler.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 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_QUICK_QUICK_COMPILER_H_
+#define ART_COMPILER_DEX_QUICK_QUICK_COMPILER_H_
+
+namespace art {
+
+class Compiler;
+class CompilerDriver;
+
+Compiler* CreateQuickCompiler(CompilerDriver* driver);
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_QUICK_QUICK_COMPILER_H_
diff --git a/compiler/dex/quick/x86/backend_x86.h b/compiler/dex/quick/x86/backend_x86.h
new file mode 100644
index 0000000..f73db94
--- /dev/null
+++ b/compiler/dex/quick/x86/backend_x86.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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_QUICK_X86_BACKEND_X86_H_
+#define ART_COMPILER_DEX_QUICK_X86_BACKEND_X86_H_
+
+namespace art {
+
+struct CompilationUnit;
+class Mir2Lir;
+class MIRGraph;
+class ArenaAllocator;
+
+Mir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
+                          ArenaAllocator* const arena);
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_QUICK_X86_BACKEND_X86_H_
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 7d1e20e..9c50121 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -18,6 +18,7 @@
 #define ART_COMPILER_DEX_QUICK_X86_CODEGEN_X86_H_
 
 #include "dex/compiler_internals.h"
+#include "dex/quick/mir_to_lir.h"
 #include "x86_lir.h"
 
 #include <map>
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 8c6aa5f..604f4bf 100755
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -17,6 +17,7 @@
 #include <string>
 #include <inttypes.h>
 
+#include "backend_x86.h"
 #include "codegen_x86.h"
 #include "dex/compiler_internals.h"
 #include "dex/quick/mir_to_lir-inl.h"
diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc
index 4a3e071..f13165e 100644
--- a/compiler/dex/vreg_analysis.cc
+++ b/compiler/dex/vreg_analysis.cc
@@ -404,30 +404,15 @@
 static const char* storage_name[] = {" Frame ", "PhysReg", " Spill "};
 
 void MIRGraph::DumpRegLocTable(RegLocation* table, int count) {
-  // FIXME: Quick-specific.  Move to Quick (and make a generic version for MIRGraph?
-  Mir2Lir* cg = static_cast<Mir2Lir*>(cu_->cg.get());
-  if (cg != NULL) {
-    for (int i = 0; i < count; i++) {
-      LOG(INFO) << StringPrintf("Loc[%02d] : %s, %c %c %c %c %c %c 0x%04x S%d",
-          table[i].orig_sreg, storage_name[table[i].location],
-          table[i].wide ? 'W' : 'N', table[i].defined ? 'D' : 'U',
-          table[i].fp ? 'F' : table[i].ref ? 'R' :'C',
-          table[i].is_const ? 'c' : 'n',
-          table[i].high_word ? 'H' : 'L', table[i].home ? 'h' : 't',
-          table[i].reg.GetRawBits(),
-          table[i].s_reg_low);
-    }
-  } else {
-    // Either pre-regalloc or Portable.
-    for (int i = 0; i < count; i++) {
-      LOG(INFO) << StringPrintf("Loc[%02d] : %s, %c %c %c %c %c %c S%d",
-          table[i].orig_sreg, storage_name[table[i].location],
-          table[i].wide ? 'W' : 'N', table[i].defined ? 'D' : 'U',
-          table[i].fp ? 'F' : table[i].ref ? 'R' :'C',
-          table[i].is_const ? 'c' : 'n',
-          table[i].high_word ? 'H' : 'L', table[i].home ? 'h' : 't',
-          table[i].s_reg_low);
-    }
+  for (int i = 0; i < count; i++) {
+    LOG(INFO) << StringPrintf("Loc[%02d] : %s, %c %c %c %c %c %c 0x%04x S%d",
+                              table[i].orig_sreg, storage_name[table[i].location],
+                              table[i].wide ? 'W' : 'N', table[i].defined ? 'D' : 'U',
+                              table[i].fp ? 'F' : table[i].ref ? 'R' :'C',
+                              table[i].is_const ? 'c' : 'n',
+                              table[i].high_word ? 'H' : 'L', table[i].home ? 'h' : 't',
+                              table[i].reg.GetRawBits(),
+                              table[i].s_reg_low);
   }
 }
 
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index 022ec6b..4d5d253 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -20,6 +20,7 @@
 #include "compiler_driver.h"
 
 #include "dex/compiler_ir.h"
+#include "dex_compilation_unit.h"
 #include "field_helper.h"
 #include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 3915381..3b0c8af 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -444,7 +444,7 @@
   // Lazily create thread-local storage
   CompilerTls* res = static_cast<CompilerTls*>(pthread_getspecific(tls_key_));
   if (res == NULL) {
-    res = new CompilerTls();
+    res = compiler_->CreateNewCompilerTls();
     CHECK_PTHREAD_CALL(pthread_setspecific, (tls_key_, res), "compiler tls");
   }
   return res;
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index d8f318b..87523bf 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -76,20 +76,6 @@
   kOptimize               // Perform required transformation and peep-hole optimizations.
 };
 
-// Thread-local storage compiler worker threads
-class CompilerTls {
-  public:
-    CompilerTls() : llvm_info_(NULL) {}
-    ~CompilerTls() {}
-
-    void* GetLLVMInfo() { return llvm_info_; }
-
-    void SetLLVMInfo(void* llvm_info) { llvm_info_ = llvm_info; }
-
-  private:
-    void* llvm_info_;
-};
-
 class CompilerDriver {
  public:
   // Create a compiler targeting the requested "instruction_set".
diff --git a/compiler/elf_patcher.cc b/compiler/elf_patcher.cc
index 9ae755d..72bf7d3 100644
--- a/compiler/elf_patcher.cc
+++ b/compiler/elf_patcher.cc
@@ -19,6 +19,7 @@
 #include <vector>
 #include <set>
 
+#include "class_linker.h"
 #include "elf_file.h"
 #include "elf_utils.h"
 #include "mirror/art_field-inl.h"
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 3d119bb..f2a16e5 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "base/unix_file/fd_file.h"
+#include "class_linker.h"
 #include "common_compiler_test.h"
 #include "elf_fixup.h"
 #include "gc/space/image_space.h"
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 8e87021..78a228b 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "jni_compiler.h"
+
 #include <algorithm>
 #include <memory>
 #include <vector>
@@ -546,10 +548,9 @@
   }
 }
 
-}  // namespace art
-
-extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver* compiler,
-                                                         uint32_t access_flags, uint32_t method_idx,
-                                                         const art::DexFile& dex_file) {
+CompiledMethod* ArtQuickJniCompileMethod(CompilerDriver* compiler, uint32_t access_flags,
+                                         uint32_t method_idx, const DexFile& dex_file) {
   return ArtJniCompileMethodInternal(compiler, access_flags, method_idx, dex_file);
 }
+
+}  // namespace art
diff --git a/compiler/jni/quick/jni_compiler.h b/compiler/jni/quick/jni_compiler.h
new file mode 100644
index 0000000..46277f1
--- /dev/null
+++ b/compiler/jni/quick/jni_compiler.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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_JNI_QUICK_JNI_COMPILER_H_
+#define ART_COMPILER_JNI_QUICK_JNI_COMPILER_H_
+
+#include "dex_file.h"
+
+namespace art {
+
+class CompilerDriver;
+class CompiledMethod;
+
+CompiledMethod* ArtQuickJniCompileMethod(CompilerDriver* compiler, uint32_t access_flags,
+                                         uint32_t method_idx, const DexFile& dex_file);
+
+}  // namespace art
+
+#endif  // ART_COMPILER_JNI_QUICK_JNI_COMPILER_H_
diff --git a/compiler/llvm/compiler_llvm.cc b/compiler/llvm/compiler_llvm.cc
index 5990e8c..3aeecad 100644
--- a/compiler/llvm/compiler_llvm.cc
+++ b/compiler/llvm/compiler_llvm.cc
@@ -141,7 +141,7 @@
   cunit->SetDexCompilationUnit(dex_compilation_unit);
   cunit->SetCompilerDriver(compiler_driver_);
   // TODO: consolidate ArtCompileMethods
-  CompileOneMethod(*compiler_driver_,
+  CompileOneMethod(compiler_driver_,
                    compiler_driver_->GetCompiler(),
                    dex_compilation_unit->GetCodeItem(),
                    dex_compilation_unit->GetAccessFlags(),
@@ -172,68 +172,62 @@
 }
 
 
-}  // namespace llvm
-}  // namespace art
-
-static art::llvm::CompilerLLVM* ContextOf(art::CompilerDriver* driver) {
+static CompilerLLVM* ContextOf(art::CompilerDriver* driver) {
   void *compiler_context = driver->GetCompilerContext();
   CHECK(compiler_context != NULL);
-  return reinterpret_cast<art::llvm::CompilerLLVM*>(compiler_context);
+  return reinterpret_cast<CompilerLLVM*>(compiler_context);
 }
 
-static art::llvm::CompilerLLVM* ContextOf(const art::CompilerDriver& driver) {
+static CompilerLLVM* ContextOf(const art::CompilerDriver& driver) {
   void *compiler_context = driver.GetCompilerContext();
   CHECK(compiler_context != NULL);
-  return reinterpret_cast<art::llvm::CompilerLLVM*>(compiler_context);
+  return reinterpret_cast<CompilerLLVM*>(compiler_context);
 }
 
-extern "C" void ArtInitCompilerContext(art::CompilerDriver* driver) {
+void ArtInitCompilerContext(CompilerDriver* driver) {
   CHECK(driver->GetCompilerContext() == nullptr);
 
-  art::llvm::CompilerLLVM* compiler_llvm = new art::llvm::CompilerLLVM(driver,
-                                                                       driver->GetInstructionSet());
+  CompilerLLVM* compiler_llvm = new CompilerLLVM(driver, driver->GetInstructionSet());
 
   driver->SetCompilerContext(compiler_llvm);
 }
 
-extern "C" void ArtUnInitCompilerContext(art::CompilerDriver* driver) {
+void ArtUnInitCompilerContext(CompilerDriver* driver) {
   delete ContextOf(driver);
   driver->SetCompilerContext(nullptr);
 }
-extern "C" art::CompiledMethod* ArtCompileMethod(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) {
+
+CompiledMethod* ArtCompileMethod(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) {
   UNUSED(class_def_idx);  // TODO: this is used with Compiler::RequiresConstructorBarrier.
-  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
+  ClassLinker *class_linker = Runtime::Current()->GetClassLinker();
 
-  art::DexCompilationUnit dex_compilation_unit(
-    NULL, class_loader, class_linker, dex_file, code_item,
-    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);
+  DexCompilationUnit dex_compilation_unit(nullptr, class_loader, class_linker, dex_file, code_item,
+                                          class_def_idx, method_idx, access_flags,
+                                          driver->GetVerifiedMethod(&dex_file, method_idx));
+  CompilerLLVM* compiler_llvm = ContextOf(driver);
+  CompiledMethod* result = compiler_llvm->CompileDexMethod(&dex_compilation_unit, invoke_type);
   return result;
 }
 
-extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver* driver,
-                                                        uint32_t access_flags, uint32_t method_idx,
-                                                        const art::DexFile& dex_file) {
-  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
+CompiledMethod* ArtLLVMJniCompileMethod(CompilerDriver* driver, uint32_t access_flags,
+                                        uint32_t method_idx, const DexFile& dex_file) {
+  ClassLinker *class_linker = Runtime::Current()->GetClassLinker();
 
-  art::DexCompilationUnit dex_compilation_unit(
-      nullptr, nullptr, class_linker, dex_file, nullptr,
-      0, method_idx, access_flags, nullptr);
+  DexCompilationUnit dex_compilation_unit(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);
+  CompilerLLVM* compiler_llvm = ContextOf(driver);
+  CompiledMethod* result = compiler_llvm->CompileNativeMethod(&dex_compilation_unit);
   return result;
 }
 
-extern "C" void compilerLLVMSetBitcodeFileName(const art::CompilerDriver& driver,
-                                               const std::string& filename) {
+void compilerLLVMSetBitcodeFileName(const CompilerDriver& driver, const std::string& filename) {
   ContextOf(driver)->SetBitcodeFileName(filename);
 }
+
+}  // namespace llvm
+}  // namespace art
+
diff --git a/compiler/llvm/compiler_llvm.h b/compiler/llvm/compiler_llvm.h
index cc74deb..7d29198 100644
--- a/compiler/llvm/compiler_llvm.h
+++ b/compiler/llvm/compiler_llvm.h
@@ -95,6 +95,19 @@
   DISALLOW_COPY_AND_ASSIGN(CompilerLLVM);
 };
 
+void ArtInitCompilerContext(CompilerDriver* driver);
+
+void ArtUnInitCompilerContext(CompilerDriver* driver);
+
+CompiledMethod* ArtCompileMethod(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);
+
+CompiledMethod* ArtLLVMJniCompileMethod(CompilerDriver* driver, uint32_t access_flags,
+                                        uint32_t method_idx, const DexFile& dex_file);
+
+void compilerLLVMSetBitcodeFileName(const CompilerDriver& driver, const std::string& filename);
 
 }  // namespace llvm
 }  // namespace art
diff --git a/compiler/llvm/llvm_compiler.cc b/compiler/llvm/llvm_compiler.cc
new file mode 100644
index 0000000..55af614
--- /dev/null
+++ b/compiler/llvm/llvm_compiler.cc
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "llvm_compiler.h"
+
+#ifdef ART_USE_PORTABLE_COMPILER
+#include "compiler.h"
+#include "compiler_llvm.h"
+#include "dex/portable/mir_to_gbc.h"
+#include "dex_file.h"
+#include "elf_writer_mclinker.h"
+#include "mirror/art_method-inl.h"
+#endif
+
+namespace art {
+
+#ifdef ART_USE_PORTABLE_COMPILER
+
+namespace llvm {
+
+// Thread-local storage compiler worker threads
+class LLVMCompilerTls : public CompilerTls {
+  public:
+    LLVMCompilerTls() : llvm_info_(nullptr) {}
+    ~LLVMCompilerTls() {}
+
+    void* GetLLVMInfo() { return llvm_info_; }
+
+    void SetLLVMInfo(void* llvm_info) { llvm_info_ = llvm_info; }
+
+  private:
+    void* llvm_info_;
+};
+
+
+
+class LLVMCompiler FINAL : public Compiler {
+ public:
+  explicit LLVMCompiler(CompilerDriver* driver) : Compiler(driver, 1000) {}
+
+  CompilerTls* CreateNewCompilerTls() {
+    return new LLVMCompilerTls();
+  }
+
+  void Init() const OVERRIDE {
+    ArtInitCompilerContext(GetCompilerDriver());
+  }
+
+  void UnInit() const OVERRIDE {
+    ArtUnInitCompilerContext(GetCompilerDriver());
+  }
+
+  bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, CompilationUnit* cu) const
+      OVERRIDE {
+    return true;
+  }
+
+  CompiledMethod* Compile(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) const OVERRIDE {
+    CompiledMethod* method = TryCompileWithSeaIR(code_item,
+                                                 access_flags,
+                                                 invoke_type,
+                                                 class_def_idx,
+                                                 method_idx,
+                                                 class_loader,
+                                                 dex_file);
+    if (method != nullptr) {
+      return method;
+    }
+
+    return ArtCompileMethod(GetCompilerDriver(),
+                            code_item,
+                            access_flags,
+                            invoke_type,
+                            class_def_idx,
+                            method_idx,
+                            class_loader,
+                            dex_file);
+  }
+
+  CompiledMethod* JniCompile(uint32_t access_flags,
+                             uint32_t method_idx,
+                             const DexFile& dex_file) const OVERRIDE {
+    return ArtLLVMJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
+  }
+
+  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
+    return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
+  }
+
+  bool WriteElf(art::File* file,
+                OatWriter* oat_writer,
+                const std::vector<const art::DexFile*>& dex_files,
+                const std::string& android_root,
+                bool is_host, const CompilerDriver& driver) const
+      OVERRIDE
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return art::ElfWriterMclinker::Create(
+        file, oat_writer, dex_files, android_root, is_host, driver);
+  }
+
+  Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
+    return PortableCodeGenerator(
+        cu, cu->mir_graph.get(), &cu->arena,
+        reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
+  }
+
+  void InitCompilationUnit(CompilationUnit& cu) const {
+      // Fused long branches not currently useful in bitcode.
+    cu.disable_opt |=
+        (1 << kBranchFusing) |
+        (1 << kSuppressExceptionEdges);
+  }
+
+  bool IsPortable() const OVERRIDE {
+    return true;
+  }
+
+  void SetBitcodeFileName(const CompilerDriver& driver, const std::string& filename) {
+    typedef void (*SetBitcodeFileNameFn)(const CompilerDriver&, const std::string&);
+
+    SetBitcodeFileNameFn set_bitcode_file_name =
+      reinterpret_cast<SetBitcodeFileNameFn>(compilerLLVMSetBitcodeFileName);
+
+    set_bitcode_file_name(driver, filename);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LLVMCompiler);
+};
+
+}  // namespace llvm
+#endif
+
+Compiler* CreateLLVMCompiler(CompilerDriver* driver) {
+#ifdef ART_USE_PORTABLE_COMPILER
+      return new llvm::LLVMCompiler(driver);
+#else
+      return nullptr;
+#endif
+}
+
+}  // namespace art
diff --git a/compiler/llvm/llvm_compiler.h b/compiler/llvm/llvm_compiler.h
new file mode 100644
index 0000000..da6d0e9
--- /dev/null
+++ b/compiler/llvm/llvm_compiler.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 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_LLVM_LLVM_COMPILER_H_
+#define ART_COMPILER_LLVM_LLVM_COMPILER_H_
+
+namespace art {
+
+class Compiler;
+class CompilerDriver;
+
+Compiler* CreateLLVMCompiler(CompilerDriver* driver);
+
+}
+
+#endif  // ART_COMPILER_LLVM_LLVM_COMPILER_H_
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 11d1728..28710e0 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "class_linker.h"
 #include "common_compiler_test.h"
 #include "compiler.h"
 #include "dex/verification_results.h"
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index fce6ab0..3461276 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+#include "optimizing_compiler.h"
+
 #include <fstream>
 #include <stdint.h>
 
 #include "builder.h"
 #include "code_generator.h"
-#include "compilers.h"
+#include "compiler.h"
 #include "driver/compiler_driver.h"
 #include "driver/dex_compilation_unit.h"
 #include "graph_visualizer.h"
@@ -65,12 +67,105 @@
  */
 static const char* kStringFilter = "";
 
-OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver) : QuickCompiler(driver) {
+class OptimizingCompiler FINAL : public Compiler {
+ public:
+  explicit OptimizingCompiler(CompilerDriver* driver);
+
+  bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, CompilationUnit* cu) const
+      OVERRIDE;
+
+  CompiledMethod* Compile(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) const OVERRIDE;
+
+  CompiledMethod* TryCompile(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) const;
+
+  // For the following methods we will use the fallback. This is a delegation pattern.
+  CompiledMethod* JniCompile(uint32_t access_flags,
+                             uint32_t method_idx,
+                             const DexFile& dex_file) const OVERRIDE;
+
+  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const OVERRIDE
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  bool WriteElf(art::File* file,
+                OatWriter* oat_writer,
+                const std::vector<const art::DexFile*>& dex_files,
+                const std::string& android_root,
+                bool is_host) const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const OVERRIDE;
+
+  void InitCompilationUnit(CompilationUnit& cu) const OVERRIDE;
+
+  void Init() const OVERRIDE;
+
+  void UnInit() const OVERRIDE;
+
+ private:
+  std::unique_ptr<std::ostream> visualizer_output_;
+
+  // Delegate to another compiler in case the optimizing compiler cannot compile a method.
+  // Currently the fallback is the quick compiler.
+  std::unique_ptr<Compiler> delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(OptimizingCompiler);
+};
+
+OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver) : Compiler(driver, 100),
+    delegate_(Create(driver, Compiler::Kind::kQuick)) {
   if (kIsVisualizerEnabled) {
     visualizer_output_.reset(new std::ofstream("art.cfg"));
   }
 }
 
+void OptimizingCompiler::Init() const {
+  delegate_->Init();
+}
+
+void OptimizingCompiler::UnInit() const {
+  delegate_->UnInit();
+}
+
+bool OptimizingCompiler::CanCompileMethod(uint32_t method_idx, const DexFile& dex_file,
+                                          CompilationUnit* cu) const {
+  return delegate_->CanCompileMethod(method_idx, dex_file, cu);
+}
+
+CompiledMethod* OptimizingCompiler::JniCompile(uint32_t access_flags,
+                                               uint32_t method_idx,
+                                               const DexFile& dex_file) const {
+  return delegate_->JniCompile(access_flags, method_idx, dex_file);
+}
+
+uintptr_t OptimizingCompiler::GetEntryPointOf(mirror::ArtMethod* method) const {
+  return delegate_->GetEntryPointOf(method);
+}
+
+bool OptimizingCompiler::WriteElf(art::File* file, OatWriter* oat_writer,
+                                  const std::vector<const art::DexFile*>& dex_files,
+                                  const std::string& android_root, bool is_host) const {
+  return delegate_->WriteElf(file, oat_writer, dex_files, android_root, is_host);
+}
+
+Backend* OptimizingCompiler::GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
+  return delegate_->GetCodeGenerator(cu, compilation_unit);
+}
+
+void OptimizingCompiler::InitCompilationUnit(CompilationUnit& cu) const {
+  delegate_->InitCompilationUnit(cu);
+}
+
 CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_item,
                                                uint32_t access_flags,
                                                InvokeType invoke_type,
@@ -183,4 +278,25 @@
                             nullptr);
 }
 
+CompiledMethod* OptimizingCompiler::Compile(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) const {
+  CompiledMethod* method = TryCompile(code_item, access_flags, invoke_type, class_def_idx,
+                                      method_idx, class_loader, dex_file);
+  if (method != nullptr) {
+    return method;
+  }
+
+  return delegate_->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx,
+                            class_loader, dex_file);
+}
+
+Compiler* CreateOptimizingCompiler(CompilerDriver* driver) {
+  return new OptimizingCompiler(driver);
+}
+
 }  // namespace art
diff --git a/compiler/optimizing/optimizing_compiler.h b/compiler/optimizing/optimizing_compiler.h
new file mode 100644
index 0000000..a415eca
--- /dev/null
+++ b/compiler/optimizing/optimizing_compiler.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 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_OPTIMIZING_OPTIMIZING_COMPILER_H_
+#define ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_H_
+
+namespace art {
+
+class Compiler;
+class CompilerDriver;
+
+Compiler* CreateOptimizingCompiler(CompilerDriver* driver);
+
+}
+
+#endif  // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_H_