Quick compiler: reuse llvm context & ir builder

With this CL, we avoid setting up an llvm context, module and intrinsic
definitions for each method, and considerably speed up compilation time.
This does not represent a final form - we'll be reworking the compiler driver
to support Quick & Portable via the command line, and this code will likely
change at that time.

Change-Id: I19e298a011141c3bc35c4f28175b2b20653fd5e4
diff --git a/src/compiler.cc b/src/compiler.cc
index 091aad9..b05e688 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -331,6 +331,16 @@
                                       "ArtInitCompilerContext");
 
   init_compiler_context(*this);
+#elif defined(ART_USE_QUICK_COMPILER)
+  // Initialize compiler_context_
+  typedef void (*InitCompilerContextFn)(Compiler&);
+
+  InitCompilerContextFn init_compiler_context =
+    FindFunction<void (*)(Compiler&)>(compiler_so_name,
+                                      compiler_library_,
+                                      "ArtInitQuickCompilerContext");
+
+  init_compiler_context(*this);
 #endif
 
   compiler_ = FindFunction<CompilerFn>(compiler_so_name, compiler_library_, "ArtCompileMethod");
@@ -387,6 +397,18 @@
                                       "ArtUnInitCompilerContext");
 
   uninit_compiler_context(*this);
+#elif defined(ART_USE_QUICK_COMPILER)
+  // Uninitialize compiler_context_
+  typedef void (*UninitCompilerContextFn)(Compiler&);
+
+  std::string compiler_so_name(MakeCompilerSoName(instruction_set_));
+
+  UninitCompilerContextFn uninit_compiler_context =
+    FindFunction<void (*)(Compiler&)>(compiler_so_name,
+                                      compiler_library_,
+                                      "ArtUnInitQuickCompilerContext");
+
+  uninit_compiler_context(*this);
 #endif
   if (compiler_library_ != NULL) {
     VLOG(compiler) << "dlclose(" << compiler_library_ << ")";
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index 659b5a6..9ac6016 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -20,7 +20,20 @@
 #include "dex_file.h"
 #include "dex_instruction.h"
 
+#if defined(ART_USE_QUICK_COMPILER)
+namespace llvm {
+  class Module;
+  class LLVMContext;
+}
+#endif
+
 namespace art {
+#if defined(ART_USE_QUICK_COMPILER)
+namespace greenland {
+  class IntrinsicHelper;
+  class IRBuilder;
+}
+#endif
 
 #define COMPILER_TRACED(X)
 #define COMPILER_TRACEE(X)
@@ -163,6 +176,41 @@
   kReversePostOrderTraversal, // Depth-First-Search / reverse Post-Order
 };
 
+#if defined(ART_USE_QUICK_COMPILER)
+class QuickCompiler {
+  public:
+    QuickCompiler(art::Compiler* compiler);
+    ~QuickCompiler();
+
+    const art::Compiler* GetCompiler() const {
+      return compiler_;
+    }
+
+    llvm::LLVMContext* GetLLVMContext() {
+      return llvm_context_.get();
+    }
+
+    llvm::Module* GetLLVMModule() {
+      return llvm_module_.get();
+    }
+
+    art::greenland::IntrinsicHelper* GetIntrinsicHelper() {
+      return intrinsic_helper_.get();
+    }
+
+    art::greenland::IRBuilder* GetIRBuilder() {
+      return ir_builder_.get();
+    }
+
+  private:
+    const art::Compiler* const compiler_;
+    UniquePtr<llvm::LLVMContext> llvm_context_;
+    UniquePtr<llvm::Module> llvm_module_;
+    UniquePtr<art::greenland::IntrinsicHelper> intrinsic_helper_;
+    UniquePtr<art::greenland::IRBuilder> ir_builder_;
+};
+#endif
+
 struct CompilationUnit;
 struct BasicBlock;
 struct SSARepresentation;
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 3c579c4..8c403c5 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -23,6 +23,34 @@
 
 namespace art {
 
+#if defined(ART_USE_QUICK_COMPILER)
+QuickCompiler::QuickCompiler(art::Compiler* compiler)
+    : compiler_(compiler) {
+  // Create context, module, intrinsic helper & ir builder
+  llvm_context_.reset(new llvm::LLVMContext());
+  llvm_module_.reset(new llvm::Module("art", *llvm_context_));
+  llvm::StructType::create(*llvm_context_, "JavaObject");
+  llvm::StructType::create(*llvm_context_, "Method");
+  llvm::StructType::create(*llvm_context_, "Thread");
+  intrinsic_helper_.reset( new greenland::IntrinsicHelper(*llvm_context_, *llvm_module_));
+  ir_builder_.reset(new greenland::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
+}
+
+QuickCompiler::~QuickCompiler() {
+}
+
+extern "C" void ArtInitQuickCompilerContext(art::Compiler& compiler) {
+  CHECK(compiler.GetCompilerContext() == NULL);
+  QuickCompiler* quickCompiler = new QuickCompiler(&compiler);
+  compiler.SetCompilerContext(quickCompiler);
+}
+
+extern "C" void ArtUnInitQuickCompilerContext(art::Compiler& compiler) {
+  delete reinterpret_cast<QuickCompiler*>(compiler.GetCompilerContext());
+  compiler.SetCompilerContext(NULL);
+}
+#endif
+
 /* Default optimizer/debug setting for the compiler. */
 static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations
   //(1 << kLoadStoreElimination) |
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index c84d6d3..cfe6e6a 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -166,27 +166,14 @@
   }
   cUnit->locMap.Put(val, loc);
 }
-
 void initIR(CompilationUnit* cUnit)
 {
-  cUnit->context = new llvm::LLVMContext();
-  cUnit->module = new llvm::Module("art", *cUnit->context);
-  llvm::StructType::create(*cUnit->context, "JavaObject");
-  llvm::StructType::create(*cUnit->context, "Method");
-  llvm::StructType::create(*cUnit->context, "Thread");
-  cUnit->intrinsic_helper =
-      new greenland::IntrinsicHelper(*cUnit->context, *cUnit->module);
-  cUnit->irb =
-      new greenland::IRBuilder(*cUnit->context, *cUnit->module,
-                               *cUnit->intrinsic_helper);
-}
-
-void freeIR(CompilationUnit* cUnit)
-{
-  delete cUnit->irb;
-  delete cUnit->intrinsic_helper;
-  delete cUnit->module;
-  delete cUnit->context;
+  QuickCompiler* quick =
+      reinterpret_cast<QuickCompiler*>(cUnit->compiler->GetCompilerContext());
+  cUnit->context = quick->GetLLVMContext();
+  cUnit->module = quick->GetLLVMModule();
+  cUnit->intrinsic_helper = quick->GetIntrinsicHelper();
+  cUnit->irb = quick->GetIRBuilder();
 }
 
 const char* llvmSSAName(CompilationUnit* cUnit, int ssaReg) {
@@ -840,7 +827,6 @@
   RegLocation rlSrc[3];
   RegLocation rlDest = badLoc;
   Instruction::Code opcode = mir->dalvikInsn.opcode;
-  uint32_t vA = mir->dalvikInsn.vA;
   uint32_t vB = mir->dalvikInsn.vB;
   uint32_t vC = mir->dalvikInsn.vC;
   int optFlags = mir->optimizationFlags;
@@ -3480,7 +3466,8 @@
 
   handleIntrinsicLaunchpads(cUnit);
 
-  freeIR(cUnit);
+  cUnit->func->eraseFromParent();
+  cUnit->func = NULL;
 }