Remove ExtractCodeAndPrelink and switch Portable to MCLinker

Change-Id: Ia2459c7da6b79e0a1c0f1148c6e28ad9cbbe27a2
diff --git a/src/compiler/dex/compiler_ir.h b/src/compiler/dex/compiler_ir.h
index 4ab98a6..f8cdd34 100644
--- a/src/compiler/dex/compiler_ir.h
+++ b/src/compiler/dex/compiler_ir.h
@@ -18,15 +18,18 @@
 #define ART_SRC_COMPILER_DEX_COMPILER_IR_H_
 
 #include <vector>
-#include "dex_instruction.h"
+
+#include <llvm/Module.h>
+
+#include "compiler/dex/quick/codegen.h"
 #include "compiler/driver/compiler_driver.h"
 #include "compiler/driver/dex_compilation_unit.h"
-#include "compiler_utility.h"
-#include "safe_map.h"
-#include "compiler/llvm/ir_builder.h"
 #include "compiler/llvm/intrinsic_helper.h"
-#include "llvm/Module.h"
+#include "compiler/llvm/ir_builder.h"
 #include "compiler_enums.h"
+#include "compiler_utility.h"
+#include "dex_instruction.h"
+#include "safe_map.h"
 
 namespace art {
 
@@ -43,6 +46,9 @@
 struct ArenaBitVector;
 struct LIR;
 class LLVMInfo;
+namespace llvm {
+class LlvmCompilationUnit;
+}  // namespace llvm
 
 struct PromotionMap {
   RegLocationType core_location:3;
@@ -348,6 +354,7 @@
       mstats(NULL),
       checkstats(NULL),
       gen_bitcode(false),
+      llvm_compilation_unit(NULL),
       llvm_info(NULL),
       context(NULL),
       module(NULL),
@@ -507,7 +514,11 @@
   Memstats* mstats;
   Checkstats* checkstats;
   bool gen_bitcode;
+
+  // Fields for Portable
+  llvm::LlvmCompilationUnit* llvm_compilation_unit;
   LLVMInfo* llvm_info;
+  std::string symbol;
   ::llvm::LLVMContext* context;
   ::llvm::Module* module;
   ::llvm::Function* func;
@@ -516,6 +527,7 @@
   ::llvm::BasicBlock* placeholder_bb;
   ::llvm::BasicBlock* entry_bb;
   ::llvm::BasicBlock* entryTarget_bb;
+
   std::string bitcode_filename;
   GrowableList llvm_values;
   int32_t temp_name;
diff --git a/src/compiler/dex/dataflow.cc b/src/compiler/dex/dataflow.cc
index ac3116e..f0f177a 100644
--- a/src/compiler/dex/dataflow.cc
+++ b/src/compiler/dex/dataflow.cc
@@ -2491,10 +2491,7 @@
       LOG(WARNING) << "Unexpected invoke op: " << opcode;
       return false;
   }
-  DexCompilationUnit m_unit(cu->class_loader, cu->class_linker,
-                            *cu->dex_file, cu->code_item,
-                            cu->class_def_idx, cu->method_idx,
-                            cu->access_flags);
+  DexCompilationUnit m_unit(cu);
   // TODO: add a flag so we don't counts the stats for this twice
   uint32_t dex_method_idx = mir->dalvikInsn.vB;
   int vtable_idx;
diff --git a/src/compiler/dex/frontend.cc b/src/compiler/dex/frontend.cc
index 482804c..5b8faf4 100644
--- a/src/compiler/dex/frontend.cc
+++ b/src/compiler/dex/frontend.cc
@@ -14,8 +14,13 @@
  * limitations under the License.
  */
 
+#include <llvm/Support/Threading.h>
+
 #include "compiler/driver/compiler_driver.h"
 #include "compiler_internals.h"
+#if defined(ART_USE_PORTABLE_COMPILER)
+#include "compiler/llvm/llvm_compilation_unit.h"
+#endif
 #include "dataflow.h"
 #include "ssa_transformation.h"
 #include "leb128.h"
@@ -25,8 +30,6 @@
 #include "portable/mir_to_gbc.h"
 #include "quick/mir_to_lir.h"
 
-#include <llvm/Support/Threading.h>
-
 namespace {
 #if !defined(ART_USE_PORTABLE_COMPILER)
   pthread_once_t llvm_multi_init = PTHREAD_ONCE_INIT;
@@ -782,8 +785,11 @@
                                      const DexFile::CodeItem* code_item,
                                      uint32_t access_flags, InvokeType invoke_type,
                                      uint32_t class_def_idx, uint32_t method_idx,
-                                     jobject class_loader, const DexFile& dex_file,
-                                     LLVMInfo* llvm_info)
+                                     jobject class_loader, const DexFile& dex_file
+#if defined(ART_USE_PORTABLE_COMPILER)
+                                     , llvm::LlvmCompilationUnit* llvm_compilation_unit
+#endif
+)
 {
   VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
 
@@ -818,7 +824,11 @@
   if ((compiler_backend == kQuickGBC) || (compiler_backend == kPortable)) {
     cu->gen_bitcode = true;
   }
-  cu->llvm_info = llvm_info;
+#if defined(ART_USE_PORTABLE_COMPILER)
+  cu->llvm_compilation_unit = llvm_compilation_unit;
+  cu->llvm_info = llvm_compilation_unit->GetQuickContext();
+  cu->symbol = llvm_compilation_unit->GetDexCompilationUnit()->GetSymbol();
+#endif
   /* Adjust this value accordingly once inlining is performed */
   cu->num_dalvik_registers = code_item->registers_size_;
   // TODO: set this from command line
@@ -1137,6 +1147,7 @@
   }
 
 
+#if defined(ART_USE_PORTABLE_COMPILER)
   /* Go the LLVM path? */
   if (cu->gen_bitcode) {
     // MIR->Bitcode
@@ -1148,7 +1159,9 @@
     }
     // Bitcode->LIR
     MethodBitcode2LIR(cu.get());
-  } else {
+  } else
+#endif
+  {
     if (special_case != kNoHandler) {
       /*
        * Custom codegen for special cases.  If for any reason the
@@ -1231,13 +1244,20 @@
 CompiledMethod* CompileOneMethod(CompilerDriver& compiler,
                                  const CompilerBackend backend,
                                  const DexFile::CodeItem* code_item,
-                                 uint32_t access_flags, InvokeType invoke_type,
-                                 uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
+                                 uint32_t access_flags,
+                                 InvokeType invoke_type,
+                                 uint32_t class_def_idx,
+                                 uint32_t method_idx,
+                                 jobject class_loader,
                                  const DexFile& dex_file,
-                                 LLVMInfo* llvm_info)
+                                 llvm::LlvmCompilationUnit* llvm_compilation_unit)
 {
   return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, class_def_idx,
-                       method_idx, class_loader, dex_file, llvm_info);
+                       method_idx, class_loader, dex_file
+#if defined(ART_USE_PORTABLE_COMPILER)
+                       , llvm_compilation_unit
+#endif
+                       );
 }
 
 }  // namespace art
diff --git a/src/compiler/dex/portable/mir_to_gbc.cc b/src/compiler/dex/portable/mir_to_gbc.cc
index 8319b4d..e6900df 100644
--- a/src/compiler/dex/portable/mir_to_gbc.cc
+++ b/src/compiler/dex/portable/mir_to_gbc.cc
@@ -33,6 +33,8 @@
 #include "compiler/dex/quick/codegen_util.h"
 #include "compiler/dex/quick/local_optimizations.h"
 #include "compiler/dex/quick/ralloc_util.h"
+#include "compiler/llvm/llvm_compilation_unit.h"
+#include "compiler/llvm/utils_llvm.h"
 
 static const char* kLabelFormat = "%c0x%x_%d";
 static const char kInvalidBlock = 0xff;
@@ -1982,17 +1984,14 @@
 }
 
 static bool CreateFunction(CompilationUnit* cu) {
-  std::string func_name(PrettyMethod(cu->method_idx, *cu->dex_file,
-                                     /* with_signature */ false));
   ::llvm::FunctionType* func_type = GetFunctionType(cu);
-
   if (func_type == NULL) {
     return false;
   }
 
   cu->func = ::llvm::Function::Create(func_type,
-                                       ::llvm::Function::ExternalLinkage,
-                                       func_name, cu->module);
+                                      ::llvm::Function::InternalLinkage,
+                                      cu->symbol, cu->module);
 
   ::llvm::Function::arg_iterator arg_iter(cu->func->arg_begin());
   ::llvm::Function::arg_iterator arg_end(cu->func->arg_end());
diff --git a/src/compiler/dex/quick/codegen.h b/src/compiler/dex/quick/codegen.h
index 63c8460..21290ca 100644
--- a/src/compiler/dex/quick/codegen.h
+++ b/src/compiler/dex/quick/codegen.h
@@ -17,6 +17,8 @@
 #ifndef ART_SRC_COMPILER_DEX_QUICK_CODEGEN_H_
 #define ART_SRC_COMPILER_DEX_QUICK_CODEGEN_H_
 
+#include "invoke_type.h"
+#include "compiler/dex/compiler_enums.h"
 #include "compiler/dex/compiler_ir.h"
 
 namespace art {
@@ -82,6 +84,14 @@
 #define REG_USE12            (REG_USE1 | REG_USE2)
 #define REG_USE23            (REG_USE2 | REG_USE3)
 
+struct BasicBlock;
+struct CallInfo;
+struct CompilationUnit;
+struct LIR;
+struct MIR;
+struct RegLocation;
+struct RegisterInfo;
+
 typedef int (*NextCallInsn)(CompilationUnit*, CallInfo*, int, uint32_t dex_idx,
                             uint32_t method_idx, uintptr_t direct_code,
                             uintptr_t direct_method, InvokeType type);
diff --git a/src/compiler/dex/quick/codegen_util.cc b/src/compiler/dex/quick/codegen_util.cc
index 5f8f6ef..110146f 100644
--- a/src/compiler/dex/quick/codegen_util.cc
+++ b/src/compiler/dex/quick/codegen_util.cc
@@ -54,10 +54,7 @@
 bool FastInstance(CompilationUnit* cu,  uint32_t field_idx,
                   int& field_offset, bool& is_volatile, bool is_put)
 {
-  DexCompilationUnit m_unit(cu->class_loader, cu->class_linker,
-                            *cu->dex_file, cu->code_item,
-                            cu->class_def_idx, cu->method_idx,
-                            cu->access_flags);
+  DexCompilationUnit m_unit(cu);
   return cu->compiler_driver->ComputeInstanceFieldInfo(field_idx, &m_unit,
            field_offset, is_volatile, is_put);
 }
diff --git a/src/compiler/dex/quick/gen_common.cc b/src/compiler/dex/quick/gen_common.cc
index f14d6cf..a289252 100644
--- a/src/compiler/dex/quick/gen_common.cc
+++ b/src/compiler/dex/quick/gen_common.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "codegen_util.h"
+#include "compiler/dex/quick/codegen_util.h"
 #include "compiler/dex/compiler_ir.h"
 #include "oat/runtime/oat_support_entrypoints.h"
 #include "ralloc_util.h"
@@ -354,8 +354,7 @@
   bool is_volatile;
   bool is_referrers_class;
 
-  DexCompilationUnit m_unit(cu->class_loader, cu->class_linker, *cu->dex_file, cu->code_item,
-                            cu->class_def_idx, cu->method_idx, cu->access_flags);
+  DexCompilationUnit m_unit(cu);
 
   bool fast_path =
       cu->compiler_driver->ComputeStaticFieldInfo(field_idx, &m_unit,
@@ -446,10 +445,7 @@
   bool is_volatile;
   bool is_referrers_class;
 
-  DexCompilationUnit m_unit(cu->class_loader, cu->class_linker,
-                            *cu->dex_file, cu->code_item,
-                            cu->class_def_idx, cu->method_idx,
-                            cu->access_flags);
+  DexCompilationUnit m_unit(cu);
 
   bool fast_path =
       cu->compiler_driver->ComputeStaticFieldInfo(field_idx, &m_unit,
diff --git a/src/compiler/dex/quick/gen_invoke.cc b/src/compiler/dex/quick/gen_invoke.cc
index 2c01c19..1ae29be 100644
--- a/src/compiler/dex/quick/gen_invoke.cc
+++ b/src/compiler/dex/quick/gen_invoke.cc
@@ -16,6 +16,7 @@
 
 #include "codegen_util.h"
 #include "compiler/dex/compiler_ir.h"
+#include "invoke_type.h"
 #include "oat/runtime/oat_support_entrypoints.h"
 #include "ralloc_util.h"
 #include "x86/codegen_x86.h"
@@ -1335,10 +1336,7 @@
   // Explicit register usage
   LockCallTemps(cu);
 
-  DexCompilationUnit m_unit(cu->class_loader, cu->class_linker,
-                            *cu->dex_file, cu->code_item,
-                            cu->class_def_idx, cu->method_idx,
-                            cu->access_flags);
+  DexCompilationUnit m_unit(cu);
 
   uint32_t dex_method_idx = info->index;
   int vtable_idx;
diff --git a/src/compiler/dex/quick/gen_loadstore.cc b/src/compiler/dex/quick/gen_loadstore.cc
index b945e31..a7baea4 100644
--- a/src/compiler/dex/quick/gen_loadstore.cc
+++ b/src/compiler/dex/quick/gen_loadstore.cc
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#include "codegen_util.h"
+#include "compiler/dex/quick/codegen_util.h"
 #include "compiler/dex/compiler_ir.h"
+#include "invoke_type.h"
 #include "ralloc_util.h"
 
 namespace art {
diff --git a/src/compiler/dex/quick/ralloc_util.cc b/src/compiler/dex/quick/ralloc_util.cc
index a782264..5b7de2c 100644
--- a/src/compiler/dex/quick/ralloc_util.cc
+++ b/src/compiler/dex/quick/ralloc_util.cc
@@ -16,10 +16,10 @@
 
 /* This file contains register alloction support. */
 
-#include "codegen_util.h"
 #include "compiler/dex/compiler_ir.h"
 #include "compiler/dex/compiler_utility.h"
 #include "compiler/dex/dataflow.h"
+#include "compiler/dex/quick/codegen_util.h"
 #include "ralloc_util.h"
 
 namespace art {
diff --git a/src/compiler/dex/write_elf.cc b/src/compiler/dex/write_elf.cc
index a78d98e..7e3d512 100644
--- a/src/compiler/dex/write_elf.cc
+++ b/src/compiler/dex/write_elf.cc
@@ -19,12 +19,17 @@
 
 namespace art {
 class CompilerDriver;
+class DexFile;
 }  // namespace art
 
 extern "C" bool WriteElf(art::CompilerDriver& driver,
+                         const std::string* host_prefix,
+                         bool is_host,
+                         const std::vector<const art::DexFile*>& dex_files,
                          std::vector<uint8_t>& oat_contents,
-                         art::File* file) {
-  return art::ElfWriter::Create(file, oat_contents, driver);
+                         art::File* file)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return art::ElfWriter::Create(file, oat_contents, dex_files, host_prefix, is_host, driver);
 }
 extern "C" bool FixupElf(art::File* file, uintptr_t oat_data_begin) {
   return art::ElfWriter::Fixup(file, oat_data_begin);
@@ -34,3 +39,6 @@
                                      size_t& oat_data_offset) {
   art::ElfWriter::GetOatElfInformation(file, oat_loaded_size, oat_data_offset);
 }
+extern "C" bool StripElf(art::File* file) {
+  return art::ElfWriter::Strip(file);
+}
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index a28ba18..8856a00 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -1678,7 +1678,7 @@
   const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx), &shorty_len);
   bool is_static = (access_flags & kAccStatic) != 0;
   std::string key(MakeInvokeStubKey(is_static, shorty));
-  const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(key);
+  CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(key);
   if (compiled_invoke_stub == NULL) {
     compiled_invoke_stub = (*create_invoke_stub_)(*this, is_static, shorty, shorty_len);
     CHECK(compiled_invoke_stub != NULL);
@@ -1686,7 +1686,7 @@
   }
 
   if ((compiler_backend_ == kPortable) && !is_static) {
-    const CompiledInvokeStub* compiled_proxy_stub = FindProxyStub(shorty);
+    CompiledInvokeStub* compiled_proxy_stub = FindProxyStub(shorty);
     if (compiled_proxy_stub == NULL) {
       compiled_proxy_stub = (*create_proxy_stub_)(*this, shorty, shorty_len);
       CHECK(compiled_proxy_stub != NULL);
@@ -1701,12 +1701,12 @@
   }
 }
 
-const CompiledInvokeStub* CompilerDriver::FindInvokeStub(bool is_static, const char* shorty) const {
+CompiledInvokeStub* CompilerDriver::FindInvokeStub(bool is_static, const char* shorty) const {
   const std::string key(MakeInvokeStubKey(is_static, shorty));
   return FindInvokeStub(key);
 }
 
-const CompiledInvokeStub* CompilerDriver::FindInvokeStub(const std::string& key) const {
+CompiledInvokeStub* CompilerDriver::FindInvokeStub(const std::string& key) const {
   MutexLock mu(Thread::Current(), compiled_invoke_stubs_lock_);
   InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
   if (it == compiled_invoke_stubs_.end()) {
@@ -1717,8 +1717,7 @@
   }
 }
 
-void CompilerDriver::InsertInvokeStub(const std::string& key,
-                                      const CompiledInvokeStub* compiled_invoke_stub) {
+void CompilerDriver::InsertInvokeStub(const std::string& key, CompiledInvokeStub* compiled_invoke_stub) {
   MutexLock mu(Thread::Current(), compiled_invoke_stubs_lock_);
   InvokeStubTable::iterator it = compiled_invoke_stubs_.find(key);
   if (it != compiled_invoke_stubs_.end()) {
@@ -1729,7 +1728,7 @@
   }
 }
 
-const CompiledInvokeStub* CompilerDriver::FindProxyStub(const char* shorty) const {
+CompiledInvokeStub* CompilerDriver::FindProxyStub(const char* shorty) const {
   MutexLock mu(Thread::Current(), compiled_proxy_stubs_lock_);
   ProxyStubTable::const_iterator it = compiled_proxy_stubs_.find(shorty);
   if (it == compiled_proxy_stubs_.end()) {
@@ -1740,8 +1739,7 @@
   }
 }
 
-void CompilerDriver::InsertProxyStub(const char* shorty,
-                                     const CompiledInvokeStub* compiled_proxy_stub) {
+void CompilerDriver::InsertProxyStub(const char* shorty, CompiledInvokeStub* compiled_proxy_stub) {
   MutexLock mu(Thread::Current(), compiled_proxy_stubs_lock_);
   InvokeStubTable::iterator it = compiled_proxy_stubs_.find(shorty);
   if (it != compiled_proxy_stubs_.end()) {
@@ -1795,11 +1793,21 @@
   return freezing_constructor_classes_.count(ClassReference(dex_file, class_def_index)) != 0;
 }
 
-bool CompilerDriver::WriteElf(std::vector<uint8_t>& oat_contents, File* file) {
-  typedef bool (*WriteElfFn)(CompilerDriver&, std::vector<uint8_t>&, File*);
+bool CompilerDriver::WriteElf(const std::string* host_prefix,
+                              bool is_host,
+                              const std::vector<const DexFile*>& dex_files,
+                              std::vector<uint8_t>& oat_contents,
+                              File* file) {
+  typedef bool (*WriteElfFn)(CompilerDriver&,
+                             const std::string* host_prefix,
+                             bool is_host,
+                             const std::vector<const DexFile*>& dex_files,
+                             std::vector<uint8_t>&,
+                             File*);
   WriteElfFn WriteElf =
     FindFunction<WriteElfFn>(MakeCompilerSoName(compiler_backend_), compiler_library_, "WriteElf");
-  return WriteElf(*this, oat_contents, file);
+  Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
+  return WriteElf(*this, host_prefix, is_host, dex_files, oat_contents, file);
 }
 
 bool CompilerDriver::FixupElf(File* file, uintptr_t oat_data_begin) const {
@@ -1819,11 +1827,18 @@
   GetOatElfInformation(file, oat_loaded_size, oat_data_offset);
 }
 
+bool CompilerDriver::StripElf(File* file) const {
+  typedef bool (*StripElfFn)(File*);
+  StripElfFn StripElf =
+    FindFunction<StripElfFn>(MakeCompilerSoName(compiler_backend_), compiler_library_, "StripElf");
+  return StripElf(file);
+}
+
 void CompilerDriver::InstructionSetToLLVMTarget(InstructionSet instruction_set,
                                                 std::string& target_triple,
                                                 std::string& target_cpu,
                                                 std::string& target_attr) {
-    switch (instruction_set) {
+  switch (instruction_set) {
     case kThumb2:
       target_triple = "thumb-none-linux-gnueabi";
       target_cpu = "cortex-a9";
diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h
index 49bc473..7f67c21 100644
--- a/src/compiler/driver/compiler_driver.h
+++ b/src/compiler/driver/compiler_driver.h
@@ -123,11 +123,11 @@
   CompiledMethod* GetCompiledMethod(MethodReference ref) const
       LOCKS_EXCLUDED(compiled_methods_lock_);
 
-  const CompiledInvokeStub* FindInvokeStub(bool is_static, const char* shorty) const;
-  const CompiledInvokeStub* FindInvokeStub(const std::string& key) const
+  CompiledInvokeStub* FindInvokeStub(bool is_static, const char* shorty) const;
+  CompiledInvokeStub* FindInvokeStub(const std::string& key) const
       LOCKS_EXCLUDED(compiled_invoke_stubs_lock_);
 
-  const CompiledInvokeStub* FindProxyStub(const char* shorty) const;
+  CompiledInvokeStub* FindProxyStub(const char* shorty) const;
 
   void AddRequiresConstructorBarrier(Thread* self, const DexFile* dex_file, size_t class_def_index);
   bool RequiresConstructorBarrier(Thread* self, const DexFile* dex_file, size_t class_def_index);
@@ -186,10 +186,15 @@
 
   void SetBitcodeFileName(std::string const& filename);
 
-  // TODO: remove when libart links against LLVM (when separate compiler library is gone)
-  bool WriteElf(std::vector<uint8_t>& oat_contents, File* file);
+  // TODO: remove these Elf wrappers when libart links against LLVM (when separate compiler library is gone)
+  bool WriteElf(const std::string* host_prefix,
+                bool is_host,
+                const std::vector<const DexFile*>& dex_files,
+                std::vector<uint8_t>& oat_contents,
+                File* file);
   bool FixupElf(File* file, uintptr_t oat_data_begin) const;
   void GetOatElfInformation(File* file, size_t& oat_loaded_size, size_t& oat_data_offset) const;
+  bool StripElf(File* file) const;
 
   // TODO: move to a common home for llvm helpers once quick/portable are merged
   static void InstructionSetToLLVMTarget(InstructionSet instruction_set,
@@ -316,10 +321,10 @@
   static void CompileClass(const ParallelCompilationManager* context, size_t class_def_index)
       LOCKS_EXCLUDED(Locks::mutator_lock_);
 
-  void InsertInvokeStub(const std::string& key, const CompiledInvokeStub* compiled_invoke_stub)
+  void InsertInvokeStub(const std::string& key, CompiledInvokeStub* compiled_invoke_stub)
       LOCKS_EXCLUDED(compiled_invoke_stubs_lock_);
 
-  void InsertProxyStub(const char* shorty, const CompiledInvokeStub* compiled_proxy_stub);
+  void InsertProxyStub(const char* shorty, CompiledInvokeStub* compiled_proxy_stub);
 
   std::vector<const PatchInformation*> code_to_patch_;
   std::vector<const PatchInformation*> methods_to_patch_;
@@ -342,12 +347,12 @@
   mutable Mutex compiled_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   MethodTable compiled_methods_ GUARDED_BY(compiled_methods_lock_);
 
-  typedef SafeMap<std::string, const CompiledInvokeStub*> InvokeStubTable;
+  typedef SafeMap<std::string, CompiledInvokeStub*> InvokeStubTable;
   // Invocation stubs created to allow invocation of the compiled methods.
   mutable Mutex compiled_invoke_stubs_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   InvokeStubTable compiled_invoke_stubs_ GUARDED_BY(compiled_invoke_stubs_lock_);
 
-  typedef SafeMap<std::string, const CompiledInvokeStub*> ProxyStubTable;
+  typedef SafeMap<std::string, CompiledInvokeStub*> ProxyStubTable;
   // Proxy stubs created for proxy invocation delegation
   mutable Mutex compiled_proxy_stubs_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   ProxyStubTable compiled_proxy_stubs_ GUARDED_BY(compiled_proxy_stubs_lock_);
diff --git a/src/compiler/driver/compiler_driver_test.cc b/src/compiler/driver/compiler_driver_test.cc
index 19ccb35..dee448d 100644
--- a/src/compiler/driver/compiler_driver_test.cc
+++ b/src/compiler/driver/compiler_driver_test.cc
@@ -132,6 +132,7 @@
 }
 
 TEST_F(CompilerDriverTest, AbstractMethodErrorStub) {
+  TEST_DISABLED_FOR_PORTABLE();
   jobject class_loader;
   {
     ScopedObjectAccess soa(Thread::Current());
diff --git a/src/compiler/driver/dex_compilation_unit.cc b/src/compiler/driver/dex_compilation_unit.cc
new file mode 100644
index 0000000..67987fa
--- /dev/null
+++ b/src/compiler/driver/dex_compilation_unit.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 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 "dex_compilation_unit.h"
+
+#include "base/stringprintf.h"
+#include "compiler/dex/compiler_ir.h"
+#include "utils.h"
+
+namespace art {
+
+DexCompilationUnit::DexCompilationUnit(CompilationUnit* cu)
+    : cu_(cu),
+      class_loader_(cu->class_loader),
+      class_linker_(cu->class_linker),
+      dex_file_(cu->dex_file),
+      code_item_(cu->code_item),
+      class_def_idx_(cu->class_def_idx),
+      dex_method_idx_(cu->method_idx),
+      access_flags_(cu->access_flags),
+      symbol_(StringPrintf("dex_%s", MangleForJni(PrettyMethod(dex_method_idx_, *dex_file_)).c_str())) {
+}
+
+DexCompilationUnit:: DexCompilationUnit(CompilationUnit* cu,
+                                        jobject class_loader,
+                                        ClassLinker* class_linker,
+                                        const DexFile& dex_file,
+                                        const DexFile::CodeItem* code_item,
+                                        uint32_t class_def_idx,
+                                        uint32_t method_idx,
+                                        uint32_t access_flags)
+    : cu_(cu),
+      class_loader_(class_loader),
+      class_linker_(class_linker),
+      dex_file_(&dex_file),
+      code_item_(code_item),
+      class_def_idx_(class_def_idx),
+      dex_method_idx_(method_idx),
+      access_flags_(access_flags),
+      symbol_(StringPrintf("dex_%s", MangleForJni(PrettyMethod(dex_method_idx_, *dex_file_)).c_str())) {
+}
+
+} // namespace art
diff --git a/src/compiler/driver/dex_compilation_unit.h b/src/compiler/driver/dex_compilation_unit.h
index 6a0218d..0fc1123 100644
--- a/src/compiler/driver/dex_compilation_unit.h
+++ b/src/compiler/driver/dex_compilation_unit.h
@@ -17,26 +17,29 @@
 #ifndef ART_SRC_COMPILER_DEX_DEX_COMPILATION_UNIT_H_
 #define ART_SRC_COMPILER_DEX_DEX_COMPILATION_UNIT_H_
 
-#include "dex_file.h"
-
 #include <stdint.h>
 
+#include "dex_file.h"
+#include "jni.h"
+
 namespace art {
 namespace mirror {
 class ClassLoader;
 class DexCache;
 }  // namespace mirror
 class ClassLinker;
-class DexFile;
+class CompilationUnit;
 
 class DexCompilationUnit {
  public:
-  DexCompilationUnit(jobject class_loader, ClassLinker* class_linker, const DexFile& dex_file,
-                     const DexFile::CodeItem* code_item, uint32_t class_def_idx,
-                     uint32_t method_idx, uint32_t access_flags)
-      : class_loader_(class_loader), class_linker_(class_linker), dex_file_(&dex_file),
-        code_item_(code_item), class_def_idx_(class_def_idx), dex_method_idx_(method_idx),
-        access_flags_(access_flags) {
+  DexCompilationUnit(CompilationUnit* cu);
+
+  DexCompilationUnit(CompilationUnit* cu, jobject class_loader, ClassLinker* class_linker,
+                     const DexFile& dex_file, const DexFile::CodeItem* code_item,
+                     uint32_t class_def_idx, uint32_t method_idx, uint32_t access_flags);
+
+  CompilationUnit* GetCompilationUnit() const {
+    return cu_;
   }
 
   jobject GetClassLoader() const {
@@ -89,8 +92,15 @@
     return ((access_flags_ & kAccSynchronized) != 0);
   }
 
+  const std::string& GetSymbol() const {
+    return symbol_;
+  }
+
  private:
+  CompilationUnit* cu_;
+
   const jobject class_loader_;
+
   ClassLinker* const class_linker_;
 
   const DexFile* const dex_file_;
@@ -99,6 +109,8 @@
   const uint32_t class_def_idx_;
   const uint32_t dex_method_idx_;
   const uint32_t access_flags_;
+
+  const std::string symbol_;
 };
 
 } // namespace art
diff --git a/src/compiler/invoke_stubs/portable/stub_compiler.cc b/src/compiler/invoke_stubs/portable/stub_compiler.cc
index 5c314e6..ec6dc30 100644
--- a/src/compiler/invoke_stubs/portable/stub_compiler.cc
+++ b/src/compiler/invoke_stubs/portable/stub_compiler.cc
@@ -52,7 +52,7 @@
   size_t shorty_size = strlen(shorty);
 
   // Function name
-  std::string func_name(ElfFuncName(cunit_->GetIndex()));
+  std::string func_name(StringPrintf("invoke_stub_%s%s", shorty, is_static ? "_static" : ""));
 
   // Get argument types
   ::llvm::Type* arg_types[] = {
@@ -69,8 +69,8 @@
 
   // Create function
   ::llvm::Function* func =
-    ::llvm::Function::Create(func_type, ::llvm::Function::ExternalLinkage,
-                           func_name, module_);
+    ::llvm::Function::Create(func_type, ::llvm::Function::InternalLinkage,
+                             func_name, module_);
 
 
   // Create basic block for the body of this function
@@ -185,7 +185,8 @@
   cunit_->Materialize();
 
   return new CompiledInvokeStub(cunit_->GetInstructionSet(),
-                                cunit_->GetCompiledCode());
+                                cunit_->GetElfObject(),
+                                func_name);
 }
 
 
@@ -194,7 +195,7 @@
   size_t shorty_size = strlen(shorty);
 
   // Function name
-  std::string func_name(ElfFuncName(cunit_->GetIndex()));
+  std::string func_name(StringPrintf("proxy_stub_%s", shorty));
 
   // Accurate function type
   ::llvm::Type* accurate_ret_type = irb_.getJType(shorty[0]);
@@ -212,7 +213,7 @@
 
   // Create function
   ::llvm::Function* func =
-    ::llvm::Function::Create(accurate_func_type, ::llvm::Function::ExternalLinkage,
+    ::llvm::Function::Create(accurate_func_type, ::llvm::Function::InternalLinkage,
                              func_name, module_);
   switch(shorty[0]) {
     case 'Z':
@@ -271,7 +272,8 @@
   cunit_->Materialize();
 
   return new CompiledInvokeStub(cunit_->GetInstructionSet(),
-                                cunit_->GetCompiledCode());
+                                cunit_->GetElfObject(),
+                                func_name);
 }
 
 
diff --git a/src/compiler/jni/jni_compiler_test.cc b/src/compiler/jni/jni_compiler_test.cc
index 4ed7898..5176752 100644
--- a/src/compiler/jni/jni_compiler_test.cc
+++ b/src/compiler/jni/jni_compiler_test.cc
@@ -130,6 +130,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "foo", "()V",
                reinterpret_cast<void*>(&Java_MyClassNatives_foo));
 
@@ -141,6 +142,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "bar", "(I)I",
                NULL /* calling through stub will link with &Java_MyClassNatives_bar */);
 
@@ -155,6 +157,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "sbar", "(I)I",
                NULL /* calling through stub will link with &Java_MyClassNatives_sbar */);
 
@@ -181,6 +184,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooI", "(I)I",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooI));
 
@@ -206,6 +210,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooII", "(II)I",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooII));
 
@@ -232,6 +237,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooJJ", "(JJ)J",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ));
 
@@ -259,6 +265,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooDD", "(DD)D",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooDD));
 
@@ -287,6 +294,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRun_fooJJ_synchronized) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ_synchronized));
 
@@ -319,6 +327,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooIOO",
                "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooIOO));
@@ -362,6 +371,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "fooSII", "(II)I",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooSII));
 
@@ -384,6 +394,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "fooSDD", "(DD)D",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooSDD));
 
@@ -420,6 +431,7 @@
 
 
 TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "fooSIOO",
                "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooSIOO));
@@ -470,6 +482,7 @@
 }
 
 TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "fooSSIOO",
                "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooSSIOO));
@@ -506,6 +519,7 @@
 }
 
 TEST_F(JniCompilerTest, ExceptionHandling) {
+  TEST_DISABLED_FOR_PORTABLE();
   {
     ASSERT_FALSE(runtime_->IsStarted());
     ScopedObjectAccess soa(Thread::Current());
@@ -585,6 +599,7 @@
 }
 
 TEST_F(JniCompilerTest, NativeStackTraceElement) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooI", "(I)I",
                reinterpret_cast<void*>(&Java_MyClassNatives_nativeUpCall));
   jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
@@ -596,6 +611,7 @@
 }
 
 TEST_F(JniCompilerTest, ReturnGlobalRef) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
                reinterpret_cast<void*>(&Java_MyClassNatives_fooO));
   jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
@@ -613,6 +629,7 @@
 }
 
 TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
   // 1000 invocations of a method that adds 10 local references
   for (int i = 0; i < 1000; i++) {
@@ -631,6 +648,7 @@
 }
 
 TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
                reinterpret_cast<void*>(&my_arraycopy));
   env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
@@ -646,6 +664,7 @@
 }
 
 TEST_F(JniCompilerTest, CompareAndSwapInt) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
                reinterpret_cast<void*>(&my_casi));
   jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
@@ -662,6 +681,7 @@
 }
 
 TEST_F(JniCompilerTest, GetText) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "getText", "(JLjava/lang/Object;JLjava/lang/Object;)I",
                reinterpret_cast<void*>(&my_gettext));
   jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 0x12345678ABCDEF88ll, jobj_,
@@ -670,6 +690,7 @@
 }
 
 TEST_F(JniCompilerTest, GetSinkPropertiesNative) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", NULL);
   // This space intentionally left blank. Just testing compilation succeeds.
 }
@@ -685,6 +706,7 @@
 }
 
 TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Instance) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "instanceMethodThatShouldReturnClass", "()Ljava/lang/Class;",
                reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldReturnClass));
 
@@ -702,6 +724,7 @@
 }
 
 TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Static) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "staticMethodThatShouldReturnClass", "()Ljava/lang/Class;",
                reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldReturnClass));
 
@@ -727,6 +750,7 @@
 }
 
 TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Instance) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(false, "instanceMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
                reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldTakeClass));
 
@@ -737,6 +761,7 @@
 }
 
 TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Static) {
+  TEST_DISABLED_FOR_PORTABLE();
   SetUpForTest(true, "staticMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
                reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldTakeClass));
 
diff --git a/src/compiler/jni/portable/jni_compiler.cc b/src/compiler/jni/portable/jni_compiler.cc
index 1a4ad95..8495150 100644
--- a/src/compiler/jni/portable/jni_compiler.cc
+++ b/src/compiler/jni/portable/jni_compiler.cc
@@ -64,7 +64,10 @@
   char const return_shorty = dex_file->GetMethodShorty(method_id)[0];
   ::llvm::Value* this_object_or_class_object;
 
-  CreateFunction();
+  uint32_t method_idx = dex_compilation_unit_->GetDexMethodIndex();
+  std::string func_name(StringPrintf("jni_%s",
+                                     MangleForJni(PrettyMethod(method_idx, *dex_file)).c_str()));
+  CreateFunction(func_name);
 
   // Set argument name
   ::llvm::Function::arg_iterator arg_begin(func_->arg_begin());
@@ -233,13 +236,13 @@
   cunit_->Materialize();
 
   return new CompiledMethod(cunit_->GetInstructionSet(),
-                            cunit_->GetCompiledCode());
+                            cunit_->GetElfObject(),
+                            func_name);
 }
 
 
-void JniCompiler::CreateFunction() {
-  // LLVM function name
-  std::string func_name(ElfFuncName(cunit_->GetIndex()));
+void JniCompiler::CreateFunction(const std::string& func_name) {
+  CHECK_NE(0U, func_name.size());
 
   const bool is_static = dex_compilation_unit_->IsStatic();
 
@@ -248,8 +251,8 @@
     GetFunctionType(dex_compilation_unit_->GetDexMethodIndex(), is_static, false);
 
   // Create function
-  func_ = ::llvm::Function::Create(func_type, ::llvm::Function::ExternalLinkage,
-                                 func_name, module_);
+  func_ = ::llvm::Function::Create(func_type, ::llvm::Function::InternalLinkage,
+                                   func_name, module_);
 
   // Create basic block
   ::llvm::BasicBlock* basic_block = ::llvm::BasicBlock::Create(*context_, "B0", func_);
diff --git a/src/compiler/jni/portable/jni_compiler.h b/src/compiler/jni/portable/jni_compiler.h
index 3df81a5..a04277c 100644
--- a/src/compiler/jni/portable/jni_compiler.h
+++ b/src/compiler/jni/portable/jni_compiler.h
@@ -19,6 +19,8 @@
 
 #include <stdint.h>
 
+#include <string>
+
 namespace art {
   class ClassLinker;
   class CompiledMethod;
@@ -58,10 +60,10 @@
   CompiledMethod* Compile();
 
  private:
-  void CreateFunction();
+  void CreateFunction(const std::string& symbol);
 
   ::llvm::FunctionType* GetFunctionType(uint32_t method_idx,
-                                      bool is_static, bool is_target_function);
+                                        bool is_static, bool is_target_function);
 
  private:
   LlvmCompilationUnit* cunit_;
diff --git a/src/compiler/llvm/compiler_llvm.cc b/src/compiler/llvm/compiler_llvm.cc
index 1c9a494..be1730f 100644
--- a/src/compiler/llvm/compiler_llvm.cc
+++ b/src/compiler/llvm/compiler_llvm.cc
@@ -16,14 +16,15 @@
 
 #include "compiler_llvm.h"
 
-#include "base/stl_util.h"
 #include "backend_options.h"
+#include "base/stl_util.h"
 #include "class_linker.h"
 #include "compiled_method.h"
 #include "compiler/driver/compiler_driver.h"
 #include "compiler/driver/dex_compilation_unit.h"
 #include "compiler/invoke_stubs/portable/stub_compiler.h"
 #include "compiler/jni/portable/jni_compiler.h"
+#include "globals.h"
 #include "ir_builder.h"
 #include "llvm_compilation_unit.h"
 #include "oat_file.h"
@@ -43,7 +44,7 @@
                       uint32_t access_flags, InvokeType invoke_type,
                       uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
                       const DexFile& dex_file,
-                      LLVMInfo* llvm_info);
+                      llvm::LlvmCompilationUnit* llvm_info);
 }
 
 namespace llvm {
@@ -65,17 +66,17 @@
   art::llvm::InitialBackendOptions();
 
   // Initialize LLVM target, MC subsystem, asm printer, and asm parser.
-#if defined(ART_TARGET)
-  // Don't initialize all targets on device. Just initialize the device's native target
-  llvm::InitializeNativeTarget();
-  llvm::InitializeNativeTargetAsmPrinter();
-  llvm::InitializeNativeTargetAsmParser();
-#else
-  llvm::InitializeAllTargets();
-  llvm::InitializeAllTargetMCs();
-  llvm::InitializeAllAsmPrinters();
-  llvm::InitializeAllAsmParsers();
-#endif
+  if (art::kIsTargetBuild) {
+    // Don't initialize all targets on device. Just initialize the device's native target
+    llvm::InitializeNativeTarget();
+    llvm::InitializeNativeTargetAsmPrinter();
+    llvm::InitializeNativeTargetAsmParser();
+  } else {
+    llvm::InitializeAllTargets();
+    llvm::InitializeAllTargetMCs();
+    llvm::InitializeAllAsmPrinters();
+    llvm::InitializeAllAsmParsers();
+  }
 
   // Initialize LLVM optimization passes
   llvm::PassRegistry &registry = *llvm::PassRegistry::getPassRegistry();
@@ -110,8 +111,7 @@
 
 CompilerLLVM::CompilerLLVM(CompilerDriver* driver, InstructionSet insn_set)
     : compiler_driver_(driver), insn_set_(insn_set),
-      num_cunits_lock_("compilation unit counter lock"), num_cunits_(0),
-      plt_(insn_set) {
+      next_cunit_id_lock_("compilation unit id lock"), next_cunit_id_(1) {
 
   // Initialize LLVM libraries
   pthread_once(&llvm_initialized, InitializeLLVM);
@@ -123,10 +123,12 @@
 
 
 LlvmCompilationUnit* CompilerLLVM::AllocateCompilationUnit() {
-  MutexLock GUARD(Thread::Current(), num_cunits_lock_);
-  LlvmCompilationUnit* cunit = new LlvmCompilationUnit(this, ++num_cunits_);
+  MutexLock GUARD(Thread::Current(), next_cunit_id_lock_);
+  LlvmCompilationUnit* cunit = new LlvmCompilationUnit(this, next_cunit_id_++);
   if (!bitcode_filename_.empty()) {
-    cunit->SetBitcodeFileName(StringPrintf("%s-%zu", bitcode_filename_.c_str(), cunit->GetIndex()));
+    cunit->SetBitcodeFileName(StringPrintf("%s-%zu",
+                                           bitcode_filename_.c_str(),
+                                           cunit->GetCompilationUnitId()));
   }
   return cunit;
 }
@@ -136,8 +138,8 @@
 CompileDexMethod(DexCompilationUnit* dex_compilation_unit, InvokeType invoke_type) {
   UniquePtr<LlvmCompilationUnit> cunit(AllocateCompilationUnit());
 
-  std::string methodName(PrettyMethod(dex_compilation_unit->GetDexMethodIndex(),
-                                      *dex_compilation_unit->GetDexFile()));
+  cunit->SetDexCompilationUnit(dex_compilation_unit);
+  cunit->SetCompiler(compiler_driver_);
   // TODO: consolidate ArtCompileMethods
   CompileOneMethod(*compiler_driver_,
                    kPortable,
@@ -148,19 +150,16 @@
                    dex_compilation_unit->GetDexMethodIndex(),
                    dex_compilation_unit->GetClassLoader(),
                    *dex_compilation_unit->GetDexFile(),
-                   cunit->GetQuickContext()
-  );
-
-  cunit->SetCompiler(compiler_driver_);
-  cunit->SetDexCompilationUnit(dex_compilation_unit);
+                   cunit.get());
 
   cunit->Materialize();
 
   CompilerDriver::MethodReference mref(dex_compilation_unit->GetDexFile(),
                                        dex_compilation_unit->GetDexMethodIndex());
   return new CompiledMethod(compiler_driver_->GetInstructionSet(),
-                            cunit->GetCompiledCode(),
-                            *verifier::MethodVerifier::GetDexGcMap(mref));
+                            cunit->GetElfObject(),
+                            *verifier::MethodVerifier::GetDexGcMap(mref),
+                            cunit->GetDexCompilationUnit()->GetSymbol());
 }
 
 
@@ -235,7 +234,7 @@
   art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
 
   art::DexCompilationUnit dex_compilation_unit(
-    class_loader, class_linker, dex_file, code_item,
+    NULL, class_loader, class_linker, dex_file, code_item,
     class_def_idx, method_idx, access_flags);
   art::llvm::CompilerLLVM* compiler_llvm = ContextOf(driver);
   art::CompiledMethod* result = compiler_llvm->CompileDexMethod(&dex_compilation_unit, invoke_type);
@@ -248,7 +247,7 @@
   art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
 
   art::DexCompilationUnit dex_compilation_unit(
-    NULL, class_linker, dex_file, NULL,
+    NULL, NULL, class_linker, dex_file, NULL,
     0, method_idx, access_flags);
 
   art::llvm::CompilerLLVM* compiler_llvm = ContextOf(driver);
diff --git a/src/compiler/llvm/compiler_llvm.h b/src/compiler/llvm/compiler_llvm.h
index 870a541..cbee115 100644
--- a/src/compiler/llvm/compiler_llvm.h
+++ b/src/compiler/llvm/compiler_llvm.h
@@ -22,7 +22,6 @@
 #include "dex_file.h"
 #include "instruction_set.h"
 #include "mirror/object.h"
-#include "procedure_linkage_table.h"
 
 #include <UniquePtr.h>
 
@@ -87,10 +86,6 @@
 
   CompiledInvokeStub* CreateProxyStub(const char *shorty);
 
-  const ProcedureLinkageTable& GetProcedureLinkageTable() const {
-    return plt_;
-  }
-
  private:
   LlvmCompilationUnit* AllocateCompilationUnit();
 
@@ -98,13 +93,11 @@
 
   InstructionSet insn_set_;
 
-  Mutex num_cunits_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
-  size_t num_cunits_ GUARDED_BY(num_cunits_lock_);
+  Mutex next_cunit_id_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  size_t next_cunit_id_ GUARDED_BY(next_cunit_id_lock_);
 
   std::string bitcode_filename_;
 
-  ProcedureLinkageTable plt_;
-
   DISALLOW_COPY_AND_ASSIGN(CompilerLLVM);
 };
 
diff --git a/src/compiler/llvm/compiler_runtime_func_list.h b/src/compiler/llvm/compiler_runtime_func_list.h
deleted file mode 100644
index ffbae85..0000000
--- a/src/compiler/llvm/compiler_runtime_func_list.h
+++ /dev/null
@@ -1,234 +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_COMPILER_RUNTIME_FUNC_LIST_H_
-#define ART_SRC_COMPILER_LLVM_COMPILER_RUNTIME_FUNC_LIST_H_
-
-// NOTE: COMPILER_RUNTIME_FUNC_LIST_* should be sorted!
-
-#define COMPILER_RUNTIME_FUNC_LIST_X86(V) \
-  V(__ashldi3,          long long, long long, int) \
-  V(__ashrdi3,          long long, long long, int) \
-  V(__divdi3,           long long, long long, long long) \
-  V(__fixdfdi,          long long, double) \
-  V(__fixsfdi,          long long, float) \
-  V(__fixtfdi,          long long, long double) \
-  V(__fixtfsi,          int, long double) \
-  V(__fixunsdfdi,       unsigned long long, double) \
-  V(__fixunsdfsi,       unsigned int, double) \
-  V(__fixunssfdi,       unsigned long long, float) \
-  V(__fixunssfsi,       unsigned int, float) \
-  V(__fixunstfdi,       unsigned long long, long double) \
-  V(__fixunstfsi,       unsigned int, long double) \
-  V(__fixunsxfdi,       unsigned long long, long double) \
-  V(__fixunsxfsi,       unsigned int, long double) \
-  V(__fixxfdi,          long long, long double) \
-  V(__floatdidf,        double, long long) \
-  V(__floatdisf,        float, long long) \
-  V(__floatditf,        long double, long long) \
-  V(__floatdixf,        long double, long long) \
-  V(__floatsitf,        long double, int) \
-  V(__floatundidf,      double, unsigned long long) \
-  V(__floatundisf,      float, unsigned long long) \
-  V(__floatunditf,      long double, unsigned long long) \
-  V(__floatundixf,      long double, unsigned long long) \
-  V(__floatunsitf,      long double, int) \
-  V(__lshrdi3,          long long, long long, int) \
-  V(__moddi3,           long long, long long, long long) \
-  V(__muldi3,           long long, long long, long long) \
-  V(__negdi2,           long long, long long) \
-  V(__powidf2,          double, double, int) \
-  V(__powisf2,          float, float, int) \
-  V(__powitf2,          long double, long double, int) \
-  V(__powixf2,          long double, long double, int) \
-  V(__trunctfdf2,       double, long double) \
-  V(__trunctfsf2,       float, long double) \
-  V(__udivdi3,          unsigned long long, unsigned long long, unsigned long long) \
-  V(__umoddi3,          unsigned long long, unsigned long long, unsigned long long) \
-  V(ceil,               double, double) \
-  V(ceilf,              float, float) \
-  V(ceill,              long double, long double) \
-  V(copysign,           double, double, double) \
-  V(copysignf,          float, float, float) \
-  V(copysignl,          long double, long double, long double) \
-  V(cos,                double, double) \
-  V(cosf,               float, float) \
-  V(exp,                double, double) \
-  V(exp2,               double, double) \
-  V(exp2f,              float, float) \
-  V(expf,               float, float) \
-  V(floor,              double, double) \
-  V(floorf,             float, float) \
-  V(floorl,             long double, long double) \
-  V(fma,                double, double, double, double) \
-  V(fmaf,               float, float, float, float) \
-  V(fmod,               double, double, double) \
-  V(fmodf,              float, float, float) \
-  V(log,                double, double) \
-  V(log10,              double, double) \
-  V(log10f,             float, float) \
-  V(logf,               float, float) \
-  V(memcpy,             void *, void *, const void *, size_t) \
-  V(memmove,            void *, void *, const void *, size_t) \
-  V(memset,             void *, void *, int, size_t) \
-  V(nearbyint,          double, double) \
-  V(nearbyintf,         float, float) \
-  V(pow,                double, double, double) \
-  V(powf,               float, float, float) \
-  V(rint,               double, double) \
-  V(rintf,              float, float) \
-  V(sin,                double, double) \
-  V(sinf,               float, float) \
-  V(sqrt,               double, double) \
-  V(sqrtf,              float, float) \
-  V(trunc,              double, double) \
-  V(truncf,             float, float) \
-  V(truncl,             long double, long double)
-
-#define COMPILER_RUNTIME_FUNC_LIST_MIPS(V) \
-  V(__ashldi3,          long long, long long, int) \
-  V(__ashrdi3,          long long, long long, int) \
-  V(__divdi3,           long long, long long, long long) \
-  V(__fixdfdi,          long long, double) \
-  V(__fixsfdi,          long long, float) \
-  V(__fixunsdfdi,       unsigned long long, double) \
-  V(__fixunsdfsi,       unsigned int, double) \
-  V(__fixunssfdi,       unsigned long long, float) \
-  V(__fixunssfsi,       unsigned int, float) \
-  V(__floatdidf,        double, long long) \
-  V(__floatdisf,        float, long long) \
-  V(__floatundidf,      double, unsigned long long) \
-  V(__floatundisf,      float, unsigned long long) \
-  V(__lshrdi3,          long long, long long, int) \
-  V(__moddi3,           long long, long long, long long) \
-  V(__muldi3,           long long, long long, long long) \
-  V(__negdi2,           long long, long long) \
-  V(__powidf2,          double, double, int) \
-  V(__powisf2,          float, float, int) \
-  V(__udivdi3,          unsigned long long, unsigned long long, unsigned long long) \
-  V(__umoddi3,          unsigned long long, unsigned long long, unsigned long long) \
-  V(ceil,               double, double) \
-  V(ceilf,              float, float) \
-  V(ceill,              long double, long double) \
-  V(copysign,           double, double, double) \
-  V(copysignf,          float, float, float) \
-  V(copysignl,          long double, long double, long double) \
-  V(cos,                double, double) \
-  V(cosf,               float, float) \
-  V(exp,                double, double) \
-  V(exp2,               double, double) \
-  V(exp2f,              float, float) \
-  V(expf,               float, float) \
-  V(floor,              double, double) \
-  V(floorf,             float, float) \
-  V(floorl,             long double, long double) \
-  V(fma,                double, double, double, double) \
-  V(fmaf,               float, float, float, float) \
-  V(fmod,               double, double, double) \
-  V(fmodf,              float, float, float) \
-  V(log,                double, double) \
-  V(log10,              double, double) \
-  V(log10f,             float, float) \
-  V(logf,               float, float) \
-  V(memcpy,             void *, void *, const void *, size_t) \
-  V(memmove,            void *, void *, const void *, size_t) \
-  V(memset,             void *, void *, int, size_t) \
-  V(nearbyint,          double, double) \
-  V(nearbyintf,         float, float) \
-  V(pow,                double, double, double) \
-  V(powf,               float, float, float) \
-  V(rint,               double, double) \
-  V(rintf,              float, float) \
-  V(sin,                double, double) \
-  V(sinf,               float, float) \
-  V(sqrt,               double, double) \
-  V(sqrtf,              float, float) \
-  V(trunc,              double, double) \
-  V(truncf,             float, float) \
-  V(truncl,             long double, long double)
-
-#define COMPILER_RUNTIME_FUNC_LIST_ARM(V) \
-  V(__aeabi_d2f,        float, double) \
-  V(__aeabi_d2iz,       int, double) \
-  V(__aeabi_d2lz,       long long, double) \
-  V(__aeabi_d2uiz,      unsigned, double) \
-  V(__aeabi_d2ulz,      unsigned long long, double) \
-  V(__aeabi_dadd,       double, double, double) \
-  V(__aeabi_dcmpeq,     int, double, double) \
-  V(__aeabi_dcmpge,     int, double, double) \
-  V(__aeabi_dcmpgt,     int, double, double) \
-  V(__aeabi_dcmple,     int, double, double) \
-  V(__aeabi_dcmplt,     int, double, double) \
-  V(__aeabi_dcmpun,     int, double, double) \
-  V(__aeabi_ddiv,       double, double, double) \
-  V(__aeabi_dmul,       double, double, double) \
-  V(__aeabi_dsub,       double, double, double) \
-  V(__aeabi_f2d,        double, float) \
-  V(__aeabi_f2iz,       int, float) \
-  V(__aeabi_f2lz,       long long, float) \
-  V(__aeabi_f2uiz,      unsigned int, float) \
-  V(__aeabi_f2ulz,      unsigned long long, float) \
-  V(__aeabi_fadd,       float, float, float) \
-  V(__aeabi_fcmpeq,     int, float, float) \
-  V(__aeabi_fcmpge,     int, float, float) \
-  V(__aeabi_fcmpgt,     int, float, float) \
-  V(__aeabi_fcmple,     int, float, float) \
-  V(__aeabi_fcmplt,     int, float, float) \
-  V(__aeabi_fcmpun,     int, float, float) \
-  V(__aeabi_fdiv,       float, float, float) \
-  V(__aeabi_fmul,       float, float, float) \
-  V(__aeabi_fsub,       float, float, float) \
-  V(__aeabi_i2d,        double, int) \
-  V(__aeabi_i2f,        float, int) \
-  V(__aeabi_idiv,       int, int, int) \
-  V(__aeabi_l2d,        double, long long) \
-  V(__aeabi_l2f,        float, long long) \
-  V(__aeabi_lasr,       long long, long long, int) \
-  V(__aeabi_ldivmod,    /* value in regs */ void, long long, long long) \
-  V(__aeabi_llsl,       long long, long long, int) \
-  V(__aeabi_llsr,       long long, long long, int) \
-  V(__aeabi_lmul,       long long, long long, long long) \
-  V(__aeabi_memcpy,     void, void *, const void *, size_t) \
-  V(__aeabi_memmove,    void, void *, const void *, size_t) \
-  V(__aeabi_memset,     void, void *, size_t, int) /* different from stdlib */ \
-  V(__aeabi_ui2d,       double, unsigned int) \
-  V(__aeabi_ui2f,       float, unsigned int) \
-  V(__aeabi_uidiv,      unsigned int, unsigned int, unsigned int) \
-  V(__aeabi_ul2d,       double, unsigned long long) \
-  V(__aeabi_ul2f,       float, unsigned long long) \
-  V(__aeabi_uldivmod,   /* value in regs */ void, unsigned long long, unsigned long long) \
-  V(__moddi3,           long long, long long, long long) \
-  V(__modsi3,           int, int, int) \
-  V(__umoddi3,          unsigned long long, unsigned long long, unsigned long long) \
-  V(__umodsi3,          unsigned int, unsigned int, unsigned int) \
-  V(fmod,               double, double, double) \
-  V(fmodf,              float, float, float) \
-  V(memcpy,             void *, void *, const void *, size_t) \
-  V(memmove,            void *, void *, const void *, size_t) \
-  V(memset,             void *, void *, int, size_t)
-
-
-#if defined(__arm__)
-#define COMPILER_RUNTIME_FUNC_LIST_NATIVE(V) COMPILER_RUNTIME_FUNC_LIST_ARM(V)
-#elif defined(__mips__)
-#define COMPILER_RUNTIME_FUNC_LIST_NATIVE(V) COMPILER_RUNTIME_FUNC_LIST_MIPS(V)
-#elif defined(__i386__)
-#define COMPILER_RUNTIME_FUNC_LIST_NATIVE(V) COMPILER_RUNTIME_FUNC_LIST_X86(V)
-#else
-#error "Unknown target platform"
-#endif
-
-#endif // ART_SRC_COMPILER_LLVM_COMPILER_RUNTIME_FUNC_LIST_H_
diff --git a/src/compiler/llvm/gbc_expander.cc b/src/compiler/llvm/gbc_expander.cc
index 4e1a91d..9de2e41 100644
--- a/src/compiler/llvm/gbc_expander.cc
+++ b/src/compiler/llvm/gbc_expander.cc
@@ -326,7 +326,7 @@
   static char ID;
 
   GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
-                  art::CompilerDriver* compiler, art::DexCompilationUnit* dex_compilation_unit)
+                  art::CompilerDriver* compiler, const art::DexCompilationUnit* dex_compilation_unit)
       : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
         context_(irb.getContext()), rtb_(irb.Runtime()),
         shadow_frame_(NULL), old_shadow_frame_(NULL),
@@ -350,7 +350,7 @@
   VLOG(compiler) << "GBC expansion on " << func.getName().str();
 
   // Runtime support or stub
-  if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
+  if (dex_compilation_unit_ == NULL) {
     return false;
   }
 
@@ -3634,7 +3634,7 @@
 
 ::llvm::FunctionPass*
 CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
-                      CompilerDriver* driver, DexCompilationUnit* dex_compilation_unit) {
+                      CompilerDriver* driver, const DexCompilationUnit* dex_compilation_unit) {
   return new GBCExpanderPass(intrinsic_helper, irb, driver, dex_compilation_unit);
 }
 
diff --git a/src/compiler/llvm/llvm_compilation_unit.cc b/src/compiler/llvm/llvm_compilation_unit.cc
index aad18fb..3783ae9 100644
--- a/src/compiler/llvm/llvm_compilation_unit.cc
+++ b/src/compiler/llvm/llvm_compilation_unit.cc
@@ -16,16 +16,11 @@
 
 #include "llvm_compilation_unit.h"
 
-#include "base/logging.h"
-#include "compiled_method.h"
-#include "compiler_llvm.h"
-#include "instruction_set.h"
-#include "ir_builder.h"
-#include "os.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
-#include "runtime_support_builder_arm.h"
-#include "runtime_support_builder_thumb2.h"
-#include "runtime_support_builder_x86.h"
+#include <string>
 
 #include <llvm/ADT/OwningPtr.h>
 #include <llvm/ADT/StringSet.h>
@@ -71,24 +66,30 @@
 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
 #include <llvm/Transforms/Scalar.h>
 
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <string>
+#include "base/logging.h"
+#include "base/unix_file/fd_file.h"
+#include "compiled_method.h"
+#include "compiler_llvm.h"
+#include "instruction_set.h"
+#include "ir_builder.h"
+#include "os.h"
+#include "runtime_support_builder_arm.h"
+#include "runtime_support_builder_thumb2.h"
+#include "runtime_support_builder_x86.h"
+#include "utils_llvm.h"
 
 namespace art {
 namespace llvm {
 
 ::llvm::FunctionPass*
 CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
-                      CompilerDriver* compiler, DexCompilationUnit* dex_compilation_unit);
+                      CompilerDriver* compiler, const DexCompilationUnit* dex_compilation_unit);
 
 ::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);
 
 
-LlvmCompilationUnit::LlvmCompilationUnit(const CompilerLLVM* compiler_llvm, size_t cunit_idx)
-    : compiler_llvm_(compiler_llvm), cunit_idx_(cunit_idx) {
+LlvmCompilationUnit::LlvmCompilationUnit(const CompilerLLVM* compiler_llvm, size_t cunit_id)
+    : compiler_llvm_(compiler_llvm), cunit_id_(cunit_id) {
   driver_ = NULL;
   dex_compilation_unit_ = NULL;
   llvm_info_.reset(new LLVMInfo());
@@ -136,27 +137,24 @@
 
 
 bool LlvmCompilationUnit::Materialize() {
-  std::string elf_image;
-
   // Compile and prelink ::llvm::Module
-  if (!MaterializeToString(elf_image)) {
-    LOG(ERROR) << "Failed to materialize compilation unit " << cunit_idx_;
+  if (!MaterializeToString(elf_object_)) {
+    LOG(ERROR) << "Failed to materialize compilation unit " << cunit_id_;
     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_;
-    return false;
+  if (false) {
+    // Dump the ELF image for debugging
+    std::string directory;
+    if (kIsTargetBuild) {
+      directory += GetArtCacheOrDie(GetAndroidData());
+    } else {
+      directory += "/tmp";
+    }
+    std::string filename(StringPrintf("%s/Art%u.o", directory.c_str(), cunit_id_));
+    UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+    output->WriteFully(elf_object_.data(), elf_object_.size());
+    LOG(INFO) << ".o file written successfully: " << filename;
   }
 
   return true;
@@ -284,112 +282,6 @@
   return true;
 }
 
-bool LlvmCompilationUnit::ExtractCodeAndPrelink(const std::string& elf_image) {
-  if (GetInstructionSet() == kX86) {
-    compiled_code_.push_back(0xccU);
-    compiled_code_.push_back(0xccU);
-    compiled_code_.push_back(0xccU);
-    compiled_code_.push_back(0xccU);
-    return true;
-  }
-
-  ::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
diff --git a/src/compiler/llvm/llvm_compilation_unit.h b/src/compiler/llvm/llvm_compilation_unit.h
index 9ca9e3f..96d019c 100644
--- a/src/compiler/llvm/llvm_compilation_unit.h
+++ b/src/compiler/llvm/llvm_compilation_unit.h
@@ -53,8 +53,8 @@
  public:
   ~LlvmCompilationUnit();
 
-  size_t GetIndex() const {
-    return cunit_idx_;
+  uint32_t GetCompilationUnitId() const {
+    return cunit_id_;
   }
 
   InstructionSet GetInstructionSet() const;
@@ -81,27 +81,30 @@
   void SetCompiler(CompilerDriver* driver) {
     driver_ = driver;
   }
-  void SetDexCompilationUnit(DexCompilationUnit* dex_compilation_unit) {
+  const DexCompilationUnit* GetDexCompilationUnit() {
+    return dex_compilation_unit_;
+  }
+  void SetDexCompilationUnit(const DexCompilationUnit* dex_compilation_unit) {
     dex_compilation_unit_ = dex_compilation_unit;
   }
 
   bool Materialize();
 
   bool IsMaterialized() const {
-    return !compiled_code_.empty();
+    return !elf_object_.empty();
   }
 
-  const std::vector<uint8_t>& GetCompiledCode() const {
+  const std::string& GetElfObject() const {
     DCHECK(IsMaterialized());
-    return compiled_code_;
+    return elf_object_;
   }
 
  private:
   LlvmCompilationUnit(const CompilerLLVM* compiler_llvm,
-                      size_t cunit_idx);
+                      uint32_t cunit_id);
 
   const CompilerLLVM* compiler_llvm_;
-  const size_t cunit_idx_;
+  const uint32_t cunit_id_;
 
   UniquePtr< ::llvm::LLVMContext> context_;
   UniquePtr<IRBuilder> irb_;
@@ -110,11 +113,11 @@
   UniquePtr<IntrinsicHelper> intrinsic_helper_;
   UniquePtr<LLVMInfo> llvm_info_;
   CompilerDriver* driver_;
-  DexCompilationUnit* dex_compilation_unit_;
+  const DexCompilationUnit* dex_compilation_unit_;
 
   std::string bitcode_filename_;
 
-  std::vector<uint8_t> compiled_code_;
+  std::string elf_object_;
 
   SafeMap<const ::llvm::Function*, CompiledMethod*> compiled_methods_map_;
 
@@ -123,8 +126,6 @@
   bool MaterializeToString(std::string& str_buffer);
   bool MaterializeToRawOStream(::llvm::raw_ostream& out_stream);
 
-  bool ExtractCodeAndPrelink(const std::string& elf_image);
-
   friend class CompilerLLVM;  // For LlvmCompilationUnit constructor
 };
 
diff --git a/src/compiler/llvm/procedure_linkage_table.cc b/src/compiler/llvm/procedure_linkage_table.cc
deleted file mode 100644
index 47ba9bd..0000000
--- a/src/compiler/llvm/procedure_linkage_table.cc
+++ /dev/null
@@ -1,326 +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 "procedure_linkage_table.h"
-
-#include "base/logging.h"
-#include "compiler_runtime_func_list.h"
-#include "globals.h"
-#include "instruction_set.h"
-#include "runtime_support_func_list.h"
-#include "runtime_support_llvm.h"
-#include "utils_llvm.h"
-
-#include <algorithm>
-
-#include <UniquePtr.h>
-
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-
-namespace {
-  const char* const art_runtime_func_name_list[] = {
-#define DEFINE_ENTRY(ID, NAME) #NAME,
-    RUNTIME_SUPPORT_FUNC_LIST(DEFINE_ENTRY)
-#undef DEFINE_ENTRY
-  };
-
-  const char* const compiler_runtime_func_name_list_arm[] = {
-#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) #NAME,
-    COMPILER_RUNTIME_FUNC_LIST_ARM(DEFINE_ENTRY)
-#undef DEFINE_ENTRY
-  };
-
-  const char* const compiler_runtime_func_name_list_mips[] = {
-#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) #NAME,
-    COMPILER_RUNTIME_FUNC_LIST_MIPS(DEFINE_ENTRY)
-#undef DEFINE_ENTRY
-  };
-
-  const char* const compiler_runtime_func_name_list_x86[] = {
-#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) #NAME,
-    COMPILER_RUNTIME_FUNC_LIST_X86(DEFINE_ENTRY)
-#undef DEFINE_ENTRY
-  };
-
-  const size_t art_runtime_func_count =
-    sizeof(art_runtime_func_name_list) / sizeof(const char*);
-
-  const size_t compiler_runtime_func_count_arm =
-    sizeof(compiler_runtime_func_name_list_arm) / sizeof(const char*);
-
-  const size_t compiler_runtime_func_count_mips =
-    sizeof(compiler_runtime_func_name_list_mips) / sizeof(const char*);
-
-  const size_t compiler_runtime_func_count_x86 =
-    sizeof(compiler_runtime_func_name_list_x86) / sizeof(const char*);
-}
-
-
-namespace art {
-namespace llvm {
-
-
-ProcedureLinkageTable::ProcedureLinkageTable(InstructionSet insn_set)
-    : insn_set_(insn_set) {
-}
-
-
-ProcedureLinkageTable::~ProcedureLinkageTable() {
-}
-
-
-bool ProcedureLinkageTable::AllocateTable() {
-  if (table_mmap_.get()) {
-    return true;
-  }
-
-  // Allocate the PLT
-  byte* suggested_table_addr = reinterpret_cast<byte*>(kTableAddress);
-
-  UniquePtr<MemMap> table_mmap(
-      MemMap::MapAnonymous(".plt", suggested_table_addr,
-                           GetTableSizeInBytes(), PROT_READ | PROT_WRITE));
-
-  if (!table_mmap.get()) {
-    return false;
-  }
-
-  if (table_mmap->Begin() != suggested_table_addr) {
-    // Our PLT should be allocated at the FIXED address
-    return false;
-  }
-
-  // Create the stubs in the PLT
-  byte* stub_ptr = table_mmap->Begin();
-  size_t stub_size = GetStubSizeInBytes();
-
-  for (size_t i = 0; i < art_runtime_func_count; ++i, stub_ptr += stub_size) {
-    const char* name = art_runtime_func_name_list[i];
-    void* func = art_portable_find_runtime_support_func(NULL, name);
-    DCHECK(func != NULL);
-    CreateStub(stub_ptr, func);
-  }
-
-  const char* const* crt_name_list = NULL;
-  size_t crt_count = 0u;
-
-  switch (insn_set_) {
-  case kArm:
-  case kThumb2:
-    crt_name_list = compiler_runtime_func_name_list_arm;
-    crt_count = compiler_runtime_func_count_arm;
-    break;
-
-  case kMips:
-    crt_name_list = compiler_runtime_func_name_list_mips;
-    crt_count = compiler_runtime_func_count_mips;
-    break;
-
-  case kX86:
-    crt_name_list = compiler_runtime_func_name_list_x86;
-    crt_count = compiler_runtime_func_count_x86;
-    break;
-
-  default:
-    LOG(FATAL) << "Unknown instruction set: " << insn_set_;
-    return false;
-  }
-
-  for (size_t i = 0; i < crt_count; ++i, stub_ptr += stub_size) {
-    void* func = art_portable_find_runtime_support_func(NULL, crt_name_list[i]);
-    DCHECK(func != NULL);
-    CreateStub(stub_ptr, func);
-  }
-
-  // Protect the procedure linkage table
-  table_mmap->Protect(PROT_READ | PROT_EXEC);
-
-  // Flush the instruction cache on specific architecture
-#if defined(__arm__) || defined(__mips__)
-  cacheflush(reinterpret_cast<long int>(table_mmap->Begin()),
-             reinterpret_cast<long int>(table_mmap->End()), 0);
-#endif
-
-  // Transfer the ownership
-  table_mmap_.reset(table_mmap.release());
-
-  return true;
-}
-
-
-uintptr_t ProcedureLinkageTable::GetEntryAddress(const char* name) const {
-  int func_idx = IndexOfRuntimeFunc(name);
-  if (func_idx == -1) {
-    return 0u;
-  }
-
-  return (kTableAddress + func_idx * GetStubSizeInBytes());
-}
-
-
-
-int ProcedureLinkageTable::IndexOfRuntimeFunc(const char* name) const {
-  int result = IndexOfCompilerRuntimeFunc(name);
-  if (result != -1) {
-    return art_runtime_func_count + result;
-  }
-
-  return IndexOfArtRuntimeFunc(name);
-}
-
-
-int ProcedureLinkageTable::IndexOfArtRuntimeFunc(const char* name) {
-  for (size_t i = 0; i < art_runtime_func_count; ++i) {
-    if (strcmp(name, art_runtime_func_name_list[i]) == 0) {
-      return static_cast<int>(i);
-    }
-  }
-  return -1;
-}
-
-int ProcedureLinkageTable::IndexOfCompilerRuntimeFunc(InstructionSet insn_set,
-                                                      const char* name) {
-  const char* const* rt_begin = NULL;
-  const char* const* rt_end = NULL;
-
-  switch (insn_set) {
-  case kArm:
-  case kThumb2:
-    rt_begin = compiler_runtime_func_name_list_arm;
-    rt_end = compiler_runtime_func_name_list_arm +
-             compiler_runtime_func_count_arm;
-    break;
-
-  case kMips:
-    rt_begin = compiler_runtime_func_name_list_mips;
-    rt_end = compiler_runtime_func_name_list_mips +
-             compiler_runtime_func_count_mips;
-    break;
-
-  case kX86:
-    rt_begin = compiler_runtime_func_name_list_x86;
-    rt_end = compiler_runtime_func_name_list_x86 +
-             compiler_runtime_func_count_x86;
-    break;
-
-  default:
-    LOG(FATAL) << "Unknown instruction set: " << insn_set;
-    return -1;
-  }
-
-  const char* const* name_lbound_ptr =
-      std::lower_bound(rt_begin, rt_end, name, CStringLessThanComparator());
-
-  if (name_lbound_ptr < rt_end && strcmp(*name_lbound_ptr, name) == 0) {
-    return (name_lbound_ptr - rt_begin);
-  } else {
-    return -1;
-  }
-}
-
-
-size_t ProcedureLinkageTable::GetStubCount(InstructionSet insn_set) {
-  switch (insn_set) {
-  case kArm:
-  case kThumb2:
-    return art_runtime_func_count + compiler_runtime_func_count_arm;
-
-  case kMips:
-    return art_runtime_func_count + compiler_runtime_func_count_mips;
-
-  case kX86:
-    return art_runtime_func_count + compiler_runtime_func_count_x86;
-
-  default:
-    LOG(FATAL) << "Unknown instruction set: " << insn_set;
-    return 0u;
-  }
-}
-
-
-size_t ProcedureLinkageTable::GetStubSizeInBytes(InstructionSet insn_set) {
-  switch (insn_set) {
-  case kArm:
-  case kThumb2:
-    return 8u;
-
-  case kMips:
-    return 16u;
-
-  case kX86:
-    return 8u;
-
-  default:
-    LOG(FATAL) << "Unknown instruction set: " << insn_set;
-    return 0u;
-  }
-}
-
-
-void ProcedureLinkageTable::CreateStub(InstructionSet insn_set,
-                                       byte* stub, void* dest_) {
-  switch (insn_set) {
-  case kArm:
-  case kThumb2:
-    {
-      uint32_t dest = static_cast<uint32_t>(
-                      reinterpret_cast<uintptr_t>(dest_) & 0xfffffffful);
-      uint32_t* stub_w = reinterpret_cast<uint32_t*>(stub);
-
-      stub_w[0] = 0xe51ff004ul; // ldr pc, [pc #-4]
-      stub_w[1] = dest;
-    }
-    break;
-
-  case kMips:
-    {
-      uint32_t dest = static_cast<uint32_t>(
-                      reinterpret_cast<uintptr_t>(dest_) & 0xfffffffful);
-      uint32_t* stub_w = reinterpret_cast<uint32_t*>(stub);
-
-      stub_w[0] = 0x3c190000ul | ((dest >> 16) & 0xfffful); // lui
-      stub_w[1] = 0x37390000ul | (dest & 0xfffful);; // ori
-      stub_w[2] = 0x03200008ul; // jr (jump register)
-      stub_w[3] = 0x00000000ul; // nop
-    }
-    break;
-
-  case kX86:
-    {
-      uint32_t off = static_cast<uint32_t>(
-                     reinterpret_cast<uintptr_t>(dest_) -
-                     reinterpret_cast<uintptr_t>(stub + 1) - 4);
-      // jmp (32-bit offset)
-      stub[0] = 0xe9u;
-      stub[1] = off & 0xffu;
-      stub[2] = (off >> 8) & 0xffu;
-      stub[2] = (off >> 16) & 0xffu;
-      stub[2] = (off >> 24) & 0xffu;
-    }
-    break;
-
-  default:
-    LOG(FATAL) << "Unknown instruction set: " << insn_set;
-  }
-}
-
-
-} // namespace llvm
-} // namespace art
diff --git a/src/compiler/llvm/procedure_linkage_table.h b/src/compiler/llvm/procedure_linkage_table.h
deleted file mode 100644
index 1c89d29..0000000
--- a/src/compiler/llvm/procedure_linkage_table.h
+++ /dev/null
@@ -1,85 +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_PROCEDURE_LINKAGE_TABLE_H_
-#define ART_SRC_COMPILER_LLVM_PROCEDURE_LINKAGE_TABLE_H_
-
-#include "globals.h"
-#include "instruction_set.h"
-#include "mem_map.h"
-
-#include <UniquePtr.h>
-
-#include <stddef.h>
-#include <stdint.h>
-
-namespace art {
-namespace llvm {
-
-
-class ProcedureLinkageTable {
- public:
-  ProcedureLinkageTable(InstructionSet insn_set);
-
-  ~ProcedureLinkageTable();
-
-  bool AllocateTable();
-
-  uintptr_t GetEntryAddress(const char* func_name) const;
-
- private:
-  static size_t GetStubCount(InstructionSet insn_set);
-  static size_t GetStubSizeInBytes(InstructionSet insn_set);
-  static void CreateStub(InstructionSet insn_set,
-                         byte* stub, void* branch_dest);
-
-  int IndexOfRuntimeFunc(const char* name) const;
-  static int IndexOfArtRuntimeFunc(const char* name);
-  static int IndexOfCompilerRuntimeFunc(InstructionSet insn_set,
-                                        const char* name);
-
-  size_t GetStubCount() const {
-    return GetStubCount(insn_set_);
-  }
-
-  size_t GetStubSizeInBytes() const {
-    return GetStubSizeInBytes(insn_set_);
-  }
-
-  size_t GetTableSizeInBytes() const {
-    return GetStubSizeInBytes() * GetStubCount();
-  }
-
-  void CreateStub(byte* stub, void* branch_dest) {
-    return CreateStub(insn_set_, stub, branch_dest);
-  }
-
-  int IndexOfCompilerRuntimeFunc(const char* name) const {
-    return IndexOfCompilerRuntimeFunc(insn_set_, name);
-  }
-
-  InstructionSet insn_set_;
-  UniquePtr<MemMap> table_mmap_;
-
-  static const size_t kTableSizeInBytes = 1024u;
-  static const uintptr_t kTableAddress = 0x5fffc000u;
-};
-
-
-} // namespace llvm
-} // namespace art
-
-#endif // ART_SRC_COMPILER_LLVM_PROCEDURE_LINKAGE_TABLE_H_
diff --git a/src/compiler/llvm/runtime_support_llvm.cc b/src/compiler/llvm/runtime_support_llvm.cc
index ae8bb4a..b18eefe 100644
--- a/src/compiler/llvm/runtime_support_llvm.cc
+++ b/src/compiler/llvm/runtime_support_llvm.cc
@@ -20,7 +20,6 @@
 #include "asm_support.h"
 #include "class_linker.h"
 #include "class_linker-inl.h"
-#include "compiler_runtime_func_list.h"
 #include "dex_file.h"
 #include "dex_instruction.h"
 #include "mirror/abstract_method-inl.h"
@@ -743,46 +742,6 @@
   return o;
 }
 
-//----------------------------------------------------------------------------
-// Runtime Support Function Lookup Callback
-//----------------------------------------------------------------------------
-
-#define EXTERNAL_LINKAGE(NAME, RETURN_TYPE, ...) \
-extern "C" RETURN_TYPE NAME(__VA_ARGS__);
-COMPILER_RUNTIME_FUNC_LIST_NATIVE(EXTERNAL_LINKAGE)
-#undef EXTERNAL_LINKAGE
-
-static void* art_portable_find_compiler_runtime_func(const char* name) {
-// TODO: If target support some math func, use the target's version. (e.g. art_portable_d2i -> __aeabi_d2iz)
-  static const char* const names[] = {
-#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) #NAME ,
-    COMPILER_RUNTIME_FUNC_LIST_NATIVE(DEFINE_ENTRY)
-#undef DEFINE_ENTRY
-  };
-
-  static void* const funcs[] = {
-#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) \
-    reinterpret_cast<void*>(static_cast<RETURN_TYPE (*)(__VA_ARGS__)>(NAME)) ,
-    COMPILER_RUNTIME_FUNC_LIST_NATIVE(DEFINE_ENTRY)
-#undef DEFINE_ENTRY
-  };
-
-  static const size_t num_entries = sizeof(names) / sizeof(const char* const);
-
-  const char* const* const names_begin = names;
-  const char* const* const names_end = names + num_entries;
-
-  const char* const* name_lbound_ptr =
-      std::lower_bound(names_begin, names_end, name,
-                       CStringLessThanComparator());
-
-  if (name_lbound_ptr < names_end && strcmp(*name_lbound_ptr, name) == 0) {
-    return funcs[name_lbound_ptr - names_begin];
-  } else {
-    return NULL;
-  }
-}
-
 // Handler for invocation on proxy methods. Create a boxed argument array and invoke the invocation
 // handler which is a field within the proxy object receiver. The var args encode the arguments
 // with the last argument being a pointer to a JValue to store the result in.
@@ -860,43 +819,6 @@
   }
 }
 
-void* art_portable_find_runtime_support_func(void* context, const char* name) {
-  struct func_entry_t {
-    const char* name;
-    size_t name_len;
-    void* addr;
-  };
-
-  static struct func_entry_t const tab[] = {
-#define DEFINE_ENTRY(ID, NAME) \
-    { #NAME, sizeof(#NAME) - 1, reinterpret_cast<void*>(NAME) },
-    RUNTIME_SUPPORT_FUNC_LIST(DEFINE_ENTRY)
-#undef DEFINE_ENTRY
-  };
-
-  static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
-
-  // Search the compiler runtime (such as __divdi3)
-  void* result = art_portable_find_compiler_runtime_func(name);
-  if (result != NULL) {
-    return result;
-  }
-
-  // Note: Since our table is small, we are using trivial O(n) searching
-  // function.  For bigger table, it will be better to use a binary
-  // search or hash function.
-  size_t i;
-  size_t name_len = strlen(name);
-  for (i = 0; i < tab_size; ++i) {
-    if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
-      return tab[i].addr;
-    }
-  }
-
-  LOG(FATAL) << "Error: Can't find symbol " << name;
-  return 0;
-}
-
 //----------------------------------------------------------------------------
 // Memory barrier
 //----------------------------------------------------------------------------
diff --git a/src/compiler/llvm/utils_llvm.h b/src/compiler/llvm/utils_llvm.h
index e06e113..2e273f4 100644
--- a/src/compiler/llvm/utils_llvm.h
+++ b/src/compiler/llvm/utils_llvm.h
@@ -17,13 +17,8 @@
 #ifndef ART_SRC_UTILS_LLVM_H_
 #define ART_SRC_UTILS_LLVM_H_
 
-#include "base/stringprintf.h"
-
 #include <llvm/Analysis/Verifier.h>
 
-#include <stdint.h>
-#include <string>
-
 namespace art {
 
 #ifndef NDEBUG
@@ -32,17 +27,6 @@
 #define VERIFY_LLVM_FUNCTION(func)
 #endif
 
-inline static std::string ElfFuncName(uint32_t idx) {
-  return StringPrintf("Art%u", static_cast<unsigned int>(idx));
-}
-
-class CStringLessThanComparator {
- public:
-  bool operator()(const char* lhs, const char* rhs) const {
-    return (strcmp(lhs, rhs) < 0);
-  }
-};
-
 }  // namespace art
 
 #endif  // ART_SRC_UTILS_LLVM_H_