Cleanup LLVM code generation code.

Materialize the bitcode in the end of CompileClass,
so that the code generation time won't be calculated
in method compilation time.

Change-Id: I1e2bd0b23bcb5c55bd966a31b1df0b8b34922f94
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index 08c3dfc..ac956ef 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -193,24 +193,22 @@
     fpm.run(*F);
   }
   fpm.doFinalization();
-  LOG(INFO) << "Intraprocedural optimization finished!";
 
   // Run the code generation passes
   pm.run(*module_);
-  LOG(INFO) << "Code generation finished!";
 
+  // Keep the generated executable
   out_file->keep();
-  LOG(DEBUG) << "ELF: " << elf_filename_ << " (done)";
+  LOG(INFO) << "ELF: " << elf_filename_ << " (done)";
+
+  // Free the resources
+  context_.reset(NULL);
+  irb_.reset(NULL);
+  module_ = NULL;
 
   return true;
 }
 
 
-void CompilationUnit::Finalize() {
-  context_.reset(NULL);
-  irb_.reset(NULL);
-  module_ = NULL;
-}
-
 } // namespace compiler_llvm
 } // namespace art
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index a10d977..2ae5c0b 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -56,12 +56,10 @@
   }
 
   std::string const& GetElfFileName() const {
-    CHECK(IsFinalized());
     return elf_filename_;
   }
 
   std::string const& GetBitcodeFileName() const {
-    CHECK(IsFinalized());
     return bitcode_filename_;
   }
 
@@ -77,12 +75,10 @@
 
   bool Materialize();
 
-  bool IsFinalized() const {
+  bool IsMaterialized() const {
     return (context_.get() == NULL);
   }
 
-  void Finalize();
-
   bool IsMaterializeThresholdReached() const {
     return (mem_usage_ > 300000000u); // (threshold: 300 MB)
   }
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 146f577..345872e 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -22,6 +22,7 @@
 #include "jni_compiler.h"
 #include "method_compiler.h"
 #include "oat_compilation_unit.h"
+#include "stl_util.h"
 #include "upcall_compiler.h"
 
 #include <llvm/LinkAllPasses.h>
@@ -71,7 +72,7 @@
 
 CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set)
     : compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
-      insn_set_(insn_set), cunit_counter_(0) {
+      insn_set_(insn_set), curr_cunit_(NULL) {
 
   // Initialize LLVM libraries
   pthread_once(&llvm_initialized, InitializeLLVM);
@@ -79,104 +80,105 @@
 
 
 CompilerLLVM::~CompilerLLVM() {
-  DCHECK(cunit_.get() == NULL);
+  STLDeleteElements(&cunits_);
 }
 
 
-void CompilerLLVM::EnsureCompilationUnit() {
-  MutexLock GUARD(compiler_lock_);
+void CompilerLLVM::EnsureCompilationUnit(MutexLock& GUARD) {
   DCHECK_NE(llvm_initialized, PTHREAD_ONCE_INIT);
-  if (cunit_.get() == NULL) {
-    cunit_.reset(new CompilationUnit(insn_set_));
+
+  if (curr_cunit_ != NULL) {
+    return;
   }
+
+  // Allocate compilation unit
+  size_t cunit_idx = cunits_.size();
+
+  curr_cunit_ = new CompilationUnit(insn_set_);
+
+  // Setup output filename
+  curr_cunit_->SetElfFileName(
+    StringPrintf("%s-%zu", elf_filename_.c_str(), cunit_idx));
+
+  if (IsBitcodeFileNameAvailable()) {
+    curr_cunit_->SetBitcodeFileName(
+      StringPrintf("%s-%zu", bitcode_filename_.c_str(), cunit_idx));
+  }
+
+  // Register compilation unit
+  cunits_.push_back(curr_cunit_);
 }
 
 
-void CompilerLLVM::MaterializeEveryCompilationUnit() {
-  if (cunit_.get() != NULL) {
-    MaterializeCompilationUnit();
-  }
-}
-
-
-void CompilerLLVM::MaterializeCompilationUnitSafePoint() {
-  if (cunit_->IsMaterializeThresholdReached()) {
-    MaterializeCompilationUnit();
-  }
-}
-
-
-void CompilerLLVM::MaterializeCompilationUnit() {
+void CompilerLLVM::MaterializeRemainder() {
   MutexLock GUARD(compiler_lock_);
+  if (curr_cunit_ != NULL) {
+    Materialize(GUARD);
+  }
+}
 
-  cunit_->SetElfFileName(StringPrintf("%s-%u", elf_filename_.c_str(),
-                                      cunit_counter_));
 
-  // Write the translated bitcode for debugging
-  if (!bitcode_filename_.empty()) {
-    cunit_->SetBitcodeFileName(StringPrintf("%s-%u", bitcode_filename_.c_str(),
-                                            cunit_counter_));
-    cunit_->WriteBitcodeToFile();
+void CompilerLLVM::MaterializeIfThresholdReached() {
+  MutexLock GUARD(compiler_lock_);
+  if (curr_cunit_ != NULL && curr_cunit_->IsMaterializeThresholdReached()) {
+    Materialize(GUARD);
+  }
+}
+
+
+void CompilerLLVM::Materialize(MutexLock& GUARD) {
+  DCHECK(curr_cunit_ != NULL);
+  DCHECK(!curr_cunit_->IsMaterialized());
+
+  // Write bitcode to file when filename is set
+  if (IsBitcodeFileNameAvailable()) {
+    curr_cunit_->WriteBitcodeToFile();
   }
 
   // Materialize the llvm::Module into ELF object file
-  cunit_->Materialize();
-
-  // Increase compilation unit counter
-  ++cunit_counter_;
+  curr_cunit_->Materialize();
 
   // Delete the compilation unit
-  cunit_.reset(NULL);
+  curr_cunit_ = NULL;
 }
 
 
-CompiledMethod* CompilerLLVM::CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
+CompiledMethod* CompilerLLVM::
+CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
   MutexLock GUARD(compiler_lock_);
 
-  EnsureCompilationUnit();
+  EnsureCompilationUnit(GUARD);
 
   UniquePtr<MethodCompiler> method_compiler(
-      new MethodCompiler(cunit_.get(), compiler_, oat_compilation_unit));
+      new MethodCompiler(curr_cunit_, compiler_, oat_compilation_unit));
 
-  CompiledMethod* result = method_compiler->Compile();
-
-  MaterializeCompilationUnitSafePoint();
-
-  return result;
+  return method_compiler->Compile();
 }
 
 
-CompiledMethod* CompilerLLVM::CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
+CompiledMethod* CompilerLLVM::
+CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
   MutexLock GUARD(compiler_lock_);
 
-  EnsureCompilationUnit();
+  EnsureCompilationUnit(GUARD);
 
   UniquePtr<JniCompiler> jni_compiler(
-      new JniCompiler(cunit_.get(), *compiler_, oat_compilation_unit));
+      new JniCompiler(curr_cunit_, *compiler_, oat_compilation_unit));
 
-  CompiledMethod* result = jni_compiler->Compile();
-
-  MaterializeCompilationUnitSafePoint();
-
-  return result;
+  return jni_compiler->Compile();
 }
 
 
 CompiledInvokeStub* CompilerLLVM::CreateInvokeStub(bool is_static,
                                                    char const *shorty) {
-
   MutexLock GUARD(compiler_lock_);
 
-  EnsureCompilationUnit();
+  EnsureCompilationUnit(GUARD);
 
   UniquePtr<UpcallCompiler> upcall_compiler(
-    new UpcallCompiler(cunit_.get(), *compiler_));
+    new UpcallCompiler(curr_cunit_, *compiler_));
 
-  CompiledInvokeStub* result = upcall_compiler->CreateStub(is_static, shorty);
-
-  MaterializeCompilationUnitSafePoint();
-
-  return result;
+  return upcall_compiler->CreateStub(is_static, shorty);
 }
 
 
diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h
index 208edfc..3c653a3 100644
--- a/src/compiler_llvm/compiler_llvm.h
+++ b/src/compiler_llvm/compiler_llvm.h
@@ -56,7 +56,9 @@
 
   ~CompilerLLVM();
 
-  void MaterializeEveryCompilationUnit();
+  void MaterializeIfThresholdReached();
+
+  void MaterializeRemainder();
 
   Compiler* GetCompiler() const {
     return compiler_;
@@ -81,21 +83,25 @@
   CompiledInvokeStub* CreateInvokeStub(bool is_static, char const *shorty);
 
  private:
-  void EnsureCompilationUnit();
+  void EnsureCompilationUnit(MutexLock& GUARD);
 
-  void MaterializeCompilationUnit();
+  void Materialize(MutexLock& GUARD);
 
-  void MaterializeCompilationUnitSafePoint();
+  bool IsBitcodeFileNameAvailable() const {
+    return !bitcode_filename_.empty();
+  }
 
   Compiler* compiler_;
 
+ public:
   Mutex compiler_lock_;
 
+ private:
   InstructionSet insn_set_;
 
-  UniquePtr<CompilationUnit> cunit_;
+  CompilationUnit* curr_cunit_;
 
-  unsigned cunit_counter_;
+  std::vector<CompilationUnit*> cunits_;
 
   std::string elf_filename_;