Compile method one-by-one.

Change-Id: Ic56fb397f3bd6dee32372eb875261a3383eaf30c
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index 38faf61..fdbf575 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -17,6 +17,7 @@
 #include "compilation_unit.h"
 
 #include "compiled_method.h"
+#include "compiler_llvm.h"
 #include "file.h"
 #include "instruction_set.h"
 #include "ir_builder.h"
@@ -47,8 +48,10 @@
 #include <llvm/DerivedTypes.h>
 #include <llvm/LLVMContext.h>
 #include <llvm/Module.h>
+#include <llvm/Object/ObjectFile.h>
 #include <llvm/PassManager.h>
 #include <llvm/Support/Debug.h>
+#include <llvm/Support/ELF.h>
 #include <llvm/Support/FormattedStream.h>
 #include <llvm/Support/ManagedStatic.h>
 #include <llvm/Support/MemoryBuffer.h>
@@ -77,37 +80,6 @@
 
 namespace {
 
-class UpdateFrameSizePass : public llvm::MachineFunctionPass {
- public:
-  static char ID;
-
-  UpdateFrameSizePass() : llvm::MachineFunctionPass(ID), cunit_(NULL) {
-    LOG(FATAL) << "Unexpected instantiation of UpdateFrameSizePass";
-    // NOTE: We have to declare this constructor for llvm::RegisterPass, but
-    // this constructor won't work because we have no information on
-    // CompilationUnit.  Thus, we should place a LOG(FATAL) here.
-  }
-
-  UpdateFrameSizePass(art::compiler_llvm::CompilationUnit* cunit)
-    : llvm::MachineFunctionPass(ID), cunit_(cunit) {
-  }
-
-  virtual bool runOnMachineFunction(llvm::MachineFunction &MF) {
-    cunit_->UpdateFrameSizeInBytes(MF.getFunction(),
-                                   MF.getFrameInfo()->getStackSize());
-    return false;
-  }
-
- private:
-  art::compiler_llvm::CompilationUnit* cunit_;
-};
-
-char UpdateFrameSizePass::ID = 0;
-
-llvm::RegisterPass<UpdateFrameSizePass> reg_update_frame_size_pass_(
-  "update-frame-size", "Update frame size pass", false, false);
-
-
 // TODO: We may need something to manage these passes.
 // TODO: We need high-level IR to analysis and do this at the IRBuilder level.
 class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass {
@@ -167,10 +139,10 @@
 llvm::Module* makeLLVMModuleContents(llvm::Module* module);
 
 
-CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx)
-: cunit_lock_("compilation_unit_lock"), insn_set_(insn_set), elf_idx_(elf_idx),
-  context_(new llvm::LLVMContext()), compiled_methods_map_(new CompiledMethodMap()),
-  mem_usage_(0), num_elf_funcs_(0) {
+CompilationUnit::CompilationUnit(const CompilerLLVM* compiler_llvm,
+                                 size_t cunit_idx)
+: compiler_llvm_(compiler_llvm), cunit_idx_(cunit_idx),
+  context_(new llvm::LLVMContext()) {
 
   // Create the module and include the runtime function declaration
   module_ = new llvm::Module("art", *context_);
@@ -180,7 +152,7 @@
   irb_.reset(new IRBuilder(*context_, *module_));
 
   // We always need a switch case, so just use a normal function.
-  switch(insn_set_) {
+  switch(GetInstructionSet()) {
   default:
     runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
     break;
@@ -205,57 +177,56 @@
 }
 
 
-bool CompilationUnit::Materialize(size_t thread_count) {
-  MutexLock GUARD(cunit_lock_);
-
-  // Materialize the bitcode to elf_image_
-  llvm::raw_string_ostream str_os(elf_image_);
-  bool success = MaterializeToFile(str_os);
-  LOG(INFO) << "Compilation Unit: " << elf_idx_ << (success ? " (done)" : " (failed)");
-
-  // Free the resources
-  context_.reset(NULL);
-  irb_.reset(NULL);
-  module_ = NULL;
-  runtime_support_.reset(NULL);
-  compiled_methods_map_.reset(NULL);
-
-  return success;
+InstructionSet CompilationUnit::GetInstructionSet() const {
+  return compiler_llvm_->GetInstructionSet();
 }
 
 
-void CompilationUnit::RegisterCompiledMethod(const llvm::Function* func,
-                                             CompiledMethod* compiled_method) {
-  MutexLock GUARD(cunit_lock_);
-  compiled_methods_map_->Put(func, compiled_method);
-}
+bool CompilationUnit::Materialize() {
+  std::string elf_image;
 
-
-void CompilationUnit::UpdateFrameSizeInBytes(const llvm::Function* func,
-                                             size_t frame_size_in_bytes) {
-  MutexLock GUARD(cunit_lock_);
-  SafeMap<const llvm::Function*, CompiledMethod*>::iterator iter =
-    compiled_methods_map_->find(func);
-
-  if (iter != compiled_methods_map_->end()) {
-    CompiledMethod* compiled_method = iter->second;
-    compiled_method->SetFrameSizeInBytes(frame_size_in_bytes);
-
-    if (frame_size_in_bytes > 1728u) {
-      LOG(WARNING) << "Huge frame size: " << frame_size_in_bytes
-                   << " elf_idx=" << compiled_method->GetElfIndex()
-                   << " elf_func_idx=" << compiled_method->GetElfFuncIndex();
-    }
+  // Compile and prelink llvm::Module
+  if (!MaterializeToString(elf_image)) {
+    LOG(ERROR) << "Failed to materialize compilation unit " << cunit_idx_;
+    DeleteResources();
+    return false;
   }
+
+#if 0
+  // Dump the ELF image for debugging
+  std::string filename(StringPrintf("%s/Art%zu.elf",
+                                    GetArtCacheOrDie(GetAndroidData()).c_str(),
+                                    cunit_idx_));
+  UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+  output->WriteFully(elf_image.data(), elf_image.size());
+#endif
+
+  // Extract the .text section and prelink the code
+  if (!ExtractCodeAndPrelink(elf_image)) {
+    LOG(ERROR) << "Failed to extract code from compilation unit " << cunit_idx_;
+    DeleteResources();
+    return false;
+  }
+
+  DeleteResources();
+  return true;
 }
 
-bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) {
+
+bool CompilationUnit::MaterializeToString(std::string& str_buffer) {
+  llvm::raw_string_ostream str_os(str_buffer);
+  return MaterializeToRawOStream(str_os);
+}
+
+
+bool CompilationUnit::MaterializeToRawOStream(llvm::raw_ostream& out_stream) {
   // Lookup the LLVM target
   char const* target_triple = NULL;
   char const* target_cpu = "";
   char const* target_attr = NULL;
 
-  switch (insn_set_) {
+  InstructionSet insn_set = GetInstructionSet();
+  switch (insn_set) {
   case kThumb2:
     target_triple = "thumb-none-linux-gnueabi";
     target_cpu = "cortex-a9";
@@ -281,7 +252,7 @@
     break;
 
   default:
-    LOG(FATAL) << "Unknown instruction set: " << insn_set_;
+    LOG(FATAL) << "Unknown instruction set: " << insn_set;
   }
 
   std::string errmsg;
@@ -375,11 +346,6 @@
       return false;
     }
 
-    // FIXME: Unable to run the UpdateFrameSizePass pass since it tries to
-    //        update the value reside in the different address space.
-    // Add pass to update the frame_size_in_bytes_
-    //pm.add(new ::UpdateFrameSizePass(this));
-
     // Run the per-function optimization
     fpm.doInitialization();
     for (llvm::Module::iterator F = module_->begin(), E = module_->end();
@@ -395,5 +361,130 @@
   return true;
 }
 
+
+bool CompilationUnit::ExtractCodeAndPrelink(const std::string& elf_image) {
+  llvm::OwningPtr<llvm::MemoryBuffer> elf_image_buff(
+    llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(elf_image.data(),
+                                                     elf_image.size())));
+
+  llvm::OwningPtr<llvm::object::ObjectFile> elf_file(
+    llvm::object::ObjectFile::createELFObjectFile(elf_image_buff.take()));
+
+  llvm::error_code ec;
+
+  const ProcedureLinkageTable& plt = compiler_llvm_->GetProcedureLinkageTable();
+
+  for (llvm::object::section_iterator
+       sec_iter = elf_file->begin_sections(),
+       sec_end = elf_file->end_sections();
+       sec_iter != sec_end; sec_iter.increment(ec)) {
+
+    CHECK(ec == 0) << "Failed to read section because " << ec.message();
+
+    // Read the section information
+    llvm::StringRef name;
+    uint64_t alignment = 0u;
+    uint64_t size = 0u;
+
+    CHECK(sec_iter->getName(name) == 0);
+    CHECK(sec_iter->getSize(size) == 0);
+    CHECK(sec_iter->getAlignment(alignment) == 0);
+
+    if (name == ".data" || name == ".bss" || name == ".rodata") {
+      if (size > 0) {
+        LOG(FATAL) << "Compilation unit " << cunit_idx_ << " has non-empty "
+                   << name.str() << " section";
+      }
+
+    } else if (name == "" || name == ".rel.text" ||
+               name == ".ARM.attributes" || name == ".symtab" ||
+               name == ".strtab" || name == ".shstrtab") {
+      // We can ignore these sections.  We don't have to copy them into
+      // the result Oat file.
+
+    } else if (name == ".text") {
+      // Ensure the alignment requirement is less than or equal to
+      // kArchAlignment
+      CheckCodeAlign(alignment);
+
+      // Copy the compiled code
+      llvm::StringRef contents;
+      CHECK(sec_iter->getContents(contents) == 0);
+
+      copy(contents.data(),
+           contents.data() + contents.size(),
+           back_inserter(compiled_code_));
+
+      // Prelink the compiled code
+      for (llvm::object::relocation_iterator
+           rel_iter = sec_iter->begin_relocations(),
+           rel_end = sec_iter->end_relocations(); rel_iter != rel_end;
+           rel_iter.increment(ec)) {
+
+        CHECK(ec == 0) << "Failed to read relocation because " << ec.message();
+
+        // Read the relocation information
+        llvm::object::SymbolRef sym_ref;
+        uint64_t rel_offset = 0;
+        uint64_t rel_type = 0;
+        int64_t rel_addend = 0;
+
+        CHECK(rel_iter->getSymbol(sym_ref) == 0);
+        CHECK(rel_iter->getOffset(rel_offset) == 0);
+        CHECK(rel_iter->getType(rel_type) == 0);
+        CHECK(rel_iter->getAdditionalInfo(rel_addend) == 0);
+
+        // Read the symbol related to this relocation fixup
+        llvm::StringRef sym_name;
+        CHECK(sym_ref.getName(sym_name) == 0);
+
+        // Relocate the fixup.
+        // TODO: Support more relocation type.
+        CHECK(rel_type == llvm::ELF::R_ARM_ABS32);
+        CHECK_LE(rel_offset + 4, compiled_code_.size());
+
+        uintptr_t dest_addr = plt.GetEntryAddress(sym_name.str().c_str());
+        uintptr_t final_addr = dest_addr + rel_addend;
+        compiled_code_[rel_offset] = final_addr & 0xff;
+        compiled_code_[rel_offset + 1] = (final_addr >> 8) & 0xff;
+        compiled_code_[rel_offset + 2] = (final_addr >> 16) & 0xff;
+        compiled_code_[rel_offset + 3] = (final_addr >> 24) & 0xff;
+      }
+
+    } else {
+      LOG(WARNING) << "Unexpected section: " << name.str();
+    }
+  }
+
+  return true;
+}
+
+
+// Check whether the align is less than or equal to the code alignment of
+// that architecture.  Since the Oat writer only guarantee that the compiled
+// method being aligned to kArchAlignment, we have no way to align the ELf
+// section if the section alignment is greater than kArchAlignment.
+void CompilationUnit::CheckCodeAlign(uint32_t align) const {
+  InstructionSet insn_set = GetInstructionSet();
+  switch (insn_set) {
+  case kThumb2:
+  case kArm:
+    CHECK_LE(align, static_cast<uint32_t>(kArmAlignment));
+    break;
+
+  case kX86:
+    CHECK_LE(align, static_cast<uint32_t>(kX86Alignment));
+    break;
+
+  case kMips:
+    CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment));
+    break;
+
+  default:
+    LOG(FATAL) << "Unknown instruction set: " << insn_set;
+  }
+}
+
+
 } // namespace compiler_llvm
 } // namespace art
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index d391620..576b65f 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -18,7 +18,6 @@
 #define ART_SRC_COMPILER_LLVM_COMPILATION_UNIT_H_
 
 #include "../mutex.h"
-#include "elf_image.h"
 #include "globals.h"
 #include "instruction_set.h"
 #include "logging.h"
@@ -44,81 +43,52 @@
 namespace art {
 namespace compiler_llvm {
 
+class CompilerLLVM;
 class IRBuilder;
 
 class CompilationUnit {
  public:
-  CompilationUnit(InstructionSet insn_set, size_t elf_idx);
+  CompilationUnit(const CompilerLLVM* compiler_llvm,
+                  size_t cunit_idx);
 
   ~CompilationUnit();
 
-  size_t GetElfIndex() const {
-    return elf_idx_;
+  size_t GetIndex() const {
+    return cunit_idx_;
   }
 
-  InstructionSet GetInstructionSet() const {
-    cunit_lock_.AssertHeld();
-    return insn_set_;
-  }
+  InstructionSet GetInstructionSet() const;
 
   llvm::LLVMContext* GetLLVMContext() const {
-    cunit_lock_.AssertHeld();
     return context_.get();
   }
 
   llvm::Module* GetModule() const {
-    cunit_lock_.AssertHeld();
     return module_;
   }
 
   IRBuilder* GetIRBuilder() const {
-    cunit_lock_.AssertHeld();
     return irb_.get();
   }
 
-  ElfImage GetElfImage() const {
-    MutexLock GUARD(cunit_lock_);
-    CHECK_GT(elf_image_.size(), 0u);
-    return ElfImage(elf_image_);
-  }
-
-  uint16_t AcquireUniqueElfFuncIndex() {
-    cunit_lock_.AssertHeld();
-    CHECK(num_elf_funcs_ < UINT16_MAX);
-    return num_elf_funcs_++;
-  }
-
   void SetBitcodeFileName(const std::string& bitcode_filename) {
-    MutexLock GUARD(cunit_lock_);
     bitcode_filename_ = bitcode_filename;
   }
 
-  bool Materialize(size_t thread_count);
+  bool Materialize();
 
   bool IsMaterialized() const {
-    MutexLock GUARD(cunit_lock_);
     return (context_.get() == NULL);
   }
 
-  bool IsMaterializeThresholdReached() const {
-    MutexLock GUARD(cunit_lock_);
-    return (mem_usage_ > 1000000u); // (threshold: 1 MB)
+  const std::vector<uint8_t>& GetCompiledCode() const {
+    DCHECK(IsMaterialized());
+    return compiled_code_;
   }
 
-  void AddMemUsageApproximation(size_t usage) {
-    MutexLock GUARD(cunit_lock_);
-    mem_usage_ += usage;
-  }
-
-  void RegisterCompiledMethod(const llvm::Function* func, CompiledMethod* cm);
-
-  void UpdateFrameSizeInBytes(const llvm::Function* func, size_t frame_size_in_bytes);
-
-  mutable Mutex cunit_lock_;
-
  private:
-  InstructionSet insn_set_;
-  const size_t elf_idx_;
+  const CompilerLLVM* compiler_llvm_;
+  const size_t cunit_idx_;
 
   UniquePtr<llvm::LLVMContext> context_;
   UniquePtr<IRBuilder> irb_;
@@ -126,15 +96,24 @@
   llvm::Module* module_;
 
   std::string bitcode_filename_;
-  std::string elf_image_;
 
-  typedef SafeMap<const llvm::Function*, CompiledMethod*> CompiledMethodMap;
-  UniquePtr<CompiledMethodMap> compiled_methods_map_;
+  std::vector<uint8_t> compiled_code_;
 
-  size_t mem_usage_;
-  uint16_t num_elf_funcs_;
+  SafeMap<const llvm::Function*, CompiledMethod*> compiled_methods_map_;
 
-  bool MaterializeToFile(llvm::raw_ostream& out_stream);
+  void CheckCodeAlign(uint32_t offset) const;
+
+  void DeleteResources() {
+    module_ = NULL; // Managed by context_
+    context_.reset(NULL);
+    irb_.reset(NULL);
+    runtime_support_.reset(NULL);
+  }
+
+  bool MaterializeToString(std::string& str_buffer);
+  bool MaterializeToRawOStream(llvm::raw_ostream& out_stream);
+
+  bool ExtractCodeAndPrelink(const std::string& elf_image);
 };
 
 } // namespace compiler_llvm
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 6c8188e..b793fbd 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -22,8 +22,6 @@
 #include "compiled_method.h"
 #include "compiler.h"
 #include "dex_cache.h"
-#include "elf_image.h"
-#include "elf_loader.h"
 #include "ir_builder.h"
 #include "jni_compiler.h"
 #include "method_compiler.h"
@@ -95,9 +93,9 @@
 
 
 CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set)
-    : compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
-      insn_set_(insn_set), curr_cunit_(NULL) {
-
+    : compiler_(compiler), insn_set_(insn_set),
+      num_cunits_lock_("compilation unit counter lock"), num_cunits_(0),
+      plt_(insn_set) {
 
   // Initialize LLVM libraries
   pthread_once(&llvm_initialized, InitializeLLVM);
@@ -105,152 +103,21 @@
 
 
 CompilerLLVM::~CompilerLLVM() {
-  STLDeleteElements(&cunits_);
 }
 
 
-void CompilerLLVM::EnsureCompilationUnit() {
-  compiler_lock_.AssertHeld();
-
-  if (curr_cunit_ != NULL) {
-    return;
-  }
-
-  // Allocate compilation unit
-  size_t cunit_idx = cunits_.size();
-  curr_cunit_ = new CompilationUnit(insn_set_, cunit_idx);
-
-  // Register compilation unit
-  cunits_.push_back(curr_cunit_);
-}
-
-
-void CompilerLLVM::MaterializeRemainder() {
-  compiler_lock_.Lock();
-  // Localize
-  CompilationUnit* cunit = curr_cunit_;
-  // Reset the curr_cuit_
-  curr_cunit_ = NULL;
-  compiler_lock_.Unlock();
-
-  if (cunit != NULL) {
-    Materialize(cunit);
-  }
-}
-
-
-void CompilerLLVM::MaterializeIfThresholdReached() {
-  compiler_lock_.Lock();
-  // Localize
-  CompilationUnit* cunit = curr_cunit_;
-
-  if (curr_cunit_ != NULL && curr_cunit_->IsMaterializeThresholdReached()) {
-    // Delete the compilation unit
-    curr_cunit_ = NULL;
-  } else {
-    // Reset cunit such that Materialize() won't be invoked
-    cunit = NULL;
-  }
-
-  compiler_lock_.Unlock();
-
-  if (cunit != NULL) {
-    Materialize(cunit);
-  }
-}
-
-
-void CompilerLLVM::Materialize(CompilationUnit* cunit) {
-  DCHECK(cunit != NULL);
-  DCHECK(!cunit->IsMaterialized());
-
-  // Write bitcode to file when filename is set
-  if (IsBitcodeFileNameAvailable()) {
-    const size_t cunit_idx = cunits_.size();
-    cunit->SetBitcodeFileName(
-      StringPrintf("%s-%zu", bitcode_filename_.c_str(), cunit_idx));
-  }
-
-  // Materialize the llvm::Module into ELF object file
-  cunit->Materialize(compiler_->GetThreadCount());
-
-  // Load ELF image when automatic ELF loading is enabled
-  if (IsAutoElfLoadingEnabled()) {
-    LoadElfFromCompilationUnit(cunit);
-  }
-}
-
-
-void CompilerLLVM::EnableAutoElfLoading() {
-  MutexLock GUARD(compiler_lock_);
-
-  if (IsAutoElfLoadingEnabled()) {
-    // If there is an existing ELF loader, then do nothing.
-    // Because the existing ELF loader may have returned some code address
-    // already.  If we replace the existing ELF loader with
-    // elf_loader_.reset(...), then it is possible to have some dangling
-    // pointer.
-    return;
-  }
-
-  // Create ELF loader and load the materialized CompilationUnit
-  elf_loader_.reset(new ElfLoader());
-
-  for (size_t i = 0; i < cunits_.size(); ++i) {
-    if (cunits_[i]->IsMaterialized()) {
-      LoadElfFromCompilationUnit(cunits_[i]);
-    }
-  }
-}
-
-
-void CompilerLLVM::LoadElfFromCompilationUnit(const CompilationUnit* cunit) {
-  MutexLock GUARD(compiler_lock_);
-  DCHECK(cunit->IsMaterialized()) << cunit->GetElfIndex();
-
-  if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(),
-                              cunit->GetElfImage(),
-                              OatFile::kRelocAll)) {
-    LOG(ERROR) << "Failed to load ELF from compilation unit "
-               << cunit->GetElfIndex();
-  }
-}
-
-
-const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm) const {
-  return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(),
-                                        cm->GetElfFuncIndex());
-}
-
-
-const Method::InvokeStub* CompilerLLVM::
-GetMethodInvokeStubAddr(const CompiledInvokeStub* cm) const {
-  return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(),
-                                              cm->GetElfFuncIndex());
-}
-
-
-std::vector<ElfImage> CompilerLLVM::GetElfImages() const {
-  std::vector<ElfImage> result;
-
-  for (size_t i = 0; i < cunits_.size(); ++i) {
-    result.push_back(cunits_[i]->GetElfImage());
-  }
-
-  return result;
+CompilationUnit* CompilerLLVM::AllocateCompilationUnit() {
+  MutexLock GUARD(num_cunits_lock_);
+  return new CompilationUnit(this, num_cunits_++);
 }
 
 
 CompiledMethod* CompilerLLVM::
 CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
-  MutexLock GUARD(compiler_lock_);
-
-  EnsureCompilationUnit();
-
-  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
+  UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
   UniquePtr<MethodCompiler> method_compiler(
-      new MethodCompiler(curr_cunit_, compiler_, oat_compilation_unit));
+      new MethodCompiler(cunit.get(), compiler_, oat_compilation_unit));
 
   return method_compiler->Compile();
 }
@@ -258,14 +125,10 @@
 
 CompiledMethod* CompilerLLVM::
 CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
-  MutexLock GUARD(compiler_lock_);
-
-  EnsureCompilationUnit();
-
-  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
+  UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
   UniquePtr<JniCompiler> jni_compiler(
-      new JniCompiler(curr_cunit_, *compiler_, oat_compilation_unit));
+      new JniCompiler(cunit.get(), *compiler_, oat_compilation_unit));
 
   return jni_compiler->Compile();
 }
@@ -273,28 +136,20 @@
 
 CompiledInvokeStub* CompilerLLVM::CreateInvokeStub(bool is_static,
                                                    char const *shorty) {
-  MutexLock GUARD(compiler_lock_);
-
-  EnsureCompilationUnit();
-
-  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
+  UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
   UniquePtr<StubCompiler> stub_compiler(
-    new StubCompiler(curr_cunit_, *compiler_));
+    new StubCompiler(cunit.get(), *compiler_));
 
   return stub_compiler->CreateInvokeStub(is_static, shorty);
 }
 
 
 CompiledInvokeStub* CompilerLLVM::CreateProxyStub(char const *shorty) {
-  MutexLock GUARD(compiler_lock_);
-
-  EnsureCompilationUnit();
-
-  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
+  UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
   UniquePtr<StubCompiler> stub_compiler(
-    new StubCompiler(curr_cunit_, *compiler_));
+    new StubCompiler(cunit.get(), *compiler_));
 
   return stub_compiler->CreateProxyStub(shorty);
 }
@@ -324,6 +179,11 @@
   compiler.SetCompilerContext(compiler_llvm);
 }
 
+extern "C" void ArtUnInitCompilerContext(art::Compiler& compiler) {
+  delete ContextOf(compiler);
+  compiler.SetCompilerContext(NULL);
+}
+
 extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
                                                  const art::DexFile::CodeItem* code_item,
                                                  uint32_t access_flags, uint32_t method_idx,
@@ -338,7 +198,6 @@
     method_idx, access_flags);
   art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
   art::CompiledMethod* result = compiler_llvm->CompileDexMethod(&oat_compilation_unit);
-  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
@@ -354,7 +213,6 @@
 
   art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
   art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&oat_compilation_unit);
-  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
@@ -364,7 +222,6 @@
                                                         uint32_t shorty_len) {
   art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
   art::CompiledInvokeStub* result = compiler_llvm->CreateInvokeStub(is_static, shorty);
-  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
@@ -373,7 +230,6 @@
                                                        uint32_t shorty_len) {
   art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
   art::CompiledInvokeStub* result = compiler_llvm->CreateProxyStub(shorty);
-  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
@@ -381,37 +237,3 @@
                                                std::string const& filename) {
   ContextOf(compiler)->SetBitcodeFileName(filename);
 }
-
-extern "C" void compilerLLVMMaterializeRemainder(art::Compiler& compiler) {
-  ContextOf(compiler)->MaterializeRemainder();
-}
-
-extern "C" void compilerLLVMEnableAutoElfLoading(art::Compiler& compiler) {
-  art::compiler_llvm::CompilerLLVM* compiler_llvm =
-      reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
-  return compiler_llvm->EnableAutoElfLoading();
-}
-
-extern "C" const void* compilerLLVMGetMethodCodeAddr(const art::Compiler& compiler,
-                                                     const art::CompiledMethod* cm,
-                                                     const art::Method*) {
-  const art::compiler_llvm::CompilerLLVM* compiler_llvm =
-      reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
-  return compiler_llvm->GetMethodCodeAddr(cm);
-}
-
-extern "C" const art::Method::InvokeStub* compilerLLVMGetMethodInvokeStubAddr(const art::Compiler& compiler,
-                                                                              const art::CompiledInvokeStub* cm,
-                                                                              const art::Method*) {
-  const art::compiler_llvm::CompilerLLVM* compiler_llvm =
-      reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
-  return compiler_llvm->GetMethodInvokeStubAddr(cm);
-}
-
-extern "C" std::vector<art::ElfImage> compilerLLVMGetElfImages(const art::Compiler& compiler) {
-  return ContextOf(compiler)->GetElfImages();
-}
-
-extern "C" void compilerLLVMDispose(art::Compiler& compiler) {
-  delete ContextOf(compiler);
-}
diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h
index 7cc4a0e..24a766e 100644
--- a/src/compiler_llvm/compiler_llvm.h
+++ b/src/compiler_llvm/compiler_llvm.h
@@ -19,10 +19,10 @@
 
 #include "compiler.h"
 #include "dex_file.h"
-#include "elf_image.h"
 #include "instruction_set.h"
 #include "macros.h"
 #include "object.h"
+#include "procedure_linkage_table.h"
 
 #include <UniquePtr.h>
 
@@ -54,7 +54,6 @@
 namespace compiler_llvm {
 
 class CompilationUnit;
-class ElfLoader;
 class IRBuilder;
 
 class CompilerLLVM {
@@ -63,10 +62,6 @@
 
   ~CompilerLLVM();
 
-  void MaterializeIfThresholdReached();
-
-  void MaterializeRemainder();
-
   Compiler* GetCompiler() const {
     return compiler_;
   }
@@ -75,31 +70,10 @@
     return insn_set_;
   }
 
-  size_t GetNumCompilationUnits() const {
-    return cunits_.size();
-  }
-
-  const CompilationUnit* GetCompilationUnit(size_t i) const {
-    return cunits_[i];
-  }
-
   void SetBitcodeFileName(std::string const& filename) {
     bitcode_filename_ = filename;
   }
 
-  void EnableAutoElfLoading();
-
-  bool IsAutoElfLoadingEnabled() const {
-    return (elf_loader_.get() != NULL);
-  }
-
-  const void* GetMethodCodeAddr(const CompiledMethod* cm) const;
-
-  const Method::InvokeStub* GetMethodInvokeStubAddr(
-                                const CompiledInvokeStub* cm) const;
-
-  std::vector<ElfImage> GetElfImages() const;
-
   CompiledMethod* CompileDexMethod(OatCompilationUnit* oat_compilation_unit);
 
   CompiledMethod* CompileNativeMethod(OatCompilationUnit* oat_compilation_unit);
@@ -108,32 +82,29 @@
 
   CompiledInvokeStub* CreateProxyStub(const char *shorty);
 
+  const ProcedureLinkageTable& GetProcedureLinkageTable() const {
+    return plt_;
+  }
+
  private:
-  void EnsureCompilationUnit();
+  CompilationUnit* AllocateCompilationUnit();
 
   void Materialize(CompilationUnit* cunit);
 
-  void LoadElfFromCompilationUnit(const CompilationUnit* cunit);
-
   bool IsBitcodeFileNameAvailable() const {
     return !bitcode_filename_.empty();
   }
 
   Compiler* compiler_;
 
- public:
-  Mutex compiler_lock_;
-
- private:
   InstructionSet insn_set_;
 
-  CompilationUnit* curr_cunit_;
-
-  std::vector<CompilationUnit*> cunits_;
+  Mutex num_cunits_lock_;
+  size_t num_cunits_;
 
   std::string bitcode_filename_;
 
-  UniquePtr<ElfLoader> elf_loader_;
+  ProcedureLinkageTable plt_;
 
   DISALLOW_COPY_AND_ASSIGN(CompilerLLVM);
 };
diff --git a/src/compiler_llvm/elf_loader.cc b/src/compiler_llvm/elf_loader.cc
deleted file mode 100644
index 8432a07..0000000
--- a/src/compiler_llvm/elf_loader.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.
- */
-
-#include "elf_loader.h"
-
-#include "compiled_method.h"
-#include "elf_image.h"
-#include "logging.h"
-#include "oat_file.h"
-#include "object.h"
-#include "runtime_support_llvm.h"
-#include "utils_llvm.h"
-
-#include <android/librsloader.h>
-
-namespace art {
-namespace compiler_llvm {
-
-
-ElfLoader::~ElfLoader() {
-  // Release every ELF object
-  for (size_t i = 0; i < executables_.size(); ++i) {
-    rsloaderDisposeExec(executables_[i]);
-  }
-}
-
-
-bool ElfLoader::LoadElfAt(size_t elf_idx,
-                          const ElfImage& elf_image,
-                          OatFile::RelocationBehavior reloc) {
-  if (elf_idx < executables_.size() && executables_[elf_idx] != NULL) {
-    return false;
-  }
-
-  if (elf_idx >= executables_.size()) {
-    executables_.resize(elf_idx + 1);
-    elf_images_.resize(elf_idx + 1);
-  }
-
-  RSExecRef executable = rsloaderLoadExecutable(elf_image.begin(),
-                                                elf_image.size(),
-                                                reloc == OatFile::kRelocNone ? 1 : 0);
-
-  if (executable == NULL) {
-    LOG(WARNING) << "Failed to load ELF"
-                 << " image: " << static_cast<const void*>(elf_image.begin())
-                 << " size: " << elf_image.size();
-    return false;
-  }
-
-  if (reloc == OatFile::kRelocAll) {
-    if (!rsloaderRelocateExecutable(executable,
-                                    art_find_runtime_support_func, NULL)) {
-      LOG(ERROR) << "Failed to relocate the ELF image";
-      rsloaderDisposeExec(executable);
-      return false;
-    }
-    relocated = true;
-  }
-
-  executables_[elf_idx] = executable;
-  elf_images_[elf_idx] = elf_image;
-  return true;
-}
-
-
-void ElfLoader::RelocateExecutable() {
-  if (relocated) {
-    return;
-  }
-  LOG(INFO) << "Reload ELF for relocate.";
-  for (size_t i = 0; i < executables_.size(); ++i) {
-    if (executables_[i] != NULL) {
-      // TODO: After implement in-place linking, we will no longer need to dispose and reload.
-      rsloaderDisposeExec(executables_[i]);
-      executables_[i] = rsloaderLoadExecutable(elf_images_[i].begin(), elf_images_[i].size(), 0);
-      if (executables_[i] == NULL) {
-        LOG(FATAL) << "Failed to reload ELF image " << i;
-      }
-      if (!rsloaderRelocateExecutable(executables_[i],
-                                      art_find_runtime_support_func, NULL)) {
-        LOG(FATAL) << "Failed to relocate ELF image " << i;
-      }
-    }
-  }
-  relocated = true;
-}
-
-
-const void* ElfLoader::GetMethodCodeAddr(uint16_t elf_idx,
-                                         uint16_t elf_func_idx) const {
-  CHECK_LT(elf_idx, executables_.size());
-  return GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str());
-}
-
-
-const Method::InvokeStub* ElfLoader::
-GetMethodInvokeStubAddr(uint16_t elf_idx, uint16_t elf_func_idx) const {
-  CHECK_LT(elf_idx, executables_.size());
-  return reinterpret_cast<const Method::InvokeStub*>(
-      GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str()));
-}
-
-
-size_t ElfLoader::GetCodeSize(uint16_t elf_idx, uint16_t elf_func_idx) const {
-  CHECK_LT(elf_idx, executables_.size());
-  CHECK(executables_[elf_idx] != NULL);
-  return rsloaderGetSymbolSize(executables_[elf_idx],
-                               ElfFuncName(elf_func_idx).c_str());
-}
-
-
-const void* ElfLoader::GetAddr(size_t elf_idx, const char* sym_name) const {
-  CHECK_LT(elf_idx, executables_.size());
-  CHECK(executables_[elf_idx] != NULL);
-  return rsloaderGetSymbolAddress(executables_[elf_idx], sym_name);
-}
-
-
-} // namespace compiler_llvm
-} // namespace art
diff --git a/src/compiler_llvm/elf_loader.h b/src/compiler_llvm/elf_loader.h
deleted file mode 100644
index 9e8611c..0000000
--- a/src/compiler_llvm/elf_loader.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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_SRC_COMPILER_LLVM_ELF_LOADER_H_
-#define ART_SRC_COMPILER_LLVM_ELF_LOADER_H_
-
-#include "elf_image.h"
-#include "globals.h"
-#include "oat_file.h"
-#include "object.h"
-
-#include <android/librsloader.h>
-#include <vector>
-
-namespace art {
-namespace compiler_llvm {
-
-class ElfLoader {
- public:
-  ElfLoader() : relocated(false) {}
-  ~ElfLoader();
-
-  bool LoadElfAt(size_t elf_idx, const ElfImage& elf_image,
-                 OatFile::RelocationBehavior reloc);
-
-  void RelocateExecutable();
-
-  const void* GetMethodCodeAddr(uint16_t elf_idx,
-                                uint16_t elf_func_idx) const;
-
-  const Method::InvokeStub* GetMethodInvokeStubAddr(uint16_t elf_idx,
-                                                    uint16_t elf_func_idx) const;
-
-  size_t GetCodeSize(uint16_t elf_idx, uint16_t elf_func_idx) const;
-
- private:
-  const void* GetAddr(size_t elf_idx, const char* sym_name) const;
-
-  bool relocated;
-  std::vector<ElfImage> elf_images_;
-  std::vector<RSExecRef> executables_;
-};
-
-
-} // namespace compiler_llvm
-} // namespace art
-
-#endif // ART_SRC_COMPILER_LLVM_ELF_LOADER_H_
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 37ca82f..f4f5be5 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -51,8 +51,7 @@
   class_loader_(oat_compilation_unit->class_loader_),
   dex_cache_(oat_compilation_unit->dex_cache_),
   dex_file_(oat_compilation_unit->dex_file_),
-  method_(dex_cache_->GetResolvedMethod(method_idx_)),
-  elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
+  method_(dex_cache_->GetResolvedMethod(method_idx_)) {
 
   // Check: Ensure that the method is resolved
   CHECK_NE(method_, static_cast<art::Method*>(NULL));
@@ -262,26 +261,16 @@
   // Verify the generated bitcode
   VERIFY_LLVM_FUNCTION(*func_);
 
-  // Add the memory usage approximation of the compilation unit
-  cunit_->AddMemUsageApproximation((sirt_size * 4 + 50) * 50);
-  // NOTE: We will emit 4 LLVM instructions per object argument,
-  // And about 50 instructions for other operations. (Some runtime support will be inlined.)
-  // Beside, we guess that we have to use 50 bytes to represent one LLVM instruction.
+  cunit_->Materialize();
 
-  CompiledMethod* compiled_method =
-      new CompiledMethod(cunit_->GetInstructionSet(),
-                         cunit_->GetElfIndex(),
-                         elf_func_idx_);
-
-  cunit_->RegisterCompiledMethod(func_, compiled_method);
-
-  return compiled_method;
+  return new CompiledMethod(cunit_->GetInstructionSet(),
+                            cunit_->GetCompiledCode());
 }
 
 
 void JniCompiler::CreateFunction() {
   // LLVM function name
-  std::string func_name(ElfFuncName(elf_func_idx_));
+  std::string func_name(ElfFuncName(cunit_->GetIndex()));
 
   // Get function type
   llvm::FunctionType* func_type =
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index eef71db..da8f91a 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -72,8 +72,7 @@
     basic_block_landing_pads_(code_item_->tries_size_, NULL),
     basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
     shadow_frame_(NULL), old_shadow_frame_(NULL),
-    already_pushed_shadow_frame_(NULL), shadow_frame_size_(0),
-    elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
+    already_pushed_shadow_frame_(NULL), shadow_frame_size_(0) {
 }
 
 
@@ -84,7 +83,7 @@
 
 void MethodCompiler::CreateFunction() {
   // LLVM function name
-  std::string func_name(ElfFuncName(elf_func_idx_));
+  std::string func_name(ElfFuncName(cunit_->GetIndex()));
 
   // Get function type
   llvm::FunctionType* func_type =
@@ -3616,20 +3615,10 @@
   // Verify the generated bitcode
   VERIFY_LLVM_FUNCTION(*func_);
 
-  // Add the memory usage approximation of the compilation unit
-  cunit_->AddMemUsageApproximation(code_item_->insns_size_in_code_units_ * 900);
-  // NOTE: From statistics, the bitcode size is 4.5 times bigger than the
-  // Dex file.  Besides, we have to convert the code unit into bytes.
-  // Thus, we got our magic number 9.
+  cunit_->Materialize();
 
-  CompiledMethod* compiled_method =
-    new CompiledMethod(cunit_->GetInstructionSet(),
-                       cunit_->GetElfIndex(),
-                       elf_func_idx_);
-
-  cunit_->RegisterCompiledMethod(func_, compiled_method);
-
-  return compiled_method;
+  return new CompiledMethod(cunit_->GetInstructionSet(),
+                            cunit_->GetCompiledCode());
 }
 
 
diff --git a/src/compiler_llvm/stub_compiler.cc b/src/compiler_llvm/stub_compiler.cc
index 0d64f0d..af05e52 100644
--- a/src/compiler_llvm/stub_compiler.cc
+++ b/src/compiler_llvm/stub_compiler.cc
@@ -48,13 +48,11 @@
 
 CompiledInvokeStub* StubCompiler::CreateInvokeStub(bool is_static,
                                                    char const* shorty) {
-  uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex();
-
   CHECK(shorty != NULL);
   size_t shorty_size = strlen(shorty);
 
   // Function name
-  std::string func_name(ElfFuncName(elf_func_idx));
+  std::string func_name(ElfFuncName(cunit_->GetIndex()));
 
   // Get argument types
   llvm::Type* arg_types[] = {
@@ -186,15 +184,10 @@
   // Verify the generated function
   VERIFY_LLVM_FUNCTION(*func);
 
-  // Add the memory usage approximation of the compilation unit
-  cunit_->AddMemUsageApproximation((shorty_size * 3 + 8) * 50);
-  // NOTE: We will emit 3 LLVM instructions per shorty for the argument,
-  // plus 3 for pointer arithmetic, and 5 for code_addr, retval, ret_addr,
-  // store ret_addr, and ret_void.  Beside, we guess that we have to use
-  // 50 bytes to represent one LLVM instruction.
+  cunit_->Materialize();
 
   return new CompiledInvokeStub(cunit_->GetInstructionSet(),
-                                cunit_->GetElfIndex(), elf_func_idx);
+                                cunit_->GetCompiledCode());
 }
 
 
@@ -202,10 +195,8 @@
   CHECK(shorty != NULL);
   size_t shorty_size = strlen(shorty);
 
-  uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex();
-
   // Function name
-  std::string func_name(ElfFuncName(elf_func_idx));
+  std::string func_name(ElfFuncName(cunit_->GetIndex()));
 
   // Accurate function type
   llvm::Type* accurate_ret_type = irb_.getJType(shorty[0], kAccurate);
@@ -266,11 +257,10 @@
   // Verify the generated function
   VERIFY_LLVM_FUNCTION(*func);
 
-  // Add the memory usage approximation of the compilation unit
-  cunit_->AddMemUsageApproximation((shorty_size + 2) * 50);
+  cunit_->Materialize();
 
   return new CompiledInvokeStub(cunit_->GetInstructionSet(),
-                                cunit_->GetElfIndex(), elf_func_idx);
+                                cunit_->GetCompiledCode());
 }
 
 
diff --git a/src/compiler_llvm/utils_llvm.h b/src/compiler_llvm/utils_llvm.h
index dd35f0a..eb5fd53 100644
--- a/src/compiler_llvm/utils_llvm.h
+++ b/src/compiler_llvm/utils_llvm.h
@@ -32,8 +32,8 @@
 #define VERIFY_LLVM_FUNCTION(func)
 #endif
 
-inline static std::string ElfFuncName(uint16_t elf_func_idx) {
-  return StringPrintf("Art%u", static_cast<unsigned int>(elf_func_idx));
+inline static std::string ElfFuncName(uint16_t idx) {
+  return StringPrintf("Art%u", static_cast<unsigned int>(idx));
 }
 
 class CStringLessThanComparator {