Compile method one-by-one.

Change-Id: Ic56fb397f3bd6dee32372eb875261a3383eaf30c
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 2558eba..013a561 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -20,7 +20,6 @@
 
 #include "class_linker.h"
 #include "class_loader.h"
-#include "elf_image.h"
 #include "file.h"
 #include "os.h"
 #include "safe_map.h"
@@ -53,15 +52,12 @@
   image_file_location_checksum_ = image_file_location_checksum;
   image_file_location_ = image_file_location;
   dex_files_ = &dex_files;
-  elf_images_ = compiler_->GetElfImages();
   oat_header_ = NULL;
   executable_offset_padding_length_ = 0;
 
   size_t offset = InitOatHeader();
   offset = InitOatDexFiles(offset);
   offset = InitDexFiles(offset);
-  offset = InitOatElfImages(offset);
-  offset = InitElfImages(offset);
   offset = InitOatClasses(offset);
   offset = InitOatCode(offset);
   offset = InitOatCodeDexFiles(offset);
@@ -72,7 +68,6 @@
 OatWriter::~OatWriter() {
   delete oat_header_;
   STLDeleteElements(&oat_dex_files_);
-  STLDeleteElements(&oat_elf_images_);
   STLDeleteElements(&oat_classes_);
 }
 
@@ -80,7 +75,6 @@
   // create the OatHeader
   oat_header_ = new OatHeader(compiler_->GetInstructionSet(),
                               dex_files_,
-                              elf_images_.size(),
                               image_file_location_checksum_,
                               image_file_location_);
   size_t offset = sizeof(*oat_header_);
@@ -115,34 +109,6 @@
   return offset;
 }
 
-size_t OatWriter::InitOatElfImages(size_t offset) {
-  size_t n = elf_images_.size();
-  if (n != 0) {
-    // Offset to ELF image table should be rounded up to 4-byte aligned, so that
-    // we can read the uint32_t directly.
-    offset = RoundUp(offset, 4);
-    oat_header_->SetElfImageTableOffset(offset);
-  } else {
-    oat_header_->SetElfImageTableOffset(0);
-  }
-
-  for (size_t i = 0; i < n; ++i) {
-    OatElfImage* oat_elf_image = new OatElfImage(elf_images_[i]);
-    oat_elf_images_.push_back(oat_elf_image);
-    offset += oat_elf_image->SizeOf();
-  }
-  return offset;
-}
-
-size_t OatWriter::InitElfImages(size_t offset) {
-  for (size_t i = 0; i < oat_elf_images_.size(); ++i) {
-    offset = RoundUp(offset, 4);
-    oat_elf_images_[i]->SetElfOffset(offset);
-    offset += oat_elf_images_[i]->GetElfSize();
-  }
-  return offset;
-}
-
 size_t OatWriter::InitOatClasses(size_t offset) {
   // create the OatClasses
   // calculate the offsets within OatDexFiles to OatClasses
@@ -258,10 +224,6 @@
                                     uint32_t method_idx, const DexFile* dex_file) {
   // derived from CompiledMethod if available
   uint32_t code_offset = 0;
-#if defined(ART_USE_LLVM_COMPILER)
-  uint16_t code_elf_idx = static_cast<uint16_t>(-1u);
-  uint16_t code_elf_func_idx = static_cast<uint16_t>(-1u);
-#endif
   uint32_t frame_size_in_bytes = kStackAlignment;
   uint32_t core_spill_mask = 0;
   uint32_t fp_spill_mask = 0;
@@ -271,125 +233,107 @@
   // derived from CompiledInvokeStub if available
   uint32_t invoke_stub_offset = 0;
 #if defined(ART_USE_LLVM_COMPILER)
-  uint16_t invoke_stub_elf_idx = static_cast<uint16_t>(-1u);
-  uint16_t invoke_stub_elf_func_idx = static_cast<uint16_t>(-1u);
-  uint16_t proxy_stub_elf_idx = static_cast<uint16_t>(-1u);
-  uint16_t proxy_stub_elf_func_idx = static_cast<uint16_t>(-1u);
+  uint32_t proxy_stub_offset = 0;
 #endif
 
   CompiledMethod* compiled_method =
       compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file, method_idx));
   if (compiled_method != NULL) {
-    if (compiled_method->IsExecutableInElf()) {
-#if defined(ART_USE_LLVM_COMPILER)
-      code_elf_idx = compiled_method->GetElfIndex();
-      code_elf_func_idx = compiled_method->GetElfFuncIndex();
-#endif
-      frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+    offset = compiled_method->AlignCode(offset);
+    DCHECK_ALIGNED(offset, kArmAlignment);
+    const std::vector<uint8_t>& code = compiled_method->GetCode();
+    uint32_t code_size = code.size() * sizeof(code[0]);
+    CHECK_NE(code_size, 0U);
+    uint32_t thumb_offset = compiled_method->CodeDelta();
+    code_offset = offset + sizeof(code_size) + thumb_offset;
+
+    // Deduplicate code arrays
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
+    if (code_iter != code_offsets_.end()) {
+      code_offset = code_iter->second;
     } else {
-      offset = compiled_method->AlignCode(offset);
-      DCHECK_ALIGNED(offset, kArmAlignment);
-      const std::vector<uint8_t>& code = compiled_method->GetCode();
-      uint32_t code_size = code.size() * sizeof(code[0]);
-      CHECK_NE(code_size, 0U);
-      uint32_t thumb_offset = compiled_method->CodeDelta();
-      code_offset = offset + sizeof(code_size) + thumb_offset;
+      code_offsets_.Put(&code, code_offset);
+      offset += sizeof(code_size);  // code size is prepended before code
+      offset += code_size;
+      oat_header_->UpdateChecksum(&code[0], code_size);
+    }
+    frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+    core_spill_mask = compiled_method->GetCoreSpillMask();
+    fp_spill_mask = compiled_method->GetFpSpillMask();
 
-      // Deduplicate code arrays
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
-      if (code_iter != code_offsets_.end()) {
-        code_offset = code_iter->second;
-      } else {
-        code_offsets_.Put(&code, code_offset);
-        offset += sizeof(code_size);  // code size is prepended before code
-        offset += code_size;
-        oat_header_->UpdateChecksum(&code[0], code_size);
-      }
-      frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
-      core_spill_mask = compiled_method->GetCoreSpillMask();
-      fp_spill_mask = compiled_method->GetFpSpillMask();
+    const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
+    size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
+    mapping_table_offset = (mapping_table_size == 0) ? 0 : offset;
 
-      const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
-      size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
-      mapping_table_offset = (mapping_table_size == 0) ? 0 : offset;
+    // Deduplicate mapping tables
+    SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
+    if (mapping_iter != mapping_table_offsets_.end()) {
+      mapping_table_offset = mapping_iter->second;
+    } else {
+      mapping_table_offsets_.Put(&mapping_table, mapping_table_offset);
+      offset += mapping_table_size;
+      oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size);
+    }
 
-      // Deduplicate mapping tables
-      SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
-      if (mapping_iter != mapping_table_offsets_.end()) {
-        mapping_table_offset = mapping_iter->second;
-      } else {
-        mapping_table_offsets_.Put(&mapping_table, mapping_table_offset);
-        offset += mapping_table_size;
-        oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size);
-      }
+    const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
+    size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
+    vmap_table_offset = (vmap_table_size == 0) ? 0 : offset;
 
-      const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
-      size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
-      vmap_table_offset = (vmap_table_size == 0) ? 0 : offset;
+    // Deduplicate vmap tables
+    SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
+    if (vmap_iter != vmap_table_offsets_.end()) {
+      vmap_table_offset = vmap_iter->second;
+    } else {
+      vmap_table_offsets_.Put(&vmap_table, vmap_table_offset);
+      offset += vmap_table_size;
+      oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size);
+    }
 
-      // Deduplicate vmap tables
-      SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
-      if (vmap_iter != vmap_table_offsets_.end()) {
-        vmap_table_offset = vmap_iter->second;
-      } else {
-        vmap_table_offsets_.Put(&vmap_table, vmap_table_offset);
-        offset += vmap_table_size;
-        oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size);
-      }
+    const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
+    size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
+    gc_map_offset = (gc_map_size == 0) ? 0 : offset;
 
-      const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
-      size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
-      gc_map_offset = (gc_map_size == 0) ? 0 : offset;
-
-#ifndef NDEBUG
-      // We expect GC maps except when the class hasn't been verified or the method is native
-      CompiledClass* compiled_class =
-          compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
-      Class::Status status =
-          (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
-      CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified)
-          << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file);
+#if !defined(NDEBUG) && !defined(ART_USE_LLVM_COMPILER)
+    // We expect GC maps except when the class hasn't been verified or the method is native
+    CompiledClass* compiled_class =
+        compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
+    Class::Status status =
+        (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
+    CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified)
+        << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file);
 #endif
 
-      // Deduplicate GC maps
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map);
-      if (gc_map_iter != gc_map_offsets_.end()) {
-        gc_map_offset = gc_map_iter->second;
-      } else {
-        gc_map_offsets_.Put(&gc_map, gc_map_offset);
-        offset += gc_map_size;
-        oat_header_->UpdateChecksum(&gc_map[0], gc_map_size);
-      }
+    // Deduplicate GC maps
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map);
+    if (gc_map_iter != gc_map_offsets_.end()) {
+      gc_map_offset = gc_map_iter->second;
+    } else {
+      gc_map_offsets_.Put(&gc_map, gc_map_offset);
+      offset += gc_map_size;
+      oat_header_->UpdateChecksum(&gc_map[0], gc_map_size);
     }
   }
 
   const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx));
   const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
-    if (compiled_invoke_stub->IsExecutableInElf()) {
-#if defined(ART_USE_LLVM_COMPILER)
-      invoke_stub_elf_idx = compiled_invoke_stub->GetElfIndex();
-      invoke_stub_elf_func_idx = compiled_invoke_stub->GetElfFuncIndex();
-#endif
-    } else {
-      offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
-      DCHECK_ALIGNED(offset, kArmAlignment);
-      const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
-      uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
-      CHECK_NE(invoke_stub_size, 0U);
-      uint32_t thumb_offset = compiled_invoke_stub->CodeDelta();
-      invoke_stub_offset = offset + sizeof(invoke_stub_size) + thumb_offset;
+    offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
+    DCHECK_ALIGNED(offset, kArmAlignment);
+    const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
+    uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
+    CHECK_NE(invoke_stub_size, 0U);
+    uint32_t thumb_offset = compiled_invoke_stub->CodeDelta();
+    invoke_stub_offset = offset + sizeof(invoke_stub_size) + thumb_offset;
 
-      // Deduplicate invoke stubs
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
-      if (stub_iter != code_offsets_.end()) {
-        invoke_stub_offset = stub_iter->second;
-      } else {
-        code_offsets_.Put(&invoke_stub, invoke_stub_offset);
-        offset += sizeof(invoke_stub_size);  // invoke stub size is prepended before code
-        offset += invoke_stub_size;
-        oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
-      }
+    // Deduplicate invoke stubs
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
+    if (stub_iter != code_offsets_.end()) {
+      invoke_stub_offset = stub_iter->second;
+    } else {
+      code_offsets_.Put(&invoke_stub, invoke_stub_offset);
+      offset += sizeof(invoke_stub_size);  // invoke stub size is prepended before code
+      offset += invoke_stub_size;
+      oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
     }
   }
 
@@ -397,9 +341,24 @@
   if (!is_static) {
     const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
     if (compiled_proxy_stub != NULL) {
-      DCHECK(compiled_proxy_stub->IsExecutableInElf());
-      proxy_stub_elf_idx = compiled_proxy_stub->GetElfIndex();
-      proxy_stub_elf_func_idx = compiled_proxy_stub->GetElfFuncIndex();
+      offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
+      DCHECK_ALIGNED(offset, kArmAlignment);
+      const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode();
+      uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]);
+      CHECK_NE(proxy_stub_size, 0U);
+      uint32_t thumb_offset = compiled_proxy_stub->CodeDelta();
+      proxy_stub_offset = offset + sizeof(proxy_stub_size) + thumb_offset;
+
+      // Deduplicate proxy stubs
+      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&proxy_stub);
+      if (stub_iter != code_offsets_.end()) {
+        proxy_stub_offset = stub_iter->second;
+      } else {
+        code_offsets_.Put(&proxy_stub, proxy_stub_offset);
+        offset += sizeof(proxy_stub_size);  // proxy stub size is prepended before code
+        offset += proxy_stub_size;
+        oat_header_->UpdateChecksum(&proxy_stub[0], proxy_stub_size);
+      }
     }
   }
 #endif
@@ -414,12 +373,7 @@
                          gc_map_offset,
                          invoke_stub_offset
 #if defined(ART_USE_LLVM_COMPILER)
-                       , code_elf_idx,
-                         code_elf_func_idx,
-                         invoke_stub_elf_idx,
-                         invoke_stub_elf_func_idx,
-                         proxy_stub_elf_idx,
-                         proxy_stub_elf_func_idx
+                       , proxy_stub_offset
 #endif
                          );
 
@@ -505,25 +459,6 @@
       return false;
     }
   }
-  for (size_t i = 0; i != oat_elf_images_.size(); ++i) {
-    if (!oat_elf_images_[i]->Write(file)) {
-      PLOG(ERROR) << "Failed to write oat elf information to " << file->name();
-      return false;
-    }
-  }
-  for (size_t i = 0; i != oat_elf_images_.size(); ++i) {
-    uint32_t expected_offset = oat_elf_images_[i]->GetElfOffset();
-    off_t actual_offset = lseek(file->Fd(), expected_offset, SEEK_SET);
-    if (static_cast<uint32_t>(actual_offset) != expected_offset) {
-      PLOG(ERROR) << "Failed to seek to dex file section."
-                  << " Actual: " << actual_offset
-                  << " Expected: " << expected_offset;
-      return false;
-    }
-    if (!oat_elf_images_[i]->WriteElfImage(file)) {
-      return false;
-    }
-  }
   for (size_t i = 0; i != oat_classes_.size(); ++i) {
     if (!oat_classes_[i]->Write(file)) {
       PLOG(ERROR) << "Failed to write oat methods information to " << file->name();
@@ -629,126 +564,169 @@
 
 
   if (compiled_method != NULL) {  // ie. not an abstract method
-    if (!compiled_method->IsExecutableInElf()) {
-      uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
-      uint32_t aligned_code_delta = aligned_code_offset - code_offset;
-      if (aligned_code_delta != 0) {
-        off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
-        if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
-          PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
-                      << " Expected: " << aligned_code_offset << " File: " << file->name();
-          return 0;
-        }
-        code_offset += aligned_code_delta;
-        DCHECK_CODE_OFFSET();
+    uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
+    uint32_t aligned_code_delta = aligned_code_offset - code_offset;
+    if (aligned_code_delta != 0) {
+      off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
+      if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
+        PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
+                    << " Expected: " << aligned_code_offset << " File: " << file->name();
+        return 0;
       }
-      DCHECK_ALIGNED(code_offset, kArmAlignment);
-      const std::vector<uint8_t>& code = compiled_method->GetCode();
-      uint32_t code_size = code.size() * sizeof(code[0]);
-      CHECK_NE(code_size, 0U);
-
-      // Deduplicate code arrays
-      size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta();
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
-      if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
-        DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&code_size, sizeof(code_size))) {
-          ReportWriteFailure("method code size", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += sizeof(code_size);
-        DCHECK_CODE_OFFSET();
-        if (!file->WriteFully(&code[0], code_size)) {
-          ReportWriteFailure("method code", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += code_size;
-      }
-      DCHECK_CODE_OFFSET();
-
-      const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
-      size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
-
-      // Deduplicate mapping tables
-      SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
-          mapping_table_offsets_.find(&mapping_table);
-      if (mapping_iter != mapping_table_offsets_.end() &&
-          code_offset != method_offsets.mapping_table_offset_) {
-        DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
-            || mapping_iter->second == method_offsets.mapping_table_offset_)
-            << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
-            || code_offset == method_offsets.mapping_table_offset_)
-            << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
-          ReportWriteFailure("mapping table", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += mapping_table_size;
-      }
-      DCHECK_CODE_OFFSET();
-
-      const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
-      size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
-
-      // Deduplicate vmap tables
-      SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
-          vmap_table_offsets_.find(&vmap_table);
-      if (vmap_iter != vmap_table_offsets_.end() &&
-          code_offset != method_offsets.vmap_table_offset_) {
-        DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
-            || vmap_iter->second == method_offsets.vmap_table_offset_)
-            << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
-            || code_offset == method_offsets.vmap_table_offset_)
-            << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
-          ReportWriteFailure("vmap table", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += vmap_table_size;
-      }
-      DCHECK_CODE_OFFSET();
-
-      const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
-      size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
-
-      // Deduplicate GC maps
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter =
-          gc_map_offsets_.find(&gc_map);
-      if (gc_map_iter != gc_map_offsets_.end() &&
-          code_offset != method_offsets.gc_map_offset_) {
-        DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
-            || gc_map_iter->second == method_offsets.gc_map_offset_)
-            << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
-            || code_offset == method_offsets.gc_map_offset_)
-            << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&gc_map[0], gc_map_size)) {
-          ReportWriteFailure("GC map", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += gc_map_size;
-      }
+      code_offset += aligned_code_delta;
       DCHECK_CODE_OFFSET();
     }
+    DCHECK_ALIGNED(code_offset, kArmAlignment);
+    const std::vector<uint8_t>& code = compiled_method->GetCode();
+    uint32_t code_size = code.size() * sizeof(code[0]);
+    CHECK_NE(code_size, 0U);
+
+    // Deduplicate code arrays
+    size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta();
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
+    if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
+      DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&code_size, sizeof(code_size))) {
+        ReportWriteFailure("method code size", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += sizeof(code_size);
+      DCHECK_CODE_OFFSET();
+      if (!file->WriteFully(&code[0], code_size)) {
+        ReportWriteFailure("method code", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += code_size;
+    }
+    DCHECK_CODE_OFFSET();
+
+    const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
+    size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
+
+    // Deduplicate mapping tables
+    SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
+        mapping_table_offsets_.find(&mapping_table);
+    if (mapping_iter != mapping_table_offsets_.end() &&
+        code_offset != method_offsets.mapping_table_offset_) {
+      DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+          || mapping_iter->second == method_offsets.mapping_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+          || code_offset == method_offsets.mapping_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
+        ReportWriteFailure("mapping table", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += mapping_table_size;
+    }
+    DCHECK_CODE_OFFSET();
+
+    const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
+    size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
+
+    // Deduplicate vmap tables
+    SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
+        vmap_table_offsets_.find(&vmap_table);
+    if (vmap_iter != vmap_table_offsets_.end() &&
+        code_offset != method_offsets.vmap_table_offset_) {
+      DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+          || vmap_iter->second == method_offsets.vmap_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+          || code_offset == method_offsets.vmap_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
+        ReportWriteFailure("vmap table", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += vmap_table_size;
+    }
+    DCHECK_CODE_OFFSET();
+
+    const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
+    size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
+
+    // Deduplicate GC maps
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter =
+        gc_map_offsets_.find(&gc_map);
+    if (gc_map_iter != gc_map_offsets_.end() &&
+        code_offset != method_offsets.gc_map_offset_) {
+      DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
+          || gc_map_iter->second == method_offsets.gc_map_offset_)
+          << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
+          || code_offset == method_offsets.gc_map_offset_)
+          << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&gc_map[0], gc_map_size)) {
+        ReportWriteFailure("GC map", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += gc_map_size;
+    }
+    DCHECK_CODE_OFFSET();
   }
   const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
   const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
-    if (!compiled_invoke_stub->IsExecutableInElf()) {
+    uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
+                                                             compiler_->GetInstructionSet());
+    uint32_t aligned_code_delta = aligned_code_offset - code_offset;
+    if (aligned_code_delta != 0) {
+      off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
+      if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
+        PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset
+                    << " Expected: " << aligned_code_offset;
+        return 0;
+      }
+      code_offset += aligned_code_delta;
+      DCHECK_CODE_OFFSET();
+    }
+    DCHECK_ALIGNED(code_offset, kArmAlignment);
+    const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
+    uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
+    CHECK_NE(invoke_stub_size, 0U);
+
+    // Deduplicate invoke stubs
+    size_t offset = code_offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta();
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
+        code_offsets_.find(&invoke_stub);
+    if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) {
+      DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) {
+        ReportWriteFailure("invoke stub code size", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += sizeof(invoke_stub_size);
+      DCHECK_CODE_OFFSET();
+      if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
+        ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += invoke_stub_size;
+      DCHECK_CODE_OFFSET();
+    }
+  }
+
+#if defined(ART_USE_LLVM_COMPILER)
+  if (!is_static) {
+    const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
+    if (compiled_proxy_stub != NULL) {
       uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
                                                                compiler_->GetInstructionSet());
       uint32_t aligned_code_delta = aligned_code_offset - code_offset;
+      CHECK(aligned_code_delta < 48u);
       if (aligned_code_delta != 0) {
         off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
         if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
-          PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset
+          PLOG(ERROR) << "Failed to seek to align proxy stub code. Actual: " << new_offset
                       << " Expected: " << aligned_code_offset;
           return 0;
         }
@@ -756,33 +734,35 @@
         DCHECK_CODE_OFFSET();
       }
       DCHECK_ALIGNED(code_offset, kArmAlignment);
-      const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
-      uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
-      CHECK_NE(invoke_stub_size, 0U);
+      const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode();
+      uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]);
+      CHECK_NE(proxy_stub_size, 0U);
 
-      // Deduplicate invoke stubs
-      size_t offset = code_offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta();
+      // Deduplicate proxy stubs
+      size_t offset = code_offset + sizeof(proxy_stub_size) + compiled_proxy_stub->CodeDelta();
       SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
-          code_offsets_.find(&invoke_stub);
-      if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) {
-        DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+          code_offsets_.find(&proxy_stub);
+      if (stub_iter != code_offsets_.end() && offset != method_offsets.proxy_stub_offset_) {
+        DCHECK(stub_iter->second == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file);
       } else {
-        DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) {
-          ReportWriteFailure("invoke stub code size", method_idx, dex_file, file);
+        DCHECK(offset == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file);
+        if (!file->WriteFully(&proxy_stub_size, sizeof(proxy_stub_size))) {
+          ReportWriteFailure("proxy stub code size", method_idx, dex_file, file);
           return 0;
         }
-        code_offset += sizeof(invoke_stub_size);
+        code_offset += sizeof(proxy_stub_size);
         DCHECK_CODE_OFFSET();
-        if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
-          ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
+        if (!file->WriteFully(&proxy_stub[0], proxy_stub_size)) {
+          ReportWriteFailure("proxy stub code", method_idx, dex_file, file);
           return 0;
         }
-        code_offset += invoke_stub_size;
+        code_offset += proxy_stub_size;
+        DCHECK_CODE_OFFSET();
       }
       DCHECK_CODE_OFFSET();
     }
   }
+#endif
 
   return code_offset;
 }
@@ -867,48 +847,4 @@
   return true;
 }
 
-OatWriter::OatElfImage::OatElfImage(const ElfImage& image)
-    : elf_offset_(0), elf_size_(image.size()), elf_addr_(image.begin()) {
-}
-
-size_t OatWriter::OatElfImage::SizeOf() const {
-  return (sizeof(elf_offset_) + sizeof(elf_size_));
-}
-
-uint32_t OatWriter::OatElfImage::GetElfSize() const {
-  return elf_size_;
-}
-
-uint32_t OatWriter::OatElfImage::GetElfOffset() const {
-  DCHECK_NE(elf_offset_, 0U);
-  return elf_offset_;
-}
-
-void OatWriter::OatElfImage::SetElfOffset(uint32_t offset) {
-  DCHECK_NE(offset, 0U);
-  DCHECK_EQ((offset & 0x3LU), 0U);
-  elf_offset_ = offset;
-}
-
-bool OatWriter::OatElfImage::Write(File* file) const {
-  DCHECK_NE(elf_offset_, 0U);
-  if (!file->WriteFully(&elf_offset_, sizeof(elf_offset_))) {
-    PLOG(ERROR) << "Failed to write ELF offset to " << file->name();
-    return false;
-  }
-  if (!file->WriteFully(&elf_size_, sizeof(elf_size_))) {
-    PLOG(ERROR) << "Failed to write ELF size to " << file->name();
-    return false;
-  }
-  return true;
-}
-
-bool OatWriter::OatElfImage::WriteElfImage(File* file) const {
-  if (!file->WriteFully(elf_addr_, elf_size_)) {
-    PLOG(ERROR) << "Failed to write ELF image to " << file->name();
-    return false;
-  }
-  return true;
-}
-
 }  // namespace art