Refactor linker files from compiler/ to dex2oat/.

This shifts some code from the libart-compiler.so to dex2oat
and reduces memory needed for JIT. We also avoid loading the
libart-dexlayout.so for JIT but the memory savings are
minimal (one shared clean page, two shared dirty pages and
some per-app kernel mmap data) as the code has never been
needed in memory by JIT.

aosp_angler-userdebug file sizes (stripped):
  lib64/libart-compiler.so: 2989112 -> 2671888 (-310KiB)
  lib/libart-compiler.so: 2160816 -> 1939276 (-216KiB)
  bin/dex2oat: 141868 -> 368808 (+222KiB)
LOAD/executable elf mapping sizes:
  lib64/libart-compiler.so: 2866308 -> 2555500 (-304KiB)
  lib/libart-compiler.so: 2050960 -> 1834836 (-211KiB)
  bin/dex2oat: 129316 -> 345916 (+212KiB)

Test: m test-art-host-gtest
Test: testrunner.py --host
Test: cd art/; mma; cd -
Change-Id: If62f02847a6cbb208eaf7e1f3e91af4663fa4a5f
diff --git a/compiler/Android.bp b/compiler/Android.bp
index c798d97..1475679 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -38,7 +38,6 @@
         "driver/dex_compilation_unit.cc",
         "linker/buffered_output_stream.cc",
         "linker/file_output_stream.cc",
-        "linker/multi_oat_relative_patcher.cc",
         "linker/output_stream.cc",
         "linker/vector_output_stream.cc",
         "linker/relative_patcher.cc",
@@ -95,10 +94,6 @@
         "utils/jni_macro_assembler.cc",
         "utils/swap_space.cc",
         "compiler.cc",
-        "elf_writer.cc",
-        "elf_writer_quick.cc",
-        "image_writer.cc",
-        "oat_writer.cc",
     ],
 
     codegen: {
@@ -198,19 +193,10 @@
     generated_sources: ["art_compiler_operator_srcs"],
     shared_libs: [
         "libbase",
-        "liblz4",
         "liblzma",
     ],
     include_dirs: ["art/disassembler"],
     export_include_dirs: ["."],
-
-    // For SHA-1 checksumming of build ID
-    static: {
-        whole_static_libs: ["libcrypto"],
-    },
-    shared: {
-        shared_libs: ["libcrypto"],
-    },
 }
 
 gensrcs {
@@ -222,7 +208,6 @@
         "dex/dex_to_dex_compiler.h",
         "driver/compiler_driver.h",
         "driver/compiler_options.h",
-        "image_writer.h",
         "optimizing/locations.h",
 
         "utils/arm/constants_arm.h",
@@ -265,7 +250,6 @@
     },
     shared_libs: [
         "libart",
-        "libart-dexlayout",
     ],
 }
 
@@ -305,7 +289,6 @@
     },
     shared_libs: [
         "libartd",
-        "libartd-dexlayout"
     ],
 }
 
@@ -332,15 +315,10 @@
         "dex/dex_to_dex_decompiler_test.cc",
         "driver/compiled_method_storage_test.cc",
         "driver/compiler_driver_test.cc",
-        "elf_writer_test.cc",
         "exception_test.cc",
-        "image_test.cc",
-        "image_write_read_test.cc",
         "jni/jni_compiler_test.cc",
         "linker/method_bss_mapping_encoder_test.cc",
-        "linker/multi_oat_relative_patcher_test.cc",
         "linker/output_stream_test.cc",
-        "oat_test.cc",
         "optimizing/bounds_check_elimination_test.cc",
         "optimizing/dominator_test.cc",
         "optimizing/find_loops_test.cc",
diff --git a/compiler/debug/dwarf/dwarf_test.h b/compiler/debug/dwarf/dwarf_test.h
index e1f538d..b30ff14 100644
--- a/compiler/debug/dwarf/dwarf_test.h
+++ b/compiler/debug/dwarf/dwarf_test.h
@@ -28,8 +28,8 @@
 
 #include "base/unix_file/fd_file.h"
 #include "common_runtime_test.h"
-#include "elf_builder.h"
 #include "gtest/gtest.h"
+#include "linker/elf_builder.h"
 #include "linker/file_output_stream.h"
 #include "os.h"
 
@@ -62,8 +62,8 @@
     // Write simple elf file with just the DWARF sections.
     InstructionSet isa = (sizeof(typename ElfTypes::Addr) == 8) ? kX86_64 : kX86;
     ScratchFile file;
-    FileOutputStream output_stream(file.GetFile());
-    ElfBuilder<ElfTypes> builder(isa, nullptr, &output_stream);
+    linker::FileOutputStream output_stream(file.GetFile());
+    linker::ElfBuilder<ElfTypes> builder(isa, nullptr, &output_stream);
     builder.Start();
     if (!debug_info_data_.empty()) {
       builder.WriteSection(".debug_info", &debug_info_data_);
diff --git a/compiler/debug/elf_debug_frame_writer.h b/compiler/debug/elf_debug_frame_writer.h
index f9d33c1..6dacdfa 100644
--- a/compiler/debug/elf_debug_frame_writer.h
+++ b/compiler/debug/elf_debug_frame_writer.h
@@ -24,7 +24,7 @@
 #include "debug/dwarf/dwarf_constants.h"
 #include "debug/dwarf/headers.h"
 #include "debug/method_debug_info.h"
-#include "elf_builder.h"
+#include "linker/elf_builder.h"
 
 namespace art {
 namespace debug {
@@ -168,7 +168,7 @@
 }
 
 template<typename ElfTypes>
-void WriteCFISection(ElfBuilder<ElfTypes>* builder,
+void WriteCFISection(linker::ElfBuilder<ElfTypes>* builder,
                      const ArrayRef<const MethodDebugInfo>& method_infos,
                      dwarf::CFIFormat format,
                      bool write_oat_patches) {
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index 2801240..2b61727 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -29,9 +29,9 @@
 #include "debug/method_debug_info.h"
 #include "dex_file-inl.h"
 #include "dex_file.h"
-#include "elf_builder.h"
 #include "heap_poisoning.h"
 #include "linear_alloc.h"
+#include "linker/elf_builder.h"
 #include "mirror/array.h"
 #include "mirror/class-inl.h"
 #include "mirror/class.h"
@@ -68,7 +68,7 @@
   using Elf_Addr = typename ElfTypes::Addr;
 
  public:
-  explicit ElfDebugInfoWriter(ElfBuilder<ElfTypes>* builder)
+  explicit ElfDebugInfoWriter(linker::ElfBuilder<ElfTypes>* builder)
       : builder_(builder),
         debug_abbrev_(&debug_abbrev_buffer_) {
   }
@@ -93,7 +93,7 @@
   }
 
  private:
-  ElfBuilder<ElfTypes>* builder_;
+  linker::ElfBuilder<ElfTypes>* builder_;
   std::vector<uintptr_t> debug_info_patches_;
   std::vector<uint8_t> debug_abbrev_buffer_;
   dwarf::DebugAbbrevWriter<> debug_abbrev_;
diff --git a/compiler/debug/elf_debug_line_writer.h b/compiler/debug/elf_debug_line_writer.h
index cdd1e53..cf5d65e 100644
--- a/compiler/debug/elf_debug_line_writer.h
+++ b/compiler/debug/elf_debug_line_writer.h
@@ -25,7 +25,7 @@
 #include "debug/dwarf/headers.h"
 #include "debug/elf_compilation_unit.h"
 #include "dex_file-inl.h"
-#include "elf_builder.h"
+#include "linker/elf_builder.h"
 #include "stack_map.h"
 
 namespace art {
@@ -43,7 +43,7 @@
   using Elf_Addr = typename ElfTypes::Addr;
 
  public:
-  explicit ElfDebugLineWriter(ElfBuilder<ElfTypes>* builder) : builder_(builder) {
+  explicit ElfDebugLineWriter(linker::ElfBuilder<ElfTypes>* builder) : builder_(builder) {
   }
 
   void Start() {
@@ -280,7 +280,7 @@
   }
 
  private:
-  ElfBuilder<ElfTypes>* builder_;
+  linker::ElfBuilder<ElfTypes>* builder_;
   std::vector<uintptr_t> debug_line_patches_;
 };
 
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc
index c5ff858..33c46d7 100644
--- a/compiler/debug/elf_debug_writer.cc
+++ b/compiler/debug/elf_debug_writer.cc
@@ -29,7 +29,7 @@
 #include "debug/elf_gnu_debugdata_writer.h"
 #include "debug/elf_symtab_writer.h"
 #include "debug/method_debug_info.h"
-#include "elf_builder.h"
+#include "linker/elf_builder.h"
 #include "linker/vector_output_stream.h"
 #include "oat.h"
 
@@ -37,7 +37,7 @@
 namespace debug {
 
 template <typename ElfTypes>
-void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
+void WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder,
                     const ArrayRef<const MethodDebugInfo>& method_infos,
                     dwarf::CFIFormat cfi_format,
                     bool write_oat_patches) {
@@ -133,8 +133,9 @@
     const ArrayRef<const MethodDebugInfo>& method_infos) {
   std::vector<uint8_t> buffer;
   buffer.reserve(KB);
-  VectorOutputStream out("Debug ELF file", &buffer);
-  std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, features, &out));
+  linker::VectorOutputStream out("Debug ELF file", &buffer);
+  std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
+      new linker::ElfBuilder<ElfTypes>(isa, features, &out));
   // No program headers since the ELF file is not linked and has no allocated sections.
   builder->Start(false /* write_program_headers */);
   WriteDebugInfo(builder.get(),
@@ -165,8 +166,9 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   std::vector<uint8_t> buffer;
   buffer.reserve(KB);
-  VectorOutputStream out("Debug ELF file", &buffer);
-  std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, features, &out));
+  linker::VectorOutputStream out("Debug ELF file", &buffer);
+  std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
+      new linker::ElfBuilder<ElfTypes>(isa, features, &out));
   // No program headers since the ELF file is not linked and has no allocated sections.
   builder->Start(false /* write_program_headers */);
   ElfDebugInfoWriter<ElfTypes> info_writer(builder.get());
@@ -192,12 +194,12 @@
 
 // Explicit instantiations
 template void WriteDebugInfo<ElfTypes32>(
-    ElfBuilder<ElfTypes32>* builder,
+    linker::ElfBuilder<ElfTypes32>* builder,
     const ArrayRef<const MethodDebugInfo>& method_infos,
     dwarf::CFIFormat cfi_format,
     bool write_oat_patches);
 template void WriteDebugInfo<ElfTypes64>(
-    ElfBuilder<ElfTypes64>* builder,
+    linker::ElfBuilder<ElfTypes64>* builder,
     const ArrayRef<const MethodDebugInfo>& method_infos,
     dwarf::CFIFormat cfi_format,
     bool write_oat_patches);
diff --git a/compiler/debug/elf_debug_writer.h b/compiler/debug/elf_debug_writer.h
index 6e26ba3..d24ca9b 100644
--- a/compiler/debug/elf_debug_writer.h
+++ b/compiler/debug/elf_debug_writer.h
@@ -23,7 +23,7 @@
 #include "base/macros.h"
 #include "base/mutex.h"
 #include "debug/dwarf/dwarf_constants.h"
-#include "elf_builder.h"
+#include "linker/elf_builder.h"
 
 namespace art {
 class OatHeader;
@@ -35,7 +35,7 @@
 
 template <typename ElfTypes>
 void WriteDebugInfo(
-    ElfBuilder<ElfTypes>* builder,
+    linker::ElfBuilder<ElfTypes>* builder,
     const ArrayRef<const MethodDebugInfo>& method_infos,
     dwarf::CFIFormat cfi_format,
     bool write_oat_patches);
diff --git a/compiler/debug/elf_gnu_debugdata_writer.h b/compiler/debug/elf_gnu_debugdata_writer.h
index fb63d62..1cdf6b0 100644
--- a/compiler/debug/elf_gnu_debugdata_writer.h
+++ b/compiler/debug/elf_gnu_debugdata_writer.h
@@ -20,7 +20,7 @@
 #include <vector>
 
 #include "arch/instruction_set.h"
-#include "elf_builder.h"
+#include "linker/elf_builder.h"
 #include "linker/vector_output_stream.h"
 
 // liblzma.
@@ -85,8 +85,9 @@
     const ArrayRef<const MethodDebugInfo>& method_infos) {
   std::vector<uint8_t> buffer;
   buffer.reserve(KB);
-  VectorOutputStream out("Mini-debug-info ELF file", &buffer);
-  std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, features, &out));
+  linker::VectorOutputStream out("Mini-debug-info ELF file", &buffer);
+  std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
+      new linker::ElfBuilder<ElfTypes>(isa, features, &out));
   builder->Start();
   // Mirror .rodata and .text as NOBITS sections.
   // It is needed to detected relocations after compression.
diff --git a/compiler/debug/elf_symtab_writer.h b/compiler/debug/elf_symtab_writer.h
index abd2699..b37f984 100644
--- a/compiler/debug/elf_symtab_writer.h
+++ b/compiler/debug/elf_symtab_writer.h
@@ -20,7 +20,7 @@
 #include <unordered_set>
 
 #include "debug/method_debug_info.h"
-#include "elf_builder.h"
+#include "linker/elf_builder.h"
 #include "utils.h"
 
 namespace art {
@@ -36,7 +36,7 @@
 constexpr bool kGenerateSingleArmMappingSymbol = true;
 
 template <typename ElfTypes>
-static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
+static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder,
                               const ArrayRef<const MethodDebugInfo>& method_infos,
                               bool with_signature) {
   uint64_t mapping_symbol_address = std::numeric_limits<uint64_t>::max();
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
deleted file mode 100644
index 37e4f11..0000000
--- a/compiler/elf_writer.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "elf_writer.h"
-
-#include "base/unix_file/fd_file.h"
-#include "elf_file.h"
-
-namespace art {
-
-uintptr_t ElfWriter::GetOatDataAddress(ElfFile* elf_file) {
-  uintptr_t oatdata_address = elf_file->FindSymbolAddress(SHT_DYNSYM,
-                                                           "oatdata",
-                                                           false);
-  CHECK_NE(0U, oatdata_address);
-  return oatdata_address;
-}
-
-void ElfWriter::GetOatElfInformation(File* file,
-                                     size_t* oat_loaded_size,
-                                     size_t* oat_data_offset) {
-  std::string error_msg;
-  std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file,
-                                                  false,
-                                                  false,
-                                                  /*low_4gb*/false,
-                                                  &error_msg));
-  CHECK(elf_file.get() != nullptr) << error_msg;
-
-  bool success = elf_file->GetLoadedSize(oat_loaded_size, &error_msg);
-  CHECK(success) << error_msg;
-  CHECK_NE(0U, *oat_loaded_size);
-  *oat_data_offset = GetOatDataAddress(elf_file.get());
-  CHECK_NE(0U, *oat_data_offset);
-}
-
-bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) {
-  std::string error_msg;
-  std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb*/false, &error_msg));
-  CHECK(elf_file.get() != nullptr) << error_msg;
-
-  // Lookup "oatdata" symbol address.
-  uintptr_t oatdata_address = ElfWriter::GetOatDataAddress(elf_file.get());
-  uintptr_t base_address = oat_data_begin - oatdata_address;
-
-  return elf_file->Fixup(base_address);
-}
-
-}  // namespace art
diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h
deleted file mode 100644
index a8a5bc3..0000000
--- a/compiler/elf_writer.h
+++ /dev/null
@@ -1,83 +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_COMPILER_ELF_WRITER_H_
-#define ART_COMPILER_ELF_WRITER_H_
-
-#include <stdint.h>
-#include <cstddef>
-#include <string>
-#include <vector>
-
-#include "base/array_ref.h"
-#include "base/macros.h"
-#include "base/mutex.h"
-#include "os.h"
-
-namespace art {
-
-class ElfFile;
-class OutputStream;
-
-namespace debug {
-struct MethodDebugInfo;
-}  // namespace debug
-
-class ElfWriter {
- public:
-  // Looks up information about location of oat file in elf file container.
-  // Used for ImageWriter to perform memory layout.
-  static void GetOatElfInformation(File* file,
-                                   size_t* oat_loaded_size,
-                                   size_t* oat_data_offset);
-
-  // Returns runtime oat_data runtime address for an opened ElfFile.
-  static uintptr_t GetOatDataAddress(ElfFile* elf_file);
-
-  static bool Fixup(File* file, uintptr_t oat_data_begin);
-
-  virtual ~ElfWriter() {}
-
-  virtual void Start() = 0;
-  virtual void PrepareDynamicSection(size_t rodata_size,
-                                     size_t text_size,
-                                     size_t bss_size,
-                                     size_t bss_methods_offset,
-                                     size_t bss_roots_offset) = 0;
-  virtual void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) = 0;
-  virtual OutputStream* StartRoData() = 0;
-  virtual void EndRoData(OutputStream* rodata) = 0;
-  virtual OutputStream* StartText() = 0;
-  virtual void EndText(OutputStream* text) = 0;
-  virtual void WriteDynamicSection() = 0;
-  virtual void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) = 0;
-  virtual bool End() = 0;
-
-  // Get the ELF writer's stream. This stream can be used for writing data directly
-  // to a section after the section has been finished. When that's done, the user
-  // should Seek() back to the position where the stream was before this operation.
-  virtual OutputStream* GetStream() = 0;
-
-  // Get the size that the loaded ELF file will occupy in memory.
-  virtual size_t GetLoadedSize() = 0;
-
- protected:
-  ElfWriter() = default;
-};
-
-}  // namespace art
-
-#endif  // ART_COMPILER_ELF_WRITER_H_
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
deleted file mode 100644
index 5d6dd2e..0000000
--- a/compiler/elf_writer_quick.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "elf_writer_quick.h"
-
-#include <openssl/sha.h>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "base/casts.h"
-#include "base/logging.h"
-#include "compiled_method.h"
-#include "debug/elf_debug_writer.h"
-#include "debug/method_debug_info.h"
-#include "driver/compiler_options.h"
-#include "elf.h"
-#include "elf_builder.h"
-#include "elf_utils.h"
-#include "globals.h"
-#include "leb128.h"
-#include "linker/buffered_output_stream.h"
-#include "linker/file_output_stream.h"
-#include "thread-current-inl.h"
-#include "thread_pool.h"
-#include "utils.h"
-
-namespace art {
-
-// .eh_frame and .debug_frame are almost identical.
-// Except for some minor formatting differences, the main difference
-// is that .eh_frame is allocated within the running program because
-// it is used by C++ exception handling (which we do not use so we
-// can choose either).  C++ compilers generally tend to use .eh_frame
-// because if they need it sometimes, they might as well always use it.
-// Let's use .debug_frame because it is easier to strip or compress.
-constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
-
-class DebugInfoTask : public Task {
- public:
-  DebugInfoTask(InstructionSet isa,
-                const InstructionSetFeatures* features,
-                size_t rodata_section_size,
-                size_t text_section_size,
-                const ArrayRef<const debug::MethodDebugInfo>& method_infos)
-      : isa_(isa),
-        instruction_set_features_(features),
-        rodata_section_size_(rodata_section_size),
-        text_section_size_(text_section_size),
-        method_infos_(method_infos) {
-  }
-
-  void Run(Thread*) {
-    result_ = debug::MakeMiniDebugInfo(isa_,
-                                       instruction_set_features_,
-                                       rodata_section_size_,
-                                       text_section_size_,
-                                       method_infos_);
-  }
-
-  std::vector<uint8_t>* GetResult() {
-    return &result_;
-  }
-
- private:
-  InstructionSet isa_;
-  const InstructionSetFeatures* instruction_set_features_;
-  size_t rodata_section_size_;
-  size_t text_section_size_;
-  const ArrayRef<const debug::MethodDebugInfo> method_infos_;
-  std::vector<uint8_t> result_;
-};
-
-template <typename ElfTypes>
-class ElfWriterQuick FINAL : public ElfWriter {
- public:
-  ElfWriterQuick(InstructionSet instruction_set,
-                 const InstructionSetFeatures* features,
-                 const CompilerOptions* compiler_options,
-                 File* elf_file);
-  ~ElfWriterQuick();
-
-  void Start() OVERRIDE;
-  void PrepareDynamicSection(size_t rodata_size,
-                             size_t text_size,
-                             size_t bss_size,
-                             size_t bss_methods_offset,
-                             size_t bss_roots_offset) OVERRIDE;
-  void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
-  OutputStream* StartRoData() OVERRIDE;
-  void EndRoData(OutputStream* rodata) OVERRIDE;
-  OutputStream* StartText() OVERRIDE;
-  void EndText(OutputStream* text) OVERRIDE;
-  void WriteDynamicSection() OVERRIDE;
-  void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
-  bool End() OVERRIDE;
-
-  virtual OutputStream* GetStream() OVERRIDE;
-
-  size_t GetLoadedSize() OVERRIDE;
-
-  static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
-                               std::vector<uint8_t>* buffer);
-
- private:
-  const InstructionSetFeatures* instruction_set_features_;
-  const CompilerOptions* const compiler_options_;
-  File* const elf_file_;
-  size_t rodata_size_;
-  size_t text_size_;
-  size_t bss_size_;
-  std::unique_ptr<BufferedOutputStream> output_stream_;
-  std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
-  std::unique_ptr<DebugInfoTask> debug_info_task_;
-  std::unique_ptr<ThreadPool> debug_info_thread_pool_;
-
-  void ComputeFileBuildId(uint8_t (*build_id)[ElfBuilder<ElfTypes>::kBuildIdLen]);
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
-};
-
-std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
-                                                const InstructionSetFeatures* features,
-                                                const CompilerOptions* compiler_options,
-                                                File* elf_file) {
-  if (Is64BitInstructionSet(instruction_set)) {
-    return std::make_unique<ElfWriterQuick<ElfTypes64>>(instruction_set,
-                                                        features,
-                                                        compiler_options,
-                                                        elf_file);
-  } else {
-    return std::make_unique<ElfWriterQuick<ElfTypes32>>(instruction_set,
-                                                        features,
-                                                        compiler_options,
-                                                        elf_file);
-  }
-}
-
-template <typename ElfTypes>
-ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set,
-                                         const InstructionSetFeatures* features,
-                                         const CompilerOptions* compiler_options,
-                                         File* elf_file)
-    : ElfWriter(),
-      instruction_set_features_(features),
-      compiler_options_(compiler_options),
-      elf_file_(elf_file),
-      rodata_size_(0u),
-      text_size_(0u),
-      bss_size_(0u),
-      output_stream_(
-          std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(elf_file))),
-      builder_(new ElfBuilder<ElfTypes>(instruction_set, features, output_stream_.get())) {}
-
-template <typename ElfTypes>
-ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {}
-
-template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::Start() {
-  builder_->Start();
-  if (compiler_options_->GetGenerateBuildId()) {
-    builder_->WriteBuildIdSection();
-  }
-}
-
-template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size,
-                                                     size_t text_size,
-                                                     size_t bss_size,
-                                                     size_t bss_methods_offset,
-                                                     size_t bss_roots_offset) {
-  DCHECK_EQ(rodata_size_, 0u);
-  rodata_size_ = rodata_size;
-  DCHECK_EQ(text_size_, 0u);
-  text_size_ = text_size;
-  DCHECK_EQ(bss_size_, 0u);
-  bss_size_ = bss_size;
-  builder_->PrepareDynamicSection(elf_file_->GetPath(),
-                                  rodata_size_,
-                                  text_size_,
-                                  bss_size_,
-                                  bss_methods_offset,
-                                  bss_roots_offset);
-}
-
-template <typename ElfTypes>
-OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() {
-  auto* rodata = builder_->GetRoData();
-  rodata->Start();
-  return rodata;
-}
-
-template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) {
-  CHECK_EQ(builder_->GetRoData(), rodata);
-  builder_->GetRoData()->End();
-}
-
-template <typename ElfTypes>
-OutputStream* ElfWriterQuick<ElfTypes>::StartText() {
-  auto* text = builder_->GetText();
-  text->Start();
-  return text;
-}
-
-template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) {
-  CHECK_EQ(builder_->GetText(), text);
-  builder_->GetText()->End();
-}
-
-template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::WriteDynamicSection() {
-  if (bss_size_ != 0u) {
-    builder_->GetBss()->WriteNoBitsSection(bss_size_);
-  }
-  if (builder_->GetIsa() == kMips || builder_->GetIsa() == kMips64) {
-    builder_->WriteMIPSabiflagsSection();
-  }
-  builder_->WriteDynamicSection();
-}
-
-template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::PrepareDebugInfo(
-    const ArrayRef<const debug::MethodDebugInfo>& method_infos) {
-  if (!method_infos.empty() && compiler_options_->GetGenerateMiniDebugInfo()) {
-    // Prepare the mini-debug-info in background while we do other I/O.
-    Thread* self = Thread::Current();
-    debug_info_task_ = std::unique_ptr<DebugInfoTask>(
-        new DebugInfoTask(builder_->GetIsa(),
-                          instruction_set_features_,
-                          rodata_size_,
-                          text_size_,
-                          method_infos));
-    debug_info_thread_pool_ = std::unique_ptr<ThreadPool>(
-        new ThreadPool("Mini-debug-info writer", 1));
-    debug_info_thread_pool_->AddTask(self, debug_info_task_.get());
-    debug_info_thread_pool_->StartWorkers(self);
-  }
-}
-
-template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::WriteDebugInfo(
-    const ArrayRef<const debug::MethodDebugInfo>& method_infos) {
-  if (!method_infos.empty()) {
-    if (compiler_options_->GetGenerateDebugInfo()) {
-      // Generate all the debug information we can.
-      debug::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */);
-    }
-    if (compiler_options_->GetGenerateMiniDebugInfo()) {
-      // Wait for the mini-debug-info generation to finish and write it to disk.
-      Thread* self = Thread::Current();
-      DCHECK(debug_info_thread_pool_ != nullptr);
-      debug_info_thread_pool_->Wait(self, true, false);
-      builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult());
-    }
-  }
-}
-
-template <typename ElfTypes>
-bool ElfWriterQuick<ElfTypes>::End() {
-  builder_->End();
-  if (compiler_options_->GetGenerateBuildId()) {
-    uint8_t build_id[ElfBuilder<ElfTypes>::kBuildIdLen];
-    ComputeFileBuildId(&build_id);
-    builder_->WriteBuildId(build_id);
-  }
-  return builder_->Good();
-}
-
-template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::ComputeFileBuildId(
-    uint8_t (*build_id)[ElfBuilder<ElfTypes>::kBuildIdLen]) {
-  constexpr int kBufSize = 8192;
-  std::vector<char> buffer(kBufSize);
-  int64_t offset = 0;
-  SHA_CTX ctx;
-  SHA1_Init(&ctx);
-  while (true) {
-    int64_t bytes_read = elf_file_->Read(buffer.data(), kBufSize, offset);
-    CHECK_GE(bytes_read, 0);
-    if (bytes_read == 0) {
-      // End of file.
-      break;
-    }
-    SHA1_Update(&ctx, buffer.data(), bytes_read);
-    offset += bytes_read;
-  }
-  SHA1_Final(*build_id, &ctx);
-}
-
-template <typename ElfTypes>
-OutputStream* ElfWriterQuick<ElfTypes>::GetStream() {
-  return builder_->GetStream();
-}
-
-template <typename ElfTypes>
-size_t ElfWriterQuick<ElfTypes>::GetLoadedSize() {
-  return builder_->GetLoadedSize();
-}
-
-// Explicit instantiations
-template class ElfWriterQuick<ElfTypes32>;
-template class ElfWriterQuick<ElfTypes64>;
-
-}  // namespace art
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
deleted file mode 100644
index 3d5dd39..0000000
--- a/compiler/elf_writer_quick.h
+++ /dev/null
@@ -1,38 +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_COMPILER_ELF_WRITER_QUICK_H_
-#define ART_COMPILER_ELF_WRITER_QUICK_H_
-
-#include <memory>
-
-#include "arch/instruction_set.h"
-#include "elf_writer.h"
-#include "os.h"
-
-namespace art {
-
-class CompilerOptions;
-class InstructionSetFeatures;
-
-std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
-                                                const InstructionSetFeatures* features,
-                                                const CompilerOptions* compiler_options,
-                                                File* elf_file);
-
-}  // namespace art
-
-#endif  // ART_COMPILER_ELF_WRITER_QUICK_H_
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
deleted file mode 100644
index 984e9ee..0000000
--- a/compiler/elf_writer_test.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "elf_file.h"
-
-#include "base/unix_file/fd_file.h"
-#include "common_compiler_test.h"
-#include "elf_builder.h"
-#include "elf_file.h"
-#include "elf_file_impl.h"
-#include "elf_writer_quick.h"
-#include "oat.h"
-#include "utils.h"
-
-namespace art {
-
-class ElfWriterTest : public CommonCompilerTest {
- protected:
-  virtual void SetUp() {
-    ReserveImageSpace();
-    CommonCompilerTest::SetUp();
-  }
-};
-
-#define EXPECT_ELF_FILE_ADDRESS(ef, expected_value, symbol_name, build_map) \
-  do { \
-    void* addr = reinterpret_cast<void*>((ef)->FindSymbolAddress(SHT_DYNSYM, \
-                                                                 symbol_name, \
-                                                                 build_map)); \
-    EXPECT_NE(nullptr, addr); \
-    if ((expected_value) == nullptr) { \
-      (expected_value) = addr; \
-    }                        \
-    EXPECT_EQ(expected_value, addr); \
-    EXPECT_EQ(expected_value, (ef)->FindDynamicSymbolAddress(symbol_name)); \
-  } while (false)
-
-TEST_F(ElfWriterTest, dlsym) {
-  std::string elf_location = GetCoreOatLocation();
-  std::string elf_filename = GetSystemImageFilename(elf_location.c_str(), kRuntimeISA);
-  LOG(INFO) << "elf_filename=" << elf_filename;
-
-  UnreserveImageSpace();
-  void* dl_oatdata = nullptr;
-  void* dl_oatexec = nullptr;
-  void* dl_oatlastword = nullptr;
-
-  std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
-  ASSERT_TRUE(file.get() != nullptr) << elf_filename;
-  {
-    std::string error_msg;
-    std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
-                                              false,
-                                              false,
-                                              /*low_4gb*/false,
-                                              &error_msg));
-    CHECK(ef.get() != nullptr) << error_msg;
-    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", false);
-    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", false);
-    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", false);
-  }
-  {
-    std::string error_msg;
-    std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
-                                              false,
-                                              false,
-                                              /*low_4gb*/false,
-                                              &error_msg));
-    CHECK(ef.get() != nullptr) << error_msg;
-    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", true);
-    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", true);
-    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", true);
-  }
-  {
-    uint8_t* base = reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS);
-    std::string error_msg;
-    std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
-                                              false,
-                                              true,
-                                              /*low_4gb*/false,
-                                              &error_msg,
-                                              base));
-    CHECK(ef.get() != nullptr) << error_msg;
-    CHECK(ef->Load(file.get(), false, /*low_4gb*/false, &error_msg)) << error_msg;
-    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatdata) + reinterpret_cast<uintptr_t>(base),
-        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatdata")));
-    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatexec) + reinterpret_cast<uintptr_t>(base),
-        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatexec")));
-    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatlastword) + reinterpret_cast<uintptr_t>(base),
-        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatlastword")));
-  }
-}
-
-TEST_F(ElfWriterTest, CheckBuildIdPresent) {
-  std::string elf_location = GetCoreOatLocation();
-  std::string elf_filename = GetSystemImageFilename(elf_location.c_str(), kRuntimeISA);
-  LOG(INFO) << "elf_filename=" << elf_filename;
-
-  std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
-  ASSERT_TRUE(file.get() != nullptr);
-  {
-    std::string error_msg;
-    std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
-                                              false,
-                                              false,
-                                              /*low_4gb*/false,
-                                              &error_msg));
-    CHECK(ef.get() != nullptr) << error_msg;
-    EXPECT_TRUE(ef->HasSection(".note.gnu.build-id"));
-  }
-}
-
-TEST_F(ElfWriterTest, EncodeDecodeOatPatches) {
-  const std::vector<std::vector<uintptr_t>> test_data {
-      { 0, 4, 8, 15, 128, 200 },
-      { 8, 8 + 127 },
-      { 8, 8 + 128 },
-      { },
-  };
-  for (const auto& patch_locations : test_data) {
-    constexpr int32_t delta = 0x11235813;
-
-    // Encode patch locations.
-    std::vector<uint8_t> oat_patches;
-    ElfBuilder<ElfTypes32>::EncodeOatPatches(ArrayRef<const uintptr_t>(patch_locations),
-                                             &oat_patches);
-
-    // Create buffer to be patched.
-    std::vector<uint8_t> initial_data(256);
-    for (size_t i = 0; i < initial_data.size(); i++) {
-      initial_data[i] = i;
-    }
-
-    // Patch manually.
-    std::vector<uint8_t> expected = initial_data;
-    for (uintptr_t location : patch_locations) {
-      typedef __attribute__((__aligned__(1))) uint32_t UnalignedAddress;
-      *reinterpret_cast<UnalignedAddress*>(expected.data() + location) += delta;
-    }
-
-    // Decode and apply patch locations.
-    std::vector<uint8_t> actual = initial_data;
-    ElfFileImpl32::ApplyOatPatches(
-        oat_patches.data(), oat_patches.data() + oat_patches.size(), delta,
-        actual.data(), actual.data() + actual.size());
-
-    EXPECT_EQ(expected, actual);
-  }
-}
-
-}  // namespace art
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
deleted file mode 100644
index 7b623dd..0000000
--- a/compiler/image_test.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2011 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 <string.h>
-#include <vector>
-
-#include "image_test.h"
-
-#include "image.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread.h"
-
-namespace art {
-
-TEST_F(ImageTest, TestImageLayout) {
-  std::vector<size_t> image_sizes;
-  std::vector<size_t> image_sizes_extra;
-  // Compile multi-image with ImageLayoutA being the last image.
-  {
-    CompilationHelper helper;
-    Compile(ImageHeader::kStorageModeUncompressed, helper, "ImageLayoutA", {"LMyClass;"});
-    image_sizes = helper.GetImageObjectSectionSizes();
-  }
-  TearDown();
-  runtime_.reset();
-  SetUp();
-  // Compile multi-image with ImageLayoutB being the last image.
-  {
-    CompilationHelper helper;
-    Compile(ImageHeader::kStorageModeUncompressed, helper, "ImageLayoutB", {"LMyClass;"});
-    image_sizes_extra = helper.GetImageObjectSectionSizes();
-  }
-  // Make sure that the new stuff in the clinit in ImageLayoutB is in the last image and not in the
-  // first two images.
-  ASSERT_EQ(image_sizes.size(), image_sizes.size());
-  // Sizes of the object sections should be the same for all but the last image.
-  for (size_t i = 0; i < image_sizes.size() - 1; ++i) {
-    EXPECT_EQ(image_sizes[i], image_sizes_extra[i]);
-  }
-  // Last image should be larger since it has a hash map and a string.
-  EXPECT_LT(image_sizes.back(), image_sizes_extra.back());
-}
-
-TEST_F(ImageTest, ImageHeaderIsValid) {
-    uint32_t image_begin = ART_BASE_ADDRESS;
-    uint32_t image_size_ = 16 * KB;
-    uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
-    uint32_t oat_checksum = 0;
-    uint32_t oat_file_begin = ART_BASE_ADDRESS + (4 * KB);  // page aligned
-    uint32_t oat_data_begin = ART_BASE_ADDRESS + (8 * KB);  // page aligned
-    uint32_t oat_data_end = ART_BASE_ADDRESS + (9 * KB);
-    uint32_t oat_file_end = ART_BASE_ADDRESS + (10 * KB);
-    ImageSection sections[ImageHeader::kSectionCount];
-    ImageHeader image_header(image_begin,
-                             image_size_,
-                             sections,
-                             image_roots,
-                             oat_checksum,
-                             oat_file_begin,
-                             oat_data_begin,
-                             oat_data_end,
-                             oat_file_end,
-                             /*boot_image_begin*/0U,
-                             /*boot_image_size*/0U,
-                             /*boot_oat_begin*/0U,
-                             /*boot_oat_size_*/0U,
-                             sizeof(void*),
-                             /*compile_pic*/false,
-                             /*is_pic*/false,
-                             ImageHeader::kDefaultStorageMode,
-                             /*data_size*/0u);
-    ASSERT_TRUE(image_header.IsValid());
-    ASSERT_TRUE(!image_header.IsAppImage());
-
-    char* magic = const_cast<char*>(image_header.GetMagic());
-    strcpy(magic, "");  // bad magic
-    ASSERT_FALSE(image_header.IsValid());
-    strcpy(magic, "art\n000");  // bad version
-    ASSERT_FALSE(image_header.IsValid());
-}
-
-// Test that pointer to quick code is the same in
-// a default method of an interface and in a copied method
-// of a class which implements the interface. This should be true
-// only if the copied method and the origin method are located in the
-// same oat file.
-TEST_F(ImageTest, TestDefaultMethods) {
-  CompilationHelper helper;
-  Compile(ImageHeader::kStorageModeUncompressed,
-      helper,
-      "DefaultMethods",
-      {"LIface;", "LImpl;", "LIterableBase;"});
-
-  PointerSize pointer_size = class_linker_->GetImagePointerSize();
-  Thread* self = Thread::Current();
-  ScopedObjectAccess soa(self);
-
-  // Test the pointer to quick code is the same in origin method
-  // and in the copied method form the same oat file.
-  mirror::Class* iface_klass = class_linker_->LookupClass(
-      self, "LIface;", ObjPtr<mirror::ClassLoader>());
-  ASSERT_NE(nullptr, iface_klass);
-  ArtMethod* origin = iface_klass->FindInterfaceMethod("defaultMethod", "()V", pointer_size);
-  ASSERT_NE(nullptr, origin);
-  ASSERT_TRUE(origin->GetDeclaringClass() == iface_klass);
-  const void* code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
-  // The origin method should have a pointer to quick code
-  ASSERT_NE(nullptr, code);
-  ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
-  mirror::Class* impl_klass = class_linker_->LookupClass(
-      self, "LImpl;", ObjPtr<mirror::ClassLoader>());
-  ASSERT_NE(nullptr, impl_klass);
-  ArtMethod* copied = FindCopiedMethod(origin, impl_klass);
-  ASSERT_NE(nullptr, copied);
-  // the copied method should have pointer to the same quick code as the origin method
-  ASSERT_EQ(code, copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size));
-
-  // Test the origin method has pointer to quick code
-  // but the copied method has pointer to interpreter
-  // because these methods are in different oat files.
-  mirror::Class* iterable_klass = class_linker_->LookupClass(
-      self, "Ljava/lang/Iterable;", ObjPtr<mirror::ClassLoader>());
-  ASSERT_NE(nullptr, iterable_klass);
-  origin = iterable_klass->FindClassMethod(
-      "forEach", "(Ljava/util/function/Consumer;)V", pointer_size);
-  ASSERT_NE(nullptr, origin);
-  ASSERT_FALSE(origin->IsDirect());
-  ASSERT_TRUE(origin->GetDeclaringClass() == iterable_klass);
-  code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
-  // the origin method should have a pointer to quick code
-  ASSERT_NE(nullptr, code);
-  ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
-  mirror::Class* iterablebase_klass = class_linker_->LookupClass(
-      self, "LIterableBase;", ObjPtr<mirror::ClassLoader>());
-  ASSERT_NE(nullptr, iterablebase_klass);
-  copied = FindCopiedMethod(origin, iterablebase_klass);
-  ASSERT_NE(nullptr, copied);
-  code = copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
-  // the copied method should have a pointer to interpreter
-  ASSERT_TRUE(class_linker_->IsQuickToInterpreterBridge(code));
-}
-
-}  // namespace art
diff --git a/compiler/image_test.h b/compiler/image_test.h
deleted file mode 100644
index f1adedd..0000000
--- a/compiler/image_test.h
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright (C) 2011 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_COMPILER_IMAGE_TEST_H_
-#define ART_COMPILER_IMAGE_TEST_H_
-
-#include "image.h"
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "android-base/stringprintf.h"
-
-#include "art_method-inl.h"
-#include "base/unix_file/fd_file.h"
-#include "class_linker-inl.h"
-#include "common_compiler_test.h"
-#include "compiler_callbacks.h"
-#include "debug/method_debug_info.h"
-#include "dex/quick_compiler_callbacks.h"
-#include "driver/compiler_options.h"
-#include "elf_writer.h"
-#include "elf_writer_quick.h"
-#include "gc/space/image_space.h"
-#include "image_writer.h"
-#include "linker/buffered_output_stream.h"
-#include "linker/file_output_stream.h"
-#include "linker/multi_oat_relative_patcher.h"
-#include "lock_word.h"
-#include "mirror/object-inl.h"
-#include "oat_writer.h"
-#include "scoped_thread_state_change-inl.h"
-#include "signal_catcher.h"
-#include "utils.h"
-
-namespace art {
-
-static const uintptr_t kRequestedImageBase = ART_BASE_ADDRESS;
-
-struct CompilationHelper {
-  std::vector<std::string> dex_file_locations;
-  std::vector<ScratchFile> image_locations;
-  std::vector<std::unique_ptr<const DexFile>> extra_dex_files;
-  std::vector<ScratchFile> image_files;
-  std::vector<ScratchFile> oat_files;
-  std::vector<ScratchFile> vdex_files;
-  std::string image_dir;
-
-  void Compile(CompilerDriver* driver,
-               ImageHeader::StorageMode storage_mode);
-
-  std::vector<size_t> GetImageObjectSectionSizes();
-
-  ~CompilationHelper();
-};
-
-class ImageTest : public CommonCompilerTest {
- protected:
-  virtual void SetUp() {
-    ReserveImageSpace();
-    CommonCompilerTest::SetUp();
-  }
-
-  void TestWriteRead(ImageHeader::StorageMode storage_mode);
-
-  void Compile(ImageHeader::StorageMode storage_mode,
-               CompilationHelper& out_helper,
-               const std::string& extra_dex = "",
-               const std::initializer_list<std::string>& image_classes = {});
-
-  void SetUpRuntimeOptions(RuntimeOptions* options) OVERRIDE {
-    CommonCompilerTest::SetUpRuntimeOptions(options);
-    QuickCompilerCallbacks* new_callbacks =
-        new QuickCompilerCallbacks(CompilerCallbacks::CallbackMode::kCompileBootImage);
-    new_callbacks->SetVerificationResults(verification_results_.get());
-    callbacks_.reset(new_callbacks);
-    options->push_back(std::make_pair("compilercallbacks", callbacks_.get()));
-  }
-
-  std::unordered_set<std::string>* GetImageClasses() OVERRIDE {
-    return new std::unordered_set<std::string>(image_classes_);
-  }
-
-  ArtMethod* FindCopiedMethod(ArtMethod* origin, mirror::Class* klass)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    PointerSize pointer_size = class_linker_->GetImagePointerSize();
-    for (ArtMethod& m : klass->GetCopiedMethods(pointer_size)) {
-      if (strcmp(origin->GetName(), m.GetName()) == 0 &&
-          origin->GetSignature() == m.GetSignature()) {
-        return &m;
-      }
-    }
-    return nullptr;
-  }
-
- private:
-  std::unordered_set<std::string> image_classes_;
-};
-
-inline CompilationHelper::~CompilationHelper() {
-  for (ScratchFile& image_file : image_files) {
-    image_file.Unlink();
-  }
-  for (ScratchFile& oat_file : oat_files) {
-    oat_file.Unlink();
-  }
-  for (ScratchFile& vdex_file : vdex_files) {
-    vdex_file.Unlink();
-  }
-  const int rmdir_result = rmdir(image_dir.c_str());
-  CHECK_EQ(0, rmdir_result);
-}
-
-inline std::vector<size_t> CompilationHelper::GetImageObjectSectionSizes() {
-  std::vector<size_t> ret;
-  for (ScratchFile& image_file : image_files) {
-    std::unique_ptr<File> file(OS::OpenFileForReading(image_file.GetFilename().c_str()));
-    CHECK(file.get() != nullptr);
-    ImageHeader image_header;
-    CHECK_EQ(file->ReadFully(&image_header, sizeof(image_header)), true);
-    CHECK(image_header.IsValid());
-    ret.push_back(image_header.GetObjectsSection().Size());
-  }
-  return ret;
-}
-
-inline void CompilationHelper::Compile(CompilerDriver* driver,
-                                       ImageHeader::StorageMode storage_mode) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  std::vector<const DexFile*> class_path = class_linker->GetBootClassPath();
-
-  for (const std::unique_ptr<const DexFile>& dex_file : extra_dex_files) {
-    {
-      ScopedObjectAccess soa(Thread::Current());
-      // Inject in boot class path so that the compiler driver can see it.
-      class_linker->AppendToBootClassPath(soa.Self(), *dex_file.get());
-    }
-    class_path.push_back(dex_file.get());
-  }
-
-  // Enable write for dex2dex.
-  for (const DexFile* dex_file : class_path) {
-    dex_file_locations.push_back(dex_file->GetLocation());
-    if (dex_file->IsReadOnly()) {
-      dex_file->EnableWrite();
-    }
-  }
-  {
-    // Create a generic tmp file, to be the base of the .art and .oat temporary files.
-    ScratchFile location;
-    for (int i = 0; i < static_cast<int>(class_path.size()); ++i) {
-      std::string cur_location =
-          android::base::StringPrintf("%s-%d.art", location.GetFilename().c_str(), i);
-      image_locations.push_back(ScratchFile(cur_location));
-    }
-  }
-  std::vector<std::string> image_filenames;
-  for (ScratchFile& file : image_locations) {
-    std::string image_filename(GetSystemImageFilename(file.GetFilename().c_str(), kRuntimeISA));
-    image_filenames.push_back(image_filename);
-    size_t pos = image_filename.rfind('/');
-    CHECK_NE(pos, std::string::npos) << image_filename;
-    if (image_dir.empty()) {
-      image_dir = image_filename.substr(0, pos);
-      int mkdir_result = mkdir(image_dir.c_str(), 0700);
-      CHECK_EQ(0, mkdir_result) << image_dir;
-    }
-    image_files.push_back(ScratchFile(OS::CreateEmptyFile(image_filename.c_str())));
-  }
-
-  std::vector<std::string> oat_filenames;
-  std::vector<std::string> vdex_filenames;
-  for (const std::string& image_filename : image_filenames) {
-    std::string oat_filename = ReplaceFileExtension(image_filename, "oat");
-    oat_files.push_back(ScratchFile(OS::CreateEmptyFile(oat_filename.c_str())));
-    oat_filenames.push_back(oat_filename);
-    std::string vdex_filename = ReplaceFileExtension(image_filename, "vdex");
-    vdex_files.push_back(ScratchFile(OS::CreateEmptyFile(vdex_filename.c_str())));
-    vdex_filenames.push_back(vdex_filename);
-  }
-
-  std::unordered_map<const DexFile*, size_t> dex_file_to_oat_index_map;
-  std::vector<const char*> oat_filename_vector;
-  for (const std::string& file : oat_filenames) {
-    oat_filename_vector.push_back(file.c_str());
-  }
-  std::vector<const char*> image_filename_vector;
-  for (const std::string& file : image_filenames) {
-    image_filename_vector.push_back(file.c_str());
-  }
-  size_t image_idx = 0;
-  for (const DexFile* dex_file : class_path) {
-    dex_file_to_oat_index_map.emplace(dex_file, image_idx);
-    ++image_idx;
-  }
-  // TODO: compile_pic should be a test argument.
-  std::unique_ptr<ImageWriter> writer(new ImageWriter(*driver,
-                                                      kRequestedImageBase,
-                                                      /*compile_pic*/false,
-                                                      /*compile_app_image*/false,
-                                                      storage_mode,
-                                                      oat_filename_vector,
-                                                      dex_file_to_oat_index_map,
-                                                      /*dirty_image_objects*/nullptr));
-  {
-    {
-      jobject class_loader = nullptr;
-      TimingLogger timings("ImageTest::WriteRead", false, false);
-      TimingLogger::ScopedTiming t("CompileAll", &timings);
-      driver->SetDexFilesForOatFile(class_path);
-      driver->CompileAll(class_loader, class_path, &timings);
-
-      t.NewTiming("WriteElf");
-      SafeMap<std::string, std::string> key_value_store;
-      std::vector<const char*> dex_filename_vector;
-      for (size_t i = 0; i < class_path.size(); ++i) {
-        dex_filename_vector.push_back("");
-      }
-      key_value_store.Put(OatHeader::kBootClassPathKey,
-                          gc::space::ImageSpace::GetMultiImageBootClassPath(
-                              dex_filename_vector,
-                              oat_filename_vector,
-                              image_filename_vector));
-
-      std::vector<std::unique_ptr<ElfWriter>> elf_writers;
-      std::vector<std::unique_ptr<OatWriter>> oat_writers;
-      for (ScratchFile& oat_file : oat_files) {
-        elf_writers.emplace_back(CreateElfWriterQuick(driver->GetInstructionSet(),
-                                                      driver->GetInstructionSetFeatures(),
-                                                      &driver->GetCompilerOptions(),
-                                                      oat_file.GetFile()));
-        elf_writers.back()->Start();
-        oat_writers.emplace_back(new OatWriter(/*compiling_boot_image*/true,
-                                               &timings,
-                                               /*profile_compilation_info*/nullptr));
-      }
-
-      std::vector<OutputStream*> rodata;
-      std::vector<std::unique_ptr<MemMap>> opened_dex_files_map;
-      std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
-      // Now that we have finalized key_value_store_, start writing the oat file.
-      for (size_t i = 0, size = oat_writers.size(); i != size; ++i) {
-        const DexFile* dex_file = class_path[i];
-        rodata.push_back(elf_writers[i]->StartRoData());
-        ArrayRef<const uint8_t> raw_dex_file(
-            reinterpret_cast<const uint8_t*>(&dex_file->GetHeader()),
-            dex_file->GetHeader().file_size_);
-        oat_writers[i]->AddRawDexFileSource(raw_dex_file,
-                                            dex_file->GetLocation().c_str(),
-                                            dex_file->GetLocationChecksum());
-
-        std::unique_ptr<MemMap> cur_opened_dex_files_map;
-        std::vector<std::unique_ptr<const DexFile>> cur_opened_dex_files;
-        bool dex_files_ok = oat_writers[i]->WriteAndOpenDexFiles(
-            kIsVdexEnabled ? vdex_files[i].GetFile() : oat_files[i].GetFile(),
-            rodata.back(),
-            driver->GetInstructionSet(),
-            driver->GetInstructionSetFeatures(),
-            &key_value_store,
-            /* verify */ false,           // Dex files may be dex-to-dex-ed, don't verify.
-            /* update_input_vdex */ false,
-            &cur_opened_dex_files_map,
-            &cur_opened_dex_files);
-        ASSERT_TRUE(dex_files_ok);
-
-        if (cur_opened_dex_files_map != nullptr) {
-          opened_dex_files_map.push_back(std::move(cur_opened_dex_files_map));
-          for (std::unique_ptr<const DexFile>& cur_dex_file : cur_opened_dex_files) {
-            // dex_file_oat_index_map_.emplace(dex_file.get(), i);
-            opened_dex_files.push_back(std::move(cur_dex_file));
-          }
-        } else {
-          ASSERT_TRUE(cur_opened_dex_files.empty());
-        }
-      }
-      bool image_space_ok = writer->PrepareImageAddressSpace();
-      ASSERT_TRUE(image_space_ok);
-
-      if (kIsVdexEnabled) {
-        for (size_t i = 0, size = vdex_files.size(); i != size; ++i) {
-          std::unique_ptr<BufferedOutputStream> vdex_out =
-              std::make_unique<BufferedOutputStream>(
-                  std::make_unique<FileOutputStream>(vdex_files[i].GetFile()));
-          oat_writers[i]->WriteVerifierDeps(vdex_out.get(), nullptr);
-          oat_writers[i]->WriteChecksumsAndVdexHeader(vdex_out.get());
-        }
-      }
-
-      for (size_t i = 0, size = oat_files.size(); i != size; ++i) {
-        linker::MultiOatRelativePatcher patcher(driver->GetInstructionSet(),
-                                                driver->GetInstructionSetFeatures());
-        OatWriter* const oat_writer = oat_writers[i].get();
-        ElfWriter* const elf_writer = elf_writers[i].get();
-        std::vector<const DexFile*> cur_dex_files(1u, class_path[i]);
-        oat_writer->Initialize(driver, writer.get(), cur_dex_files);
-        oat_writer->PrepareLayout(&patcher);
-        size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset();
-        size_t text_size = oat_writer->GetOatSize() - rodata_size;
-        elf_writer->PrepareDynamicSection(rodata_size,
-                                          text_size,
-                                          oat_writer->GetBssSize(),
-                                          oat_writer->GetBssMethodsOffset(),
-                                          oat_writer->GetBssRootsOffset());
-
-        writer->UpdateOatFileLayout(i,
-                                    elf_writer->GetLoadedSize(),
-                                    oat_writer->GetOatDataOffset(),
-                                    oat_writer->GetOatSize());
-
-        bool rodata_ok = oat_writer->WriteRodata(rodata[i]);
-        ASSERT_TRUE(rodata_ok);
-        elf_writer->EndRoData(rodata[i]);
-
-        OutputStream* text = elf_writer->StartText();
-        bool text_ok = oat_writer->WriteCode(text);
-        ASSERT_TRUE(text_ok);
-        elf_writer->EndText(text);
-
-        bool header_ok = oat_writer->WriteHeader(elf_writer->GetStream(), 0u, 0u, 0u);
-        ASSERT_TRUE(header_ok);
-
-        writer->UpdateOatFileHeader(i, oat_writer->GetOatHeader());
-
-        elf_writer->WriteDynamicSection();
-        elf_writer->WriteDebugInfo(oat_writer->GetMethodDebugInfo());
-
-        bool success = elf_writer->End();
-        ASSERT_TRUE(success);
-      }
-    }
-
-    bool success_image = writer->Write(kInvalidFd,
-                                       image_filename_vector,
-                                       oat_filename_vector);
-    ASSERT_TRUE(success_image);
-
-    for (size_t i = 0, size = oat_filenames.size(); i != size; ++i) {
-      const char* oat_filename = oat_filenames[i].c_str();
-      std::unique_ptr<File> oat_file(OS::OpenFileReadWrite(oat_filename));
-      ASSERT_TRUE(oat_file != nullptr);
-      bool success_fixup = ElfWriter::Fixup(oat_file.get(),
-                                            writer->GetOatDataBegin(i));
-      ASSERT_TRUE(success_fixup);
-      ASSERT_EQ(oat_file->FlushCloseOrErase(), 0) << "Could not flush and close oat file "
-                                                  << oat_filename;
-    }
-  }
-}
-
-inline void ImageTest::Compile(ImageHeader::StorageMode storage_mode,
-                        CompilationHelper& helper,
-                        const std::string& extra_dex,
-                        const std::initializer_list<std::string>& image_classes) {
-  for (const std::string& image_class : image_classes) {
-    image_classes_.insert(image_class);
-  }
-  CreateCompilerDriver(Compiler::kOptimizing, kRuntimeISA, kIsTargetBuild ? 2U : 16U);
-  // Set inline filter values.
-  compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits);
-  image_classes_.clear();
-  if (!extra_dex.empty()) {
-    helper.extra_dex_files = OpenTestDexFiles(extra_dex.c_str());
-  }
-  helper.Compile(compiler_driver_.get(), storage_mode);
-  if (image_classes.begin() != image_classes.end()) {
-    // Make sure the class got initialized.
-    ScopedObjectAccess soa(Thread::Current());
-    ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-    for (const std::string& image_class : image_classes) {
-      mirror::Class* klass = class_linker->FindSystemClass(Thread::Current(), image_class.c_str());
-      EXPECT_TRUE(klass != nullptr);
-      EXPECT_TRUE(klass->IsInitialized());
-    }
-  }
-}
-
-inline void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
-  CompilationHelper helper;
-  Compile(storage_mode, /*out*/ helper);
-  std::vector<uint64_t> image_file_sizes;
-  for (ScratchFile& image_file : helper.image_files) {
-    std::unique_ptr<File> file(OS::OpenFileForReading(image_file.GetFilename().c_str()));
-    ASSERT_TRUE(file.get() != nullptr);
-    ImageHeader image_header;
-    ASSERT_EQ(file->ReadFully(&image_header, sizeof(image_header)), true);
-    ASSERT_TRUE(image_header.IsValid());
-    const auto& bitmap_section = image_header.GetImageBitmapSection();
-    ASSERT_GE(bitmap_section.Offset(), sizeof(image_header));
-    ASSERT_NE(0U, bitmap_section.Size());
-
-    gc::Heap* heap = Runtime::Current()->GetHeap();
-    ASSERT_TRUE(heap->HaveContinuousSpaces());
-    gc::space::ContinuousSpace* space = heap->GetNonMovingSpace();
-    ASSERT_FALSE(space->IsImageSpace());
-    ASSERT_TRUE(space != nullptr);
-    ASSERT_TRUE(space->IsMallocSpace());
-    image_file_sizes.push_back(file->GetLength());
-  }
-
-  ASSERT_TRUE(compiler_driver_->GetImageClasses() != nullptr);
-  std::unordered_set<std::string> image_classes(*compiler_driver_->GetImageClasses());
-
-  // Need to delete the compiler since it has worker threads which are attached to runtime.
-  compiler_driver_.reset();
-
-  // Tear down old runtime before making a new one, clearing out misc state.
-
-  // Remove the reservation of the memory for use to load the image.
-  // Need to do this before we reset the runtime.
-  UnreserveImageSpace();
-
-  helper.extra_dex_files.clear();
-  runtime_.reset();
-  java_lang_dex_file_ = nullptr;
-
-  MemMap::Init();
-
-  RuntimeOptions options;
-  std::string image("-Ximage:");
-  image.append(helper.image_locations[0].GetFilename());
-  options.push_back(std::make_pair(image.c_str(), static_cast<void*>(nullptr)));
-  // By default the compiler this creates will not include patch information.
-  options.push_back(std::make_pair("-Xnorelocate", nullptr));
-
-  if (!Runtime::Create(options, false)) {
-    LOG(FATAL) << "Failed to create runtime";
-    return;
-  }
-  runtime_.reset(Runtime::Current());
-  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
-  // give it away now and then switch to a more managable ScopedObjectAccess.
-  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
-  ScopedObjectAccess soa(Thread::Current());
-  ASSERT_TRUE(runtime_.get() != nullptr);
-  class_linker_ = runtime_->GetClassLinker();
-
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  ASSERT_TRUE(heap->HasBootImageSpace());
-  ASSERT_TRUE(heap->GetNonMovingSpace()->IsMallocSpace());
-
-  // We loaded the runtime with an explicit image, so it must exist.
-  ASSERT_EQ(heap->GetBootImageSpaces().size(), image_file_sizes.size());
-  for (size_t i = 0; i < helper.dex_file_locations.size(); ++i) {
-    std::unique_ptr<const DexFile> dex(
-        LoadExpectSingleDexFile(helper.dex_file_locations[i].c_str()));
-    ASSERT_TRUE(dex != nullptr);
-    uint64_t image_file_size = image_file_sizes[i];
-    gc::space::ImageSpace* image_space = heap->GetBootImageSpaces()[i];
-    ASSERT_TRUE(image_space != nullptr);
-    if (storage_mode == ImageHeader::kStorageModeUncompressed) {
-      // Uncompressed, image should be smaller than file.
-      ASSERT_LE(image_space->GetImageHeader().GetImageSize(), image_file_size);
-    } else if (image_file_size > 16 * KB) {
-      // Compressed, file should be smaller than image. Not really valid for small images.
-      ASSERT_LE(image_file_size, image_space->GetImageHeader().GetImageSize());
-    }
-
-    image_space->VerifyImageAllocations();
-    uint8_t* image_begin = image_space->Begin();
-    uint8_t* image_end = image_space->End();
-    if (i == 0) {
-      // This check is only valid for image 0.
-      CHECK_EQ(kRequestedImageBase, reinterpret_cast<uintptr_t>(image_begin));
-    }
-    for (size_t j = 0; j < dex->NumClassDefs(); ++j) {
-      const DexFile::ClassDef& class_def = dex->GetClassDef(j);
-      const char* descriptor = dex->GetClassDescriptor(class_def);
-      mirror::Class* klass = class_linker_->FindSystemClass(soa.Self(), descriptor);
-      EXPECT_TRUE(klass != nullptr) << descriptor;
-      if (image_classes.find(descriptor) == image_classes.end()) {
-        EXPECT_TRUE(reinterpret_cast<uint8_t*>(klass) >= image_end ||
-                    reinterpret_cast<uint8_t*>(klass) < image_begin) << descriptor;
-      } else {
-        // Image classes should be located inside the image.
-        EXPECT_LT(image_begin, reinterpret_cast<uint8_t*>(klass)) << descriptor;
-        EXPECT_LT(reinterpret_cast<uint8_t*>(klass), image_end) << descriptor;
-      }
-      EXPECT_TRUE(Monitor::IsValidLockWord(klass->GetLockWord(false)));
-    }
-  }
-}
-
-
-}  // namespace art
-
-#endif  // ART_COMPILER_IMAGE_TEST_H_
diff --git a/compiler/image_write_read_test.cc b/compiler/image_write_read_test.cc
deleted file mode 100644
index 32c0b06..0000000
--- a/compiler/image_write_read_test.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2011 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 "image_test.h"
-
-namespace art {
-
-TEST_F(ImageTest, WriteReadUncompressed) {
-  TestWriteRead(ImageHeader::kStorageModeUncompressed);
-}
-
-TEST_F(ImageTest, WriteReadLZ4) {
-  TestWriteRead(ImageHeader::kStorageModeLZ4);
-}
-
-TEST_F(ImageTest, WriteReadLZ4HC) {
-  TestWriteRead(ImageHeader::kStorageModeLZ4HC);
-}
-
-}  // namespace art
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
deleted file mode 100644
index 4ffe238..0000000
--- a/compiler/image_writer.cc
+++ /dev/null
@@ -1,2839 +0,0 @@
-/*
- * Copyright (C) 2011 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 "image_writer.h"
-
-#include <lz4.h>
-#include <lz4hc.h>
-#include <sys/stat.h>
-
-#include <memory>
-#include <numeric>
-#include <unordered_set>
-#include <vector>
-
-#include "art_field-inl.h"
-#include "art_method-inl.h"
-#include "base/callee_save_type.h"
-#include "base/enums.h"
-#include "base/logging.h"
-#include "base/unix_file/fd_file.h"
-#include "class_linker-inl.h"
-#include "compiled_method.h"
-#include "dex_file-inl.h"
-#include "dex_file_types.h"
-#include "driver/compiler_driver.h"
-#include "elf_file.h"
-#include "elf_utils.h"
-#include "elf_writer.h"
-#include "gc/accounting/card_table-inl.h"
-#include "gc/accounting/heap_bitmap.h"
-#include "gc/accounting/space_bitmap-inl.h"
-#include "gc/collector/concurrent_copying.h"
-#include "gc/heap-visit-objects-inl.h"
-#include "gc/heap.h"
-#include "gc/space/large_object_space.h"
-#include "gc/space/space-inl.h"
-#include "gc/verification.h"
-#include "globals.h"
-#include "handle_scope-inl.h"
-#include "image.h"
-#include "imt_conflict_table.h"
-#include "jni_internal.h"
-#include "linear_alloc.h"
-#include "lock_word.h"
-#include "mirror/array-inl.h"
-#include "mirror/class-inl.h"
-#include "mirror/class_ext.h"
-#include "mirror/class_loader.h"
-#include "mirror/dex_cache-inl.h"
-#include "mirror/dex_cache.h"
-#include "mirror/executable.h"
-#include "mirror/method.h"
-#include "mirror/object-inl.h"
-#include "mirror/object-refvisitor-inl.h"
-#include "mirror/object_array-inl.h"
-#include "mirror/string-inl.h"
-#include "oat.h"
-#include "oat_file.h"
-#include "oat_file_manager.h"
-#include "runtime.h"
-#include "scoped_thread_state_change-inl.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
-#include "well_known_classes.h"
-
-using ::art::mirror::Class;
-using ::art::mirror::DexCache;
-using ::art::mirror::Object;
-using ::art::mirror::ObjectArray;
-using ::art::mirror::String;
-
-namespace art {
-
-// Separate objects into multiple bins to optimize dirty memory use.
-static constexpr bool kBinObjects = true;
-
-// Return true if an object is already in an image space.
-bool ImageWriter::IsInBootImage(const void* obj) const {
-  gc::Heap* const heap = Runtime::Current()->GetHeap();
-  if (!compile_app_image_) {
-    DCHECK(heap->GetBootImageSpaces().empty());
-    return false;
-  }
-  for (gc::space::ImageSpace* boot_image_space : heap->GetBootImageSpaces()) {
-    const uint8_t* image_begin = boot_image_space->Begin();
-    // Real image end including ArtMethods and ArtField sections.
-    const uint8_t* image_end = image_begin + boot_image_space->GetImageHeader().GetImageSize();
-    if (image_begin <= obj && obj < image_end) {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool ImageWriter::IsInBootOatFile(const void* ptr) const {
-  gc::Heap* const heap = Runtime::Current()->GetHeap();
-  if (!compile_app_image_) {
-    DCHECK(heap->GetBootImageSpaces().empty());
-    return false;
-  }
-  for (gc::space::ImageSpace* boot_image_space : heap->GetBootImageSpaces()) {
-    const ImageHeader& image_header = boot_image_space->GetImageHeader();
-    if (image_header.GetOatFileBegin() <= ptr && ptr < image_header.GetOatFileEnd()) {
-      return true;
-    }
-  }
-  return false;
-}
-
-static void ClearDexFileCookies() REQUIRES_SHARED(Locks::mutator_lock_) {
-  auto visitor = [](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(obj != nullptr);
-    Class* klass = obj->GetClass();
-    if (klass == WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DexFile)) {
-      ArtField* field = jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
-      // Null out the cookie to enable determinism. b/34090128
-      field->SetObject</*kTransactionActive*/false>(obj, nullptr);
-    }
-  };
-  Runtime::Current()->GetHeap()->VisitObjects(visitor);
-}
-
-bool ImageWriter::PrepareImageAddressSpace() {
-  target_ptr_size_ = InstructionSetPointerSize(compiler_driver_.GetInstructionSet());
-  gc::Heap* const heap = Runtime::Current()->GetHeap();
-  {
-    ScopedObjectAccess soa(Thread::Current());
-    PruneNonImageClasses();  // Remove junk
-    if (compile_app_image_) {
-      // Clear dex file cookies for app images to enable app image determinism. This is required
-      // since the cookie field contains long pointers to DexFiles which are not deterministic.
-      // b/34090128
-      ClearDexFileCookies();
-    } else {
-      // Avoid for app image since this may increase RAM and image size.
-      ComputeLazyFieldsForImageClasses();  // Add useful information
-    }
-  }
-  heap->CollectGarbage(false);  // Remove garbage.
-
-  if (kIsDebugBuild) {
-    ScopedObjectAccess soa(Thread::Current());
-    CheckNonImageClassesRemoved();
-  }
-
-  {
-    ScopedObjectAccess soa(Thread::Current());
-    CalculateNewObjectOffsets();
-  }
-
-  // This needs to happen after CalculateNewObjectOffsets since it relies on intern_table_bytes_ and
-  // bin size sums being calculated.
-  if (!AllocMemory()) {
-    return false;
-  }
-
-  return true;
-}
-
-bool ImageWriter::Write(int image_fd,
-                        const std::vector<const char*>& image_filenames,
-                        const std::vector<const char*>& oat_filenames) {
-  // If image_fd or oat_fd are not kInvalidFd then we may have empty strings in image_filenames or
-  // oat_filenames.
-  CHECK(!image_filenames.empty());
-  if (image_fd != kInvalidFd) {
-    CHECK_EQ(image_filenames.size(), 1u);
-  }
-  CHECK(!oat_filenames.empty());
-  CHECK_EQ(image_filenames.size(), oat_filenames.size());
-
-  {
-    ScopedObjectAccess soa(Thread::Current());
-    for (size_t i = 0; i < oat_filenames.size(); ++i) {
-      CreateHeader(i);
-      CopyAndFixupNativeData(i);
-    }
-  }
-
-  {
-    // TODO: heap validation can't handle these fix up passes.
-    ScopedObjectAccess soa(Thread::Current());
-    Runtime::Current()->GetHeap()->DisableObjectValidation();
-    CopyAndFixupObjects();
-  }
-
-  for (size_t i = 0; i < image_filenames.size(); ++i) {
-    const char* image_filename = image_filenames[i];
-    ImageInfo& image_info = GetImageInfo(i);
-    std::unique_ptr<File> image_file;
-    if (image_fd != kInvalidFd) {
-      if (strlen(image_filename) == 0u) {
-        image_file.reset(new File(image_fd, unix_file::kCheckSafeUsage));
-        // Empty the file in case it already exists.
-        if (image_file != nullptr) {
-          TEMP_FAILURE_RETRY(image_file->SetLength(0));
-          TEMP_FAILURE_RETRY(image_file->Flush());
-        }
-      } else {
-        LOG(ERROR) << "image fd " << image_fd << " name " << image_filename;
-      }
-    } else {
-      image_file.reset(OS::CreateEmptyFile(image_filename));
-    }
-
-    if (image_file == nullptr) {
-      LOG(ERROR) << "Failed to open image file " << image_filename;
-      return false;
-    }
-
-    if (!compile_app_image_ && fchmod(image_file->Fd(), 0644) != 0) {
-      PLOG(ERROR) << "Failed to make image file world readable: " << image_filename;
-      image_file->Erase();
-      return EXIT_FAILURE;
-    }
-
-    std::unique_ptr<char[]> compressed_data;
-    // Image data size excludes the bitmap and the header.
-    ImageHeader* const image_header = reinterpret_cast<ImageHeader*>(image_info.image_->Begin());
-    const size_t image_data_size = image_header->GetImageSize() - sizeof(ImageHeader);
-    char* image_data = reinterpret_cast<char*>(image_info.image_->Begin()) + sizeof(ImageHeader);
-    size_t data_size;
-    const char* image_data_to_write;
-    const uint64_t compress_start_time = NanoTime();
-
-    CHECK_EQ(image_header->storage_mode_, image_storage_mode_);
-    switch (image_storage_mode_) {
-      case ImageHeader::kStorageModeLZ4HC:  // Fall-through.
-      case ImageHeader::kStorageModeLZ4: {
-        const size_t compressed_max_size = LZ4_compressBound(image_data_size);
-        compressed_data.reset(new char[compressed_max_size]);
-        data_size = LZ4_compress_default(
-            reinterpret_cast<char*>(image_info.image_->Begin()) + sizeof(ImageHeader),
-            &compressed_data[0],
-            image_data_size,
-            compressed_max_size);
-
-        break;
-      }
-      /*
-       * Disabled due to image_test64 flakyness. Both use same decompression. b/27560444
-      case ImageHeader::kStorageModeLZ4HC: {
-        // Bound is same as non HC.
-        const size_t compressed_max_size = LZ4_compressBound(image_data_size);
-        compressed_data.reset(new char[compressed_max_size]);
-        data_size = LZ4_compressHC(
-            reinterpret_cast<char*>(image_info.image_->Begin()) + sizeof(ImageHeader),
-            &compressed_data[0],
-            image_data_size);
-        break;
-      }
-      */
-      case ImageHeader::kStorageModeUncompressed: {
-        data_size = image_data_size;
-        image_data_to_write = image_data;
-        break;
-      }
-      default: {
-        LOG(FATAL) << "Unsupported";
-        UNREACHABLE();
-      }
-    }
-
-    if (compressed_data != nullptr) {
-      image_data_to_write = &compressed_data[0];
-      VLOG(compiler) << "Compressed from " << image_data_size << " to " << data_size << " in "
-                     << PrettyDuration(NanoTime() - compress_start_time);
-      if (kIsDebugBuild) {
-        std::unique_ptr<uint8_t[]> temp(new uint8_t[image_data_size]);
-        const size_t decompressed_size = LZ4_decompress_safe(
-            reinterpret_cast<char*>(&compressed_data[0]),
-            reinterpret_cast<char*>(&temp[0]),
-            data_size,
-            image_data_size);
-        CHECK_EQ(decompressed_size, image_data_size);
-        CHECK_EQ(memcmp(image_data, &temp[0], image_data_size), 0) << image_storage_mode_;
-      }
-    }
-
-    // Write out the image + fields + methods.
-    const bool is_compressed = compressed_data != nullptr;
-    if (!image_file->PwriteFully(image_data_to_write, data_size, sizeof(ImageHeader))) {
-      PLOG(ERROR) << "Failed to write image file data " << image_filename;
-      image_file->Erase();
-      return false;
-    }
-
-    // Write out the image bitmap at the page aligned start of the image end, also uncompressed for
-    // convenience.
-    const ImageSection& bitmap_section = image_header->GetImageBitmapSection();
-    // Align up since data size may be unaligned if the image is compressed.
-    size_t bitmap_position_in_file = RoundUp(sizeof(ImageHeader) + data_size, kPageSize);
-    if (!is_compressed) {
-      CHECK_EQ(bitmap_position_in_file, bitmap_section.Offset());
-    }
-    if (!image_file->PwriteFully(reinterpret_cast<char*>(image_info.image_bitmap_->Begin()),
-                                 bitmap_section.Size(),
-                                 bitmap_position_in_file)) {
-      PLOG(ERROR) << "Failed to write image file " << image_filename;
-      image_file->Erase();
-      return false;
-    }
-
-    int err = image_file->Flush();
-    if (err < 0) {
-      PLOG(ERROR) << "Failed to flush image file " << image_filename << " with result " << err;
-      image_file->Erase();
-      return false;
-    }
-
-    // Write header last in case the compiler gets killed in the middle of image writing.
-    // We do not want to have a corrupted image with a valid header.
-    // The header is uncompressed since it contains whether the image is compressed or not.
-    image_header->data_size_ = data_size;
-    if (!image_file->PwriteFully(reinterpret_cast<char*>(image_info.image_->Begin()),
-                                 sizeof(ImageHeader),
-                                 0)) {
-      PLOG(ERROR) << "Failed to write image file header " << image_filename;
-      image_file->Erase();
-      return false;
-    }
-
-    CHECK_EQ(bitmap_position_in_file + bitmap_section.Size(),
-             static_cast<size_t>(image_file->GetLength()));
-    if (image_file->FlushCloseOrErase() != 0) {
-      PLOG(ERROR) << "Failed to flush and close image file " << image_filename;
-      return false;
-    }
-  }
-  return true;
-}
-
-void ImageWriter::SetImageOffset(mirror::Object* object, size_t offset) {
-  DCHECK(object != nullptr);
-  DCHECK_NE(offset, 0U);
-
-  // The object is already deflated from when we set the bin slot. Just overwrite the lock word.
-  object->SetLockWord(LockWord::FromForwardingAddress(offset), false);
-  DCHECK_EQ(object->GetLockWord(false).ReadBarrierState(), 0u);
-  DCHECK(IsImageOffsetAssigned(object));
-}
-
-void ImageWriter::UpdateImageOffset(mirror::Object* obj, uintptr_t offset) {
-  DCHECK(IsImageOffsetAssigned(obj)) << obj << " " << offset;
-  obj->SetLockWord(LockWord::FromForwardingAddress(offset), false);
-  DCHECK_EQ(obj->GetLockWord(false).ReadBarrierState(), 0u);
-}
-
-void ImageWriter::AssignImageOffset(mirror::Object* object, ImageWriter::BinSlot bin_slot) {
-  DCHECK(object != nullptr);
-  DCHECK_NE(image_objects_offset_begin_, 0u);
-
-  size_t oat_index = GetOatIndex(object);
-  ImageInfo& image_info = GetImageInfo(oat_index);
-  size_t bin_slot_offset = image_info.bin_slot_offsets_[bin_slot.GetBin()];
-  size_t new_offset = bin_slot_offset + bin_slot.GetIndex();
-  DCHECK_ALIGNED(new_offset, kObjectAlignment);
-
-  SetImageOffset(object, new_offset);
-  DCHECK_LT(new_offset, image_info.image_end_);
-}
-
-bool ImageWriter::IsImageOffsetAssigned(mirror::Object* object) const {
-  // Will also return true if the bin slot was assigned since we are reusing the lock word.
-  DCHECK(object != nullptr);
-  return object->GetLockWord(false).GetState() == LockWord::kForwardingAddress;
-}
-
-size_t ImageWriter::GetImageOffset(mirror::Object* object) const {
-  DCHECK(object != nullptr);
-  DCHECK(IsImageOffsetAssigned(object));
-  LockWord lock_word = object->GetLockWord(false);
-  size_t offset = lock_word.ForwardingAddress();
-  size_t oat_index = GetOatIndex(object);
-  const ImageInfo& image_info = GetImageInfo(oat_index);
-  DCHECK_LT(offset, image_info.image_end_);
-  return offset;
-}
-
-void ImageWriter::SetImageBinSlot(mirror::Object* object, BinSlot bin_slot) {
-  DCHECK(object != nullptr);
-  DCHECK(!IsImageOffsetAssigned(object));
-  DCHECK(!IsImageBinSlotAssigned(object));
-
-  // Before we stomp over the lock word, save the hash code for later.
-  LockWord lw(object->GetLockWord(false));
-  switch (lw.GetState()) {
-    case LockWord::kFatLocked:
-      FALLTHROUGH_INTENDED;
-    case LockWord::kThinLocked: {
-      std::ostringstream oss;
-      bool thin = (lw.GetState() == LockWord::kThinLocked);
-      oss << (thin ? "Thin" : "Fat")
-          << " locked object " << object << "(" << object->PrettyTypeOf()
-          << ") found during object copy";
-      if (thin) {
-        oss << ". Lock owner:" << lw.ThinLockOwner();
-      }
-      LOG(FATAL) << oss.str();
-      break;
-    }
-    case LockWord::kUnlocked:
-      // No hash, don't need to save it.
-      break;
-    case LockWord::kHashCode:
-      DCHECK(saved_hashcode_map_.find(object) == saved_hashcode_map_.end());
-      saved_hashcode_map_.emplace(object, lw.GetHashCode());
-      break;
-    default:
-      LOG(FATAL) << "Unreachable.";
-      UNREACHABLE();
-  }
-  object->SetLockWord(LockWord::FromForwardingAddress(bin_slot.Uint32Value()), false);
-  DCHECK_EQ(object->GetLockWord(false).ReadBarrierState(), 0u);
-  DCHECK(IsImageBinSlotAssigned(object));
-}
-
-void ImageWriter::PrepareDexCacheArraySlots() {
-  // Prepare dex cache array starts based on the ordering specified in the CompilerDriver.
-  // Set the slot size early to avoid DCHECK() failures in IsImageBinSlotAssigned()
-  // when AssignImageBinSlot() assigns their indexes out or order.
-  for (const DexFile* dex_file : compiler_driver_.GetDexFilesForOatFile()) {
-    auto it = dex_file_oat_index_map_.find(dex_file);
-    DCHECK(it != dex_file_oat_index_map_.end()) << dex_file->GetLocation();
-    ImageInfo& image_info = GetImageInfo(it->second);
-    image_info.dex_cache_array_starts_.Put(dex_file, image_info.bin_slot_sizes_[kBinDexCacheArray]);
-    DexCacheArraysLayout layout(target_ptr_size_, dex_file);
-    image_info.bin_slot_sizes_[kBinDexCacheArray] += layout.Size();
-  }
-
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Thread* const self = Thread::Current();
-  ReaderMutexLock mu(self, *Locks::dex_lock_);
-  for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
-    ObjPtr<mirror::DexCache> dex_cache =
-        ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
-    if (dex_cache == nullptr || IsInBootImage(dex_cache.Ptr())) {
-      continue;
-    }
-    const DexFile* dex_file = dex_cache->GetDexFile();
-    CHECK(dex_file_oat_index_map_.find(dex_file) != dex_file_oat_index_map_.end())
-        << "Dex cache should have been pruned " << dex_file->GetLocation()
-        << "; possibly in class path";
-    DexCacheArraysLayout layout(target_ptr_size_, dex_file);
-    DCHECK(layout.Valid());
-    size_t oat_index = GetOatIndexForDexCache(dex_cache);
-    ImageInfo& image_info = GetImageInfo(oat_index);
-    uint32_t start = image_info.dex_cache_array_starts_.Get(dex_file);
-    DCHECK_EQ(dex_file->NumTypeIds() != 0u, dex_cache->GetResolvedTypes() != nullptr);
-    AddDexCacheArrayRelocation(dex_cache->GetResolvedTypes(),
-                               start + layout.TypesOffset(),
-                               dex_cache);
-    DCHECK_EQ(dex_file->NumMethodIds() != 0u, dex_cache->GetResolvedMethods() != nullptr);
-    AddDexCacheArrayRelocation(dex_cache->GetResolvedMethods(),
-                               start + layout.MethodsOffset(),
-                               dex_cache);
-    DCHECK_EQ(dex_file->NumFieldIds() != 0u, dex_cache->GetResolvedFields() != nullptr);
-    AddDexCacheArrayRelocation(dex_cache->GetResolvedFields(),
-                               start + layout.FieldsOffset(),
-                               dex_cache);
-    DCHECK_EQ(dex_file->NumStringIds() != 0u, dex_cache->GetStrings() != nullptr);
-    AddDexCacheArrayRelocation(dex_cache->GetStrings(), start + layout.StringsOffset(), dex_cache);
-
-    if (dex_cache->GetResolvedMethodTypes() != nullptr) {
-      AddDexCacheArrayRelocation(dex_cache->GetResolvedMethodTypes(),
-                                 start + layout.MethodTypesOffset(),
-                                 dex_cache);
-    }
-    if (dex_cache->GetResolvedCallSites() != nullptr) {
-      AddDexCacheArrayRelocation(dex_cache->GetResolvedCallSites(),
-                                 start + layout.CallSitesOffset(),
-                                 dex_cache);
-    }
-  }
-}
-
-void ImageWriter::AddDexCacheArrayRelocation(void* array,
-                                             size_t offset,
-                                             ObjPtr<mirror::DexCache> dex_cache) {
-  if (array != nullptr) {
-    DCHECK(!IsInBootImage(array));
-    size_t oat_index = GetOatIndexForDexCache(dex_cache);
-    native_object_relocations_.emplace(array,
-        NativeObjectRelocation { oat_index, offset, kNativeObjectRelocationTypeDexCacheArray });
-  }
-}
-
-void ImageWriter::AddMethodPointerArray(mirror::PointerArray* arr) {
-  DCHECK(arr != nullptr);
-  if (kIsDebugBuild) {
-    for (size_t i = 0, len = arr->GetLength(); i < len; i++) {
-      ArtMethod* method = arr->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_);
-      if (method != nullptr && !method->IsRuntimeMethod()) {
-        mirror::Class* klass = method->GetDeclaringClass();
-        CHECK(klass == nullptr || KeepClass(klass))
-            << Class::PrettyClass(klass) << " should be a kept class";
-      }
-    }
-  }
-  // kBinArtMethodClean picked arbitrarily, just required to differentiate between ArtFields and
-  // ArtMethods.
-  pointer_arrays_.emplace(arr, kBinArtMethodClean);
-}
-
-void ImageWriter::AssignImageBinSlot(mirror::Object* object, size_t oat_index) {
-  DCHECK(object != nullptr);
-  size_t object_size = object->SizeOf();
-
-  // The magic happens here. We segregate objects into different bins based
-  // on how likely they are to get dirty at runtime.
-  //
-  // Likely-to-dirty objects get packed together into the same bin so that
-  // at runtime their page dirtiness ratio (how many dirty objects a page has) is
-  // maximized.
-  //
-  // This means more pages will stay either clean or shared dirty (with zygote) and
-  // the app will use less of its own (private) memory.
-  Bin bin = kBinRegular;
-  size_t current_offset = 0u;
-
-  if (kBinObjects) {
-    //
-    // Changing the bin of an object is purely a memory-use tuning.
-    // It has no change on runtime correctness.
-    //
-    // Memory analysis has determined that the following types of objects get dirtied
-    // the most:
-    //
-    // * Dex cache arrays are stored in a special bin. The arrays for each dex cache have
-    //   a fixed layout which helps improve generated code (using PC-relative addressing),
-    //   so we pre-calculate their offsets separately in PrepareDexCacheArraySlots().
-    //   Since these arrays are huge, most pages do not overlap other objects and it's not
-    //   really important where they are for the clean/dirty separation. Due to their
-    //   special PC-relative addressing, we arbitrarily keep them at the end.
-    // * Class'es which are verified [their clinit runs only at runtime]
-    //   - classes in general [because their static fields get overwritten]
-    //   - initialized classes with all-final statics are unlikely to be ever dirty,
-    //     so bin them separately
-    // * Art Methods that are:
-    //   - native [their native entry point is not looked up until runtime]
-    //   - have declaring classes that aren't initialized
-    //            [their interpreter/quick entry points are trampolines until the class
-    //             becomes initialized]
-    //
-    // We also assume the following objects get dirtied either never or extremely rarely:
-    //  * Strings (they are immutable)
-    //  * Art methods that aren't native and have initialized declared classes
-    //
-    // We assume that "regular" bin objects are highly unlikely to become dirtied,
-    // so packing them together will not result in a noticeably tighter dirty-to-clean ratio.
-    //
-    if (object->IsClass()) {
-      bin = kBinClassVerified;
-      mirror::Class* klass = object->AsClass();
-
-      // Add non-embedded vtable to the pointer array table if there is one.
-      auto* vtable = klass->GetVTable();
-      if (vtable != nullptr) {
-        AddMethodPointerArray(vtable);
-      }
-      auto* iftable = klass->GetIfTable();
-      if (iftable != nullptr) {
-        for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
-          if (iftable->GetMethodArrayCount(i) > 0) {
-            AddMethodPointerArray(iftable->GetMethodArray(i));
-          }
-        }
-      }
-
-      // Move known dirty objects into their own sections. This includes:
-      //   - classes with dirty static fields.
-      if (dirty_image_objects_ != nullptr &&
-          dirty_image_objects_->find(klass->PrettyDescriptor()) != dirty_image_objects_->end()) {
-        bin = kBinKnownDirty;
-      } else if (klass->GetStatus() == Class::kStatusInitialized) {
-        bin = kBinClassInitialized;
-
-        // If the class's static fields are all final, put it into a separate bin
-        // since it's very likely it will stay clean.
-        uint32_t num_static_fields = klass->NumStaticFields();
-        if (num_static_fields == 0) {
-          bin = kBinClassInitializedFinalStatics;
-        } else {
-          // Maybe all the statics are final?
-          bool all_final = true;
-          for (uint32_t i = 0; i < num_static_fields; ++i) {
-            ArtField* field = klass->GetStaticField(i);
-            if (!field->IsFinal()) {
-              all_final = false;
-              break;
-            }
-          }
-
-          if (all_final) {
-            bin = kBinClassInitializedFinalStatics;
-          }
-        }
-      }
-    } else if (object->GetClass<kVerifyNone>()->IsStringClass()) {
-      bin = kBinString;  // Strings are almost always immutable (except for object header).
-    } else if (object->GetClass<kVerifyNone>() ==
-        Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kJavaLangObject)) {
-      // Instance of java lang object, probably a lock object. This means it will be dirty when we
-      // synchronize on it.
-      bin = kBinMiscDirty;
-    } else if (object->IsDexCache()) {
-      // Dex file field becomes dirty when the image is loaded.
-      bin = kBinMiscDirty;
-    }
-    // else bin = kBinRegular
-  }
-
-  // Assign the oat index too.
-  DCHECK(oat_index_map_.find(object) == oat_index_map_.end());
-  oat_index_map_.emplace(object, oat_index);
-
-  ImageInfo& image_info = GetImageInfo(oat_index);
-
-  size_t offset_delta = RoundUp(object_size, kObjectAlignment);  // 64-bit alignment
-  current_offset = image_info.bin_slot_sizes_[bin];  // How many bytes the current bin is at (aligned).
-  // Move the current bin size up to accommodate the object we just assigned a bin slot.
-  image_info.bin_slot_sizes_[bin] += offset_delta;
-
-  BinSlot new_bin_slot(bin, current_offset);
-  SetImageBinSlot(object, new_bin_slot);
-
-  ++image_info.bin_slot_count_[bin];
-
-  // Grow the image closer to the end by the object we just assigned.
-  image_info.image_end_ += offset_delta;
-}
-
-bool ImageWriter::WillMethodBeDirty(ArtMethod* m) const {
-  if (m->IsNative()) {
-    return true;
-  }
-  mirror::Class* declaring_class = m->GetDeclaringClass();
-  // Initialized is highly unlikely to dirty since there's no entry points to mutate.
-  return declaring_class == nullptr || declaring_class->GetStatus() != Class::kStatusInitialized;
-}
-
-bool ImageWriter::IsImageBinSlotAssigned(mirror::Object* object) const {
-  DCHECK(object != nullptr);
-
-  // We always stash the bin slot into a lockword, in the 'forwarding address' state.
-  // If it's in some other state, then we haven't yet assigned an image bin slot.
-  if (object->GetLockWord(false).GetState() != LockWord::kForwardingAddress) {
-    return false;
-  } else if (kIsDebugBuild) {
-    LockWord lock_word = object->GetLockWord(false);
-    size_t offset = lock_word.ForwardingAddress();
-    BinSlot bin_slot(offset);
-    size_t oat_index = GetOatIndex(object);
-    const ImageInfo& image_info = GetImageInfo(oat_index);
-    DCHECK_LT(bin_slot.GetIndex(), image_info.bin_slot_sizes_[bin_slot.GetBin()])
-        << "bin slot offset should not exceed the size of that bin";
-  }
-  return true;
-}
-
-ImageWriter::BinSlot ImageWriter::GetImageBinSlot(mirror::Object* object) const {
-  DCHECK(object != nullptr);
-  DCHECK(IsImageBinSlotAssigned(object));
-
-  LockWord lock_word = object->GetLockWord(false);
-  size_t offset = lock_word.ForwardingAddress();  // TODO: ForwardingAddress should be uint32_t
-  DCHECK_LE(offset, std::numeric_limits<uint32_t>::max());
-
-  BinSlot bin_slot(static_cast<uint32_t>(offset));
-  size_t oat_index = GetOatIndex(object);
-  const ImageInfo& image_info = GetImageInfo(oat_index);
-  DCHECK_LT(bin_slot.GetIndex(), image_info.bin_slot_sizes_[bin_slot.GetBin()]);
-
-  return bin_slot;
-}
-
-bool ImageWriter::AllocMemory() {
-  for (ImageInfo& image_info : image_infos_) {
-    ImageSection unused_sections[ImageHeader::kSectionCount];
-    const size_t length = RoundUp(
-        image_info.CreateImageSections(unused_sections, compile_app_image_), kPageSize);
-
-    std::string error_msg;
-    image_info.image_.reset(MemMap::MapAnonymous("image writer image",
-                                                 nullptr,
-                                                 length,
-                                                 PROT_READ | PROT_WRITE,
-                                                 false,
-                                                 false,
-                                                 &error_msg));
-    if (UNLIKELY(image_info.image_.get() == nullptr)) {
-      LOG(ERROR) << "Failed to allocate memory for image file generation: " << error_msg;
-      return false;
-    }
-
-    // Create the image bitmap, only needs to cover mirror object section which is up to image_end_.
-    CHECK_LE(image_info.image_end_, length);
-    image_info.image_bitmap_.reset(gc::accounting::ContinuousSpaceBitmap::Create(
-        "image bitmap", image_info.image_->Begin(), RoundUp(image_info.image_end_, kPageSize)));
-    if (image_info.image_bitmap_.get() == nullptr) {
-      LOG(ERROR) << "Failed to allocate memory for image bitmap";
-      return false;
-    }
-  }
-  return true;
-}
-
-class ImageWriter::ComputeLazyFieldsForClassesVisitor : public ClassVisitor {
- public:
-  bool operator()(ObjPtr<Class> c) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
-    StackHandleScope<1> hs(Thread::Current());
-    mirror::Class::ComputeName(hs.NewHandle(c));
-    return true;
-  }
-};
-
-void ImageWriter::ComputeLazyFieldsForImageClasses() {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  ComputeLazyFieldsForClassesVisitor visitor;
-  class_linker->VisitClassesWithoutClassesLock(&visitor);
-}
-
-static bool IsBootClassLoaderClass(ObjPtr<mirror::Class> klass)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  return klass->GetClassLoader() == nullptr;
-}
-
-bool ImageWriter::IsBootClassLoaderNonImageClass(mirror::Class* klass) {
-  return IsBootClassLoaderClass(klass) && !IsInBootImage(klass);
-}
-
-// This visitor follows the references of an instance, recursively then prune this class
-// if a type of any field is pruned.
-class ImageWriter::PruneObjectReferenceVisitor {
- public:
-  PruneObjectReferenceVisitor(ImageWriter* image_writer,
-                        bool* early_exit,
-                        std::unordered_set<mirror::Object*>* visited,
-                        bool* result)
-      : image_writer_(image_writer), early_exit_(early_exit), visited_(visited), result_(result) {}
-
-  ALWAYS_INLINE void VisitRootIfNonNull(
-      mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const
-      REQUIRES_SHARED(Locks::mutator_lock_) { }
-
-  ALWAYS_INLINE void VisitRoot(
-      mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const
-      REQUIRES_SHARED(Locks::mutator_lock_) { }
-
-  ALWAYS_INLINE void operator() (ObjPtr<mirror::Object> obj,
-                                 MemberOffset offset,
-                                 bool is_static ATTRIBUTE_UNUSED) const
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    mirror::Object* ref =
-        obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset);
-    if (ref == nullptr || visited_->find(ref) != visited_->end()) {
-      return;
-    }
-
-    ObjPtr<mirror::Class> klass = ref->IsClass() ? ref->AsClass() : ref->GetClass();
-    if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
-      // Prune all classes using reflection because the content they held will not be fixup.
-      *result_ = true;
-    }
-
-    if (ref->IsClass()) {
-      *result_ = *result_ ||
-          image_writer_->PruneAppImageClassInternal(ref->AsClass(), early_exit_, visited_);
-    } else {
-      // Record the object visited in case of circular reference.
-      visited_->emplace(ref);
-      *result_ = *result_ ||
-          image_writer_->PruneAppImageClassInternal(klass, early_exit_, visited_);
-      ref->VisitReferences(*this, *this);
-      // Clean up before exit for next call of this function.
-      visited_->erase(ref);
-    }
-  }
-
-  ALWAYS_INLINE void operator() (ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
-                                 ObjPtr<mirror::Reference> ref) const
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    operator()(ref, mirror::Reference::ReferentOffset(), /* is_static */ false);
-  }
-
-  ALWAYS_INLINE bool GetResult() const {
-    return result_;
-  }
-
- private:
-  ImageWriter* image_writer_;
-  bool* early_exit_;
-  std::unordered_set<mirror::Object*>* visited_;
-  bool* const result_;
-};
-
-
-bool ImageWriter::PruneAppImageClass(ObjPtr<mirror::Class> klass) {
-  bool early_exit = false;
-  std::unordered_set<mirror::Object*> visited;
-  return PruneAppImageClassInternal(klass, &early_exit, &visited);
-}
-
-bool ImageWriter::PruneAppImageClassInternal(
-    ObjPtr<mirror::Class> klass,
-    bool* early_exit,
-    std::unordered_set<mirror::Object*>* visited) {
-  DCHECK(early_exit != nullptr);
-  DCHECK(visited != nullptr);
-  DCHECK(compile_app_image_);
-  if (klass == nullptr || IsInBootImage(klass.Ptr())) {
-    return false;
-  }
-  auto found = prune_class_memo_.find(klass.Ptr());
-  if (found != prune_class_memo_.end()) {
-    // Already computed, return the found value.
-    return found->second;
-  }
-  // Circular dependencies, return false but do not store the result in the memoization table.
-  if (visited->find(klass.Ptr()) != visited->end()) {
-    *early_exit = true;
-    return false;
-  }
-  visited->emplace(klass.Ptr());
-  bool result = IsBootClassLoaderClass(klass);
-  std::string temp;
-  // Prune if not an image class, this handles any broken sets of image classes such as having a
-  // class in the set but not it's superclass.
-  result = result || !compiler_driver_.IsImageClass(klass->GetDescriptor(&temp));
-  bool my_early_exit = false;  // Only for ourselves, ignore caller.
-  // Remove classes that failed to verify since we don't want to have java.lang.VerifyError in the
-  // app image.
-  if (klass->IsErroneous()) {
-    result = true;
-  } else {
-    ObjPtr<mirror::ClassExt> ext(klass->GetExtData());
-    CHECK(ext.IsNull() || ext->GetVerifyError() == nullptr) << klass->PrettyClass();
-  }
-  if (!result) {
-    // Check interfaces since these wont be visited through VisitReferences.)
-    mirror::IfTable* if_table = klass->GetIfTable();
-    for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
-      result = result || PruneAppImageClassInternal(if_table->GetInterface(i),
-                                                    &my_early_exit,
-                                                    visited);
-    }
-  }
-  if (klass->IsObjectArrayClass()) {
-    result = result || PruneAppImageClassInternal(klass->GetComponentType(),
-                                                  &my_early_exit,
-                                                  visited);
-  }
-  // Check static fields and their classes.
-  if (klass->IsResolved() && klass->NumReferenceStaticFields() != 0) {
-    size_t num_static_fields = klass->NumReferenceStaticFields();
-    // Presumably GC can happen when we are cross compiling, it should not cause performance
-    // problems to do pointer size logic.
-    MemberOffset field_offset = klass->GetFirstReferenceStaticFieldOffset(
-        Runtime::Current()->GetClassLinker()->GetImagePointerSize());
-    for (size_t i = 0u; i < num_static_fields; ++i) {
-      mirror::Object* ref = klass->GetFieldObject<mirror::Object>(field_offset);
-      if (ref != nullptr) {
-        if (ref->IsClass()) {
-          result = result || PruneAppImageClassInternal(ref->AsClass(),
-                                                        &my_early_exit,
-                                                        visited);
-        } else {
-          mirror::Class* type = ref->GetClass();
-          result = result || PruneAppImageClassInternal(type,
-                                                        &my_early_exit,
-                                                        visited);
-          if (!result) {
-            // For non-class case, also go through all the types mentioned by it's fields'
-            // references recursively to decide whether to keep this class.
-            bool tmp = false;
-            PruneObjectReferenceVisitor visitor(this, &my_early_exit, visited, &tmp);
-            ref->VisitReferences(visitor, visitor);
-            result = result || tmp;
-          }
-        }
-      }
-      field_offset = MemberOffset(field_offset.Uint32Value() +
-                                  sizeof(mirror::HeapReference<mirror::Object>));
-    }
-  }
-  result = result || PruneAppImageClassInternal(klass->GetSuperClass(),
-                                                &my_early_exit,
-                                                visited);
-  // Remove the class if the dex file is not in the set of dex files. This happens for classes that
-  // are from uses-library if there is no profile. b/30688277
-  mirror::DexCache* dex_cache = klass->GetDexCache();
-  if (dex_cache != nullptr) {
-    result = result ||
-        dex_file_oat_index_map_.find(dex_cache->GetDexFile()) == dex_file_oat_index_map_.end();
-  }
-  // Erase the element we stored earlier since we are exiting the function.
-  auto it = visited->find(klass.Ptr());
-  DCHECK(it != visited->end());
-  visited->erase(it);
-  // Only store result if it is true or none of the calls early exited due to circular
-  // dependencies. If visited is empty then we are the root caller, in this case the cycle was in
-  // a child call and we can remember the result.
-  if (result == true || !my_early_exit || visited->empty()) {
-    prune_class_memo_[klass.Ptr()] = result;
-  }
-  *early_exit |= my_early_exit;
-  return result;
-}
-
-bool ImageWriter::KeepClass(ObjPtr<mirror::Class> klass) {
-  if (klass == nullptr) {
-    return false;
-  }
-  if (compile_app_image_ && Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) {
-    // Already in boot image, return true.
-    return true;
-  }
-  std::string temp;
-  if (!compiler_driver_.IsImageClass(klass->GetDescriptor(&temp))) {
-    return false;
-  }
-  if (compile_app_image_) {
-    // For app images, we need to prune boot loader classes that are not in the boot image since
-    // these may have already been loaded when the app image is loaded.
-    // Keep classes in the boot image space since we don't want to re-resolve these.
-    return !PruneAppImageClass(klass);
-  }
-  return true;
-}
-
-class ImageWriter::PruneClassesVisitor : public ClassVisitor {
- public:
-  PruneClassesVisitor(ImageWriter* image_writer, ObjPtr<mirror::ClassLoader> class_loader)
-      : image_writer_(image_writer),
-        class_loader_(class_loader),
-        classes_to_prune_(),
-        defined_class_count_(0u) { }
-
-  bool operator()(ObjPtr<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (!image_writer_->KeepClass(klass.Ptr())) {
-      classes_to_prune_.insert(klass.Ptr());
-      if (klass->GetClassLoader() == class_loader_) {
-        ++defined_class_count_;
-      }
-    }
-    return true;
-  }
-
-  size_t Prune() REQUIRES_SHARED(Locks::mutator_lock_) {
-    ClassTable* class_table =
-        Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader_);
-    for (mirror::Class* klass : classes_to_prune_) {
-      std::string storage;
-      const char* descriptor = klass->GetDescriptor(&storage);
-      bool result = class_table->Remove(descriptor);
-      DCHECK(result);
-      DCHECK(!class_table->Remove(descriptor)) << descriptor;
-    }
-    return defined_class_count_;
-  }
-
- private:
-  ImageWriter* const image_writer_;
-  const ObjPtr<mirror::ClassLoader> class_loader_;
-  std::unordered_set<mirror::Class*> classes_to_prune_;
-  size_t defined_class_count_;
-};
-
-class ImageWriter::PruneClassLoaderClassesVisitor : public ClassLoaderVisitor {
- public:
-  explicit PruneClassLoaderClassesVisitor(ImageWriter* image_writer)
-      : image_writer_(image_writer), removed_class_count_(0) {}
-
-  virtual void Visit(ObjPtr<mirror::ClassLoader> class_loader) OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    PruneClassesVisitor classes_visitor(image_writer_, class_loader);
-    ClassTable* class_table =
-        Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader);
-    class_table->Visit(classes_visitor);
-    removed_class_count_ += classes_visitor.Prune();
-
-    // Record app image class loader. The fake boot class loader should not get registered
-    // and we should end up with only one class loader for an app and none for boot image.
-    if (class_loader != nullptr && class_table != nullptr) {
-      DCHECK(class_loader_ == nullptr);
-      class_loader_ = class_loader;
-    }
-  }
-
-  size_t GetRemovedClassCount() const {
-    return removed_class_count_;
-  }
-
-  ObjPtr<mirror::ClassLoader> GetClassLoader() const REQUIRES_SHARED(Locks::mutator_lock_) {
-    return class_loader_;
-  }
-
- private:
-  ImageWriter* const image_writer_;
-  size_t removed_class_count_;
-  ObjPtr<mirror::ClassLoader> class_loader_;
-};
-
-void ImageWriter::VisitClassLoaders(ClassLoaderVisitor* visitor) {
-  WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
-  visitor->Visit(nullptr);  // Visit boot class loader.
-  Runtime::Current()->GetClassLinker()->VisitClassLoaders(visitor);
-}
-
-void ImageWriter::PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache,
-                                          ObjPtr<mirror::ClassLoader> class_loader) {
-  // To ensure deterministic contents of the hash-based arrays, each slot shall contain
-  // the candidate with the lowest index. As we're processing entries in increasing index
-  // order, this means trying to look up the entry for the current index if the slot is
-  // empty or if it contains a higher index.
-
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  const DexFile& dex_file = *dex_cache->GetDexFile();
-  // Prune methods.
-  mirror::MethodDexCacheType* resolved_methods = dex_cache->GetResolvedMethods();
-  dex::TypeIndex last_class_idx;  // Initialized to invalid index.
-  ObjPtr<mirror::Class> last_class = nullptr;
-  for (size_t i = 0, num = dex_cache->GetDexFile()->NumMethodIds(); i != num; ++i) {
-    uint32_t slot_idx = dex_cache->MethodSlotIndex(i);
-    auto pair =
-        mirror::DexCache::GetNativePairPtrSize(resolved_methods, slot_idx, target_ptr_size_);
-    uint32_t stored_index = pair.index;
-    ArtMethod* method = pair.object;
-    if (method != nullptr && i > stored_index) {
-      continue;  // Already checked.
-    }
-    // Check if the referenced class is in the image. Note that we want to check the referenced
-    // class rather than the declaring class to preserve the semantics, i.e. using a MethodId
-    // results in resolving the referenced class and that can for example throw OOME.
-    const DexFile::MethodId& method_id = dex_file.GetMethodId(i);
-    if (method_id.class_idx_ != last_class_idx) {
-      last_class_idx = method_id.class_idx_;
-      last_class = class_linker->LookupResolvedType(
-          dex_file, last_class_idx, dex_cache, class_loader);
-      if (last_class != nullptr && !KeepClass(last_class)) {
-        last_class = nullptr;
-      }
-    }
-    if (method == nullptr || i < stored_index) {
-      if (last_class != nullptr) {
-        const char* name = dex_file.StringDataByIdx(method_id.name_idx_);
-        Signature signature = dex_file.GetMethodSignature(method_id);
-        if (last_class->IsInterface()) {
-          method = last_class->FindInterfaceMethod(name, signature, target_ptr_size_);
-        } else {
-          method = last_class->FindClassMethod(name, signature, target_ptr_size_);
-        }
-        if (method != nullptr) {
-          // If the referenced class is in the image, the defining class must also be there.
-          DCHECK(KeepClass(method->GetDeclaringClass()));
-          dex_cache->SetResolvedMethod(i, method, target_ptr_size_);
-        }
-      }
-    } else {
-      DCHECK_EQ(i, stored_index);
-      if (last_class == nullptr) {
-        dex_cache->ClearResolvedMethod(stored_index, target_ptr_size_);
-      }
-    }
-  }
-  // Prune fields and make the contents of the field array deterministic.
-  mirror::FieldDexCacheType* resolved_fields = dex_cache->GetResolvedFields();
-  last_class_idx = dex::TypeIndex();  // Initialized to invalid index.
-  last_class = nullptr;
-  for (size_t i = 0, end = dex_file.NumFieldIds(); i < end; ++i) {
-    uint32_t slot_idx = dex_cache->FieldSlotIndex(i);
-    auto pair = mirror::DexCache::GetNativePairPtrSize(resolved_fields, slot_idx, target_ptr_size_);
-    uint32_t stored_index = pair.index;
-    ArtField* field = pair.object;
-    if (field != nullptr && i > stored_index) {
-      continue;  // Already checked.
-    }
-    // Check if the referenced class is in the image. Note that we want to check the referenced
-    // class rather than the declaring class to preserve the semantics, i.e. using a FieldId
-    // results in resolving the referenced class and that can for example throw OOME.
-    const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
-    if (field_id.class_idx_ != last_class_idx) {
-      last_class_idx = field_id.class_idx_;
-      last_class = class_linker->LookupResolvedType(
-          dex_file, last_class_idx, dex_cache, class_loader);
-      if (last_class != nullptr && !KeepClass(last_class)) {
-        last_class = nullptr;
-      }
-    }
-    if (field == nullptr || i < stored_index) {
-      if (last_class != nullptr) {
-        const char* name = dex_file.StringDataByIdx(field_id.name_idx_);
-        const char* type = dex_file.StringByTypeIdx(field_id.type_idx_);
-        field = mirror::Class::FindField(Thread::Current(), last_class, name, type);
-        if (field != nullptr) {
-          // If the referenced class is in the image, the defining class must also be there.
-          DCHECK(KeepClass(field->GetDeclaringClass()));
-          dex_cache->SetResolvedField(i, field, target_ptr_size_);
-        }
-      }
-    } else {
-      DCHECK_EQ(i, stored_index);
-      if (last_class == nullptr) {
-        dex_cache->ClearResolvedField(stored_index, target_ptr_size_);
-      }
-    }
-  }
-  // Prune types and make the contents of the type array deterministic.
-  // This is done after fields and methods as their lookup can touch the types array.
-  for (size_t i = 0, end = dex_cache->GetDexFile()->NumTypeIds(); i < end; ++i) {
-    dex::TypeIndex type_idx(i);
-    uint32_t slot_idx = dex_cache->TypeSlotIndex(type_idx);
-    mirror::TypeDexCachePair pair =
-        dex_cache->GetResolvedTypes()[slot_idx].load(std::memory_order_relaxed);
-    uint32_t stored_index = pair.index;
-    ObjPtr<mirror::Class> klass = pair.object.Read();
-    if (klass == nullptr || i < stored_index) {
-      klass = class_linker->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader);
-      if (klass != nullptr) {
-        DCHECK_EQ(dex_cache->GetResolvedType(type_idx), klass);
-        stored_index = i;  // For correct clearing below if not keeping the `klass`.
-      }
-    } else if (i == stored_index && !KeepClass(klass)) {
-      dex_cache->ClearResolvedType(dex::TypeIndex(stored_index));
-    }
-  }
-  // Strings do not need pruning, but the contents of the string array must be deterministic.
-  for (size_t i = 0, end = dex_cache->GetDexFile()->NumStringIds(); i < end; ++i) {
-    dex::StringIndex string_idx(i);
-    uint32_t slot_idx = dex_cache->StringSlotIndex(string_idx);
-    mirror::StringDexCachePair pair =
-        dex_cache->GetStrings()[slot_idx].load(std::memory_order_relaxed);
-    uint32_t stored_index = pair.index;
-    ObjPtr<mirror::String> string = pair.object.Read();
-    if (string == nullptr || i < stored_index) {
-      string = class_linker->LookupString(dex_file, string_idx, dex_cache);
-      DCHECK(string == nullptr || dex_cache->GetResolvedString(string_idx) == string);
-    }
-  }
-}
-
-void ImageWriter::PruneNonImageClasses() {
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  Thread* self = Thread::Current();
-  ScopedAssertNoThreadSuspension sa(__FUNCTION__);
-
-  // Prune uses-library dex caches. Only prune the uses-library dex caches since we want to make
-  // sure the other ones don't get unloaded before the OatWriter runs.
-  class_linker->VisitClassTables(
-      [&](ClassTable* table) REQUIRES_SHARED(Locks::mutator_lock_) {
-    table->RemoveStrongRoots(
-        [&](GcRoot<mirror::Object> root) REQUIRES_SHARED(Locks::mutator_lock_) {
-      ObjPtr<mirror::Object> obj = root.Read();
-      if (obj->IsDexCache()) {
-        // Return true if the dex file is not one of the ones in the map.
-        return dex_file_oat_index_map_.find(obj->AsDexCache()->GetDexFile()) ==
-            dex_file_oat_index_map_.end();
-      }
-      // Return false to avoid removing.
-      return false;
-    });
-  });
-
-  // Remove the undesired classes from the class roots.
-  ObjPtr<mirror::ClassLoader> class_loader;
-  {
-    PruneClassLoaderClassesVisitor class_loader_visitor(this);
-    VisitClassLoaders(&class_loader_visitor);
-    VLOG(compiler) << "Pruned " << class_loader_visitor.GetRemovedClassCount() << " classes";
-    class_loader = class_loader_visitor.GetClassLoader();
-    DCHECK_EQ(class_loader != nullptr, compile_app_image_);
-  }
-
-  // Clear references to removed classes from the DexCaches.
-  std::vector<ObjPtr<mirror::DexCache>> dex_caches;
-  {
-    ReaderMutexLock mu2(self, *Locks::dex_lock_);
-    dex_caches.reserve(class_linker->GetDexCachesData().size());
-    for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
-      if (self->IsJWeakCleared(data.weak_root)) {
-        continue;
-      }
-      dex_caches.push_back(self->DecodeJObject(data.weak_root)->AsDexCache());
-    }
-  }
-  for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) {
-    PruneAndPreloadDexCache(dex_cache, class_loader);
-  }
-
-  // Drop the array class cache in the ClassLinker, as these are roots holding those classes live.
-  class_linker->DropFindArrayClassCache();
-
-  // Clear to save RAM.
-  prune_class_memo_.clear();
-}
-
-void ImageWriter::CheckNonImageClassesRemoved() {
-  if (compiler_driver_.GetImageClasses() != nullptr) {
-    auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-      if (obj->IsClass() && !IsInBootImage(obj)) {
-        Class* klass = obj->AsClass();
-        if (!KeepClass(klass)) {
-          DumpImageClasses();
-          std::string temp;
-          CHECK(KeepClass(klass))
-              << Runtime::Current()->GetHeap()->GetVerification()->FirstPathFromRootSet(klass);
-        }
-      }
-    };
-    gc::Heap* heap = Runtime::Current()->GetHeap();
-    heap->VisitObjects(visitor);
-  }
-}
-
-void ImageWriter::DumpImageClasses() {
-  auto image_classes = compiler_driver_.GetImageClasses();
-  CHECK(image_classes != nullptr);
-  for (const std::string& image_class : *image_classes) {
-    LOG(INFO) << " " << image_class;
-  }
-}
-
-mirror::String* ImageWriter::FindInternedString(mirror::String* string) {
-  Thread* const self = Thread::Current();
-  for (const ImageInfo& image_info : image_infos_) {
-    ObjPtr<mirror::String> const found = image_info.intern_table_->LookupStrong(self, string);
-    DCHECK(image_info.intern_table_->LookupWeak(self, string) == nullptr)
-        << string->ToModifiedUtf8();
-    if (found != nullptr) {
-      return found.Ptr();
-    }
-  }
-  if (compile_app_image_) {
-    Runtime* const runtime = Runtime::Current();
-    ObjPtr<mirror::String> found = runtime->GetInternTable()->LookupStrong(self, string);
-    // If we found it in the runtime intern table it could either be in the boot image or interned
-    // during app image compilation. If it was in the boot image return that, otherwise return null
-    // since it belongs to another image space.
-    if (found != nullptr && runtime->GetHeap()->ObjectIsInBootImageSpace(found.Ptr())) {
-      return found.Ptr();
-    }
-    DCHECK(runtime->GetInternTable()->LookupWeak(self, string) == nullptr)
-        << string->ToModifiedUtf8();
-  }
-  return nullptr;
-}
-
-
-ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const {
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  Thread* self = Thread::Current();
-  StackHandleScope<3> hs(self);
-  Handle<Class> object_array_class(hs.NewHandle(
-      class_linker->FindSystemClass(self, "[Ljava/lang/Object;")));
-
-  std::unordered_set<const DexFile*> image_dex_files;
-  for (auto& pair : dex_file_oat_index_map_) {
-    const DexFile* image_dex_file = pair.first;
-    size_t image_oat_index = pair.second;
-    if (oat_index == image_oat_index) {
-      image_dex_files.insert(image_dex_file);
-    }
-  }
-
-  // build an Object[] of all the DexCaches used in the source_space_.
-  // Since we can't hold the dex lock when allocating the dex_caches
-  // ObjectArray, we lock the dex lock twice, first to get the number
-  // of dex caches first and then lock it again to copy the dex
-  // caches. We check that the number of dex caches does not change.
-  size_t dex_cache_count = 0;
-  {
-    ReaderMutexLock mu(self, *Locks::dex_lock_);
-    // Count number of dex caches not in the boot image.
-    for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
-      ObjPtr<mirror::DexCache> dex_cache =
-          ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
-      if (dex_cache == nullptr) {
-        continue;
-      }
-      const DexFile* dex_file = dex_cache->GetDexFile();
-      if (!IsInBootImage(dex_cache.Ptr())) {
-        dex_cache_count += image_dex_files.find(dex_file) != image_dex_files.end() ? 1u : 0u;
-      }
-    }
-  }
-  Handle<ObjectArray<Object>> dex_caches(
-      hs.NewHandle(ObjectArray<Object>::Alloc(self, object_array_class.Get(), dex_cache_count)));
-  CHECK(dex_caches != nullptr) << "Failed to allocate a dex cache array.";
-  {
-    ReaderMutexLock mu(self, *Locks::dex_lock_);
-    size_t non_image_dex_caches = 0;
-    // Re-count number of non image dex caches.
-    for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
-      ObjPtr<mirror::DexCache> dex_cache =
-          ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
-      if (dex_cache == nullptr) {
-        continue;
-      }
-      const DexFile* dex_file = dex_cache->GetDexFile();
-      if (!IsInBootImage(dex_cache.Ptr())) {
-        non_image_dex_caches += image_dex_files.find(dex_file) != image_dex_files.end() ? 1u : 0u;
-      }
-    }
-    CHECK_EQ(dex_cache_count, non_image_dex_caches)
-        << "The number of non-image dex caches changed.";
-    size_t i = 0;
-    for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
-      ObjPtr<mirror::DexCache> dex_cache =
-          ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
-      if (dex_cache == nullptr) {
-        continue;
-      }
-      const DexFile* dex_file = dex_cache->GetDexFile();
-      if (!IsInBootImage(dex_cache.Ptr()) &&
-          image_dex_files.find(dex_file) != image_dex_files.end()) {
-        dex_caches->Set<false>(i, dex_cache.Ptr());
-        ++i;
-      }
-    }
-  }
-
-  // build an Object[] of the roots needed to restore the runtime
-  int32_t image_roots_size = ImageHeader::NumberOfImageRoots(compile_app_image_);
-  auto image_roots(hs.NewHandle(
-      ObjectArray<Object>::Alloc(self, object_array_class.Get(), image_roots_size)));
-  image_roots->Set<false>(ImageHeader::kDexCaches, dex_caches.Get());
-  image_roots->Set<false>(ImageHeader::kClassRoots, class_linker->GetClassRoots());
-  // image_roots[ImageHeader::kClassLoader] will be set later for app image.
-  static_assert(ImageHeader::kClassLoader + 1u == ImageHeader::kImageRootsMax,
-                "Class loader should be the last image root.");
-  for (int32_t i = 0; i < ImageHeader::kImageRootsMax - 1; ++i) {
-    CHECK(image_roots->Get(i) != nullptr);
-  }
-  return image_roots.Get();
-}
-
-mirror::Object* ImageWriter::TryAssignBinSlot(WorkStack& work_stack,
-                                              mirror::Object* obj,
-                                              size_t oat_index) {
-  if (obj == nullptr || IsInBootImage(obj)) {
-    // Object is null or already in the image, there is no work to do.
-    return obj;
-  }
-  if (!IsImageBinSlotAssigned(obj)) {
-    // We want to intern all strings but also assign offsets for the source string. Since the
-    // pruning phase has already happened, if we intern a string to one in the image we still
-    // end up copying an unreachable string.
-    if (obj->IsString()) {
-      // Need to check if the string is already interned in another image info so that we don't have
-      // the intern tables of two different images contain the same string.
-      mirror::String* interned = FindInternedString(obj->AsString());
-      if (interned == nullptr) {
-        // Not in another image space, insert to our table.
-        interned =
-            GetImageInfo(oat_index).intern_table_->InternStrongImageString(obj->AsString()).Ptr();
-        DCHECK_EQ(interned, obj);
-      }
-    } else if (obj->IsDexCache()) {
-      oat_index = GetOatIndexForDexCache(obj->AsDexCache());
-    } else if (obj->IsClass()) {
-      // Visit and assign offsets for fields and field arrays.
-      mirror::Class* as_klass = obj->AsClass();
-      mirror::DexCache* dex_cache = as_klass->GetDexCache();
-      DCHECK(!as_klass->IsErroneous()) << as_klass->GetStatus();
-      if (compile_app_image_) {
-        // Extra sanity, no boot loader classes should be left!
-        CHECK(!IsBootClassLoaderClass(as_klass)) << as_klass->PrettyClass();
-      }
-      LengthPrefixedArray<ArtField>* fields[] = {
-          as_klass->GetSFieldsPtr(), as_klass->GetIFieldsPtr(),
-      };
-      // Overwrite the oat index value since the class' dex cache is more accurate of where it
-      // belongs.
-      oat_index = GetOatIndexForDexCache(dex_cache);
-      ImageInfo& image_info = GetImageInfo(oat_index);
-      if (!compile_app_image_) {
-        // Note: Avoid locking to prevent lock order violations from root visiting;
-        // image_info.class_table_ is only accessed from the image writer.
-        image_info.class_table_->InsertWithoutLocks(as_klass);
-      }
-      for (LengthPrefixedArray<ArtField>* cur_fields : fields) {
-        // Total array length including header.
-        if (cur_fields != nullptr) {
-          const size_t header_size = LengthPrefixedArray<ArtField>::ComputeSize(0);
-          // Forward the entire array at once.
-          auto it = native_object_relocations_.find(cur_fields);
-          CHECK(it == native_object_relocations_.end()) << "Field array " << cur_fields
-                                                  << " already forwarded";
-          size_t& offset = image_info.bin_slot_sizes_[kBinArtField];
-          DCHECK(!IsInBootImage(cur_fields));
-          native_object_relocations_.emplace(
-              cur_fields,
-              NativeObjectRelocation {
-                  oat_index, offset, kNativeObjectRelocationTypeArtFieldArray
-              });
-          offset += header_size;
-          // Forward individual fields so that we can quickly find where they belong.
-          for (size_t i = 0, count = cur_fields->size(); i < count; ++i) {
-            // Need to forward arrays separate of fields.
-            ArtField* field = &cur_fields->At(i);
-            auto it2 = native_object_relocations_.find(field);
-            CHECK(it2 == native_object_relocations_.end()) << "Field at index=" << i
-                << " already assigned " << field->PrettyField() << " static=" << field->IsStatic();
-            DCHECK(!IsInBootImage(field));
-            native_object_relocations_.emplace(
-                field,
-                NativeObjectRelocation { oat_index, offset, kNativeObjectRelocationTypeArtField });
-            offset += sizeof(ArtField);
-          }
-        }
-      }
-      // Visit and assign offsets for methods.
-      size_t num_methods = as_klass->NumMethods();
-      if (num_methods != 0) {
-        bool any_dirty = false;
-        for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
-          if (WillMethodBeDirty(&m)) {
-            any_dirty = true;
-            break;
-          }
-        }
-        NativeObjectRelocationType type = any_dirty
-            ? kNativeObjectRelocationTypeArtMethodDirty
-            : kNativeObjectRelocationTypeArtMethodClean;
-        Bin bin_type = BinTypeForNativeRelocationType(type);
-        // Forward the entire array at once, but header first.
-        const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
-        const size_t method_size = ArtMethod::Size(target_ptr_size_);
-        const size_t header_size = LengthPrefixedArray<ArtMethod>::ComputeSize(0,
-                                                                               method_size,
-                                                                               method_alignment);
-        LengthPrefixedArray<ArtMethod>* array = as_klass->GetMethodsPtr();
-        auto it = native_object_relocations_.find(array);
-        CHECK(it == native_object_relocations_.end())
-            << "Method array " << array << " already forwarded";
-        size_t& offset = image_info.bin_slot_sizes_[bin_type];
-        DCHECK(!IsInBootImage(array));
-        native_object_relocations_.emplace(array,
-            NativeObjectRelocation {
-                oat_index,
-                offset,
-                any_dirty ? kNativeObjectRelocationTypeArtMethodArrayDirty
-                          : kNativeObjectRelocationTypeArtMethodArrayClean });
-        offset += header_size;
-        for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
-          AssignMethodOffset(&m, type, oat_index);
-        }
-        (any_dirty ? dirty_methods_ : clean_methods_) += num_methods;
-      }
-      // Assign offsets for all runtime methods in the IMT since these may hold conflict tables
-      // live.
-      if (as_klass->ShouldHaveImt()) {
-        ImTable* imt = as_klass->GetImt(target_ptr_size_);
-        if (TryAssignImTableOffset(imt, oat_index)) {
-          // Since imt's can be shared only do this the first time to not double count imt method
-          // fixups.
-          for (size_t i = 0; i < ImTable::kSize; ++i) {
-            ArtMethod* imt_method = imt->Get(i, target_ptr_size_);
-            DCHECK(imt_method != nullptr);
-            if (imt_method->IsRuntimeMethod() &&
-                !IsInBootImage(imt_method) &&
-                !NativeRelocationAssigned(imt_method)) {
-              AssignMethodOffset(imt_method, kNativeObjectRelocationTypeRuntimeMethod, oat_index);
-            }
-          }
-        }
-      }
-    } else if (obj->IsClassLoader()) {
-      // Register the class loader if it has a class table.
-      // The fake boot class loader should not get registered and we should end up with only one
-      // class loader.
-      mirror::ClassLoader* class_loader = obj->AsClassLoader();
-      if (class_loader->GetClassTable() != nullptr) {
-        DCHECK(compile_app_image_);
-        DCHECK(class_loaders_.empty());
-        class_loaders_.insert(class_loader);
-        ImageInfo& image_info = GetImageInfo(oat_index);
-        // Note: Avoid locking to prevent lock order violations from root visiting;
-        // image_info.class_table_ table is only accessed from the image writer
-        // and class_loader->GetClassTable() is iterated but not modified.
-        image_info.class_table_->CopyWithoutLocks(*class_loader->GetClassTable());
-      }
-    }
-    AssignImageBinSlot(obj, oat_index);
-    work_stack.emplace(obj, oat_index);
-  }
-  if (obj->IsString()) {
-    // Always return the interned string if there exists one.
-    mirror::String* interned = FindInternedString(obj->AsString());
-    if (interned != nullptr) {
-      return interned;
-    }
-  }
-  return obj;
-}
-
-bool ImageWriter::NativeRelocationAssigned(void* ptr) const {
-  return native_object_relocations_.find(ptr) != native_object_relocations_.end();
-}
-
-bool ImageWriter::TryAssignImTableOffset(ImTable* imt, size_t oat_index) {
-  // No offset, or already assigned.
-  if (imt == nullptr || IsInBootImage(imt) || NativeRelocationAssigned(imt)) {
-    return false;
-  }
-  // If the method is a conflict method we also want to assign the conflict table offset.
-  ImageInfo& image_info = GetImageInfo(oat_index);
-  const size_t size = ImTable::SizeInBytes(target_ptr_size_);
-  native_object_relocations_.emplace(
-      imt,
-      NativeObjectRelocation {
-          oat_index,
-          image_info.bin_slot_sizes_[kBinImTable],
-          kNativeObjectRelocationTypeIMTable});
-  image_info.bin_slot_sizes_[kBinImTable] += size;
-  return true;
-}
-
-void ImageWriter::TryAssignConflictTableOffset(ImtConflictTable* table, size_t oat_index) {
-  // No offset, or already assigned.
-  if (table == nullptr || NativeRelocationAssigned(table)) {
-    return;
-  }
-  CHECK(!IsInBootImage(table));
-  // If the method is a conflict method we also want to assign the conflict table offset.
-  ImageInfo& image_info = GetImageInfo(oat_index);
-  const size_t size = table->ComputeSize(target_ptr_size_);
-  native_object_relocations_.emplace(
-      table,
-      NativeObjectRelocation {
-          oat_index,
-          image_info.bin_slot_sizes_[kBinIMTConflictTable],
-          kNativeObjectRelocationTypeIMTConflictTable});
-  image_info.bin_slot_sizes_[kBinIMTConflictTable] += size;
-}
-
-void ImageWriter::AssignMethodOffset(ArtMethod* method,
-                                     NativeObjectRelocationType type,
-                                     size_t oat_index) {
-  DCHECK(!IsInBootImage(method));
-  CHECK(!NativeRelocationAssigned(method)) << "Method " << method << " already assigned "
-      << ArtMethod::PrettyMethod(method);
-  if (method->IsRuntimeMethod()) {
-    TryAssignConflictTableOffset(method->GetImtConflictTable(target_ptr_size_), oat_index);
-  }
-  ImageInfo& image_info = GetImageInfo(oat_index);
-  size_t& offset = image_info.bin_slot_sizes_[BinTypeForNativeRelocationType(type)];
-  native_object_relocations_.emplace(method, NativeObjectRelocation { oat_index, offset, type });
-  offset += ArtMethod::Size(target_ptr_size_);
-}
-
-void ImageWriter::UnbinObjectsIntoOffset(mirror::Object* obj) {
-  DCHECK(!IsInBootImage(obj));
-  CHECK(obj != nullptr);
-
-  // We know the bin slot, and the total bin sizes for all objects by now,
-  // so calculate the object's final image offset.
-
-  DCHECK(IsImageBinSlotAssigned(obj));
-  BinSlot bin_slot = GetImageBinSlot(obj);
-  // Change the lockword from a bin slot into an offset
-  AssignImageOffset(obj, bin_slot);
-}
-
-class ImageWriter::VisitReferencesVisitor {
- public:
-  VisitReferencesVisitor(ImageWriter* image_writer, WorkStack* work_stack, size_t oat_index)
-      : image_writer_(image_writer), work_stack_(work_stack), oat_index_(oat_index) {}
-
-  // Fix up separately since we also need to fix up method entrypoints.
-  ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (!root->IsNull()) {
-      VisitRoot(root);
-    }
-  }
-
-  ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    root->Assign(VisitReference(root->AsMirrorPtr()));
-  }
-
-  ALWAYS_INLINE void operator() (ObjPtr<mirror::Object> obj,
-                                 MemberOffset offset,
-                                 bool is_static ATTRIBUTE_UNUSED) const
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    mirror::Object* ref =
-        obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset);
-    obj->SetFieldObject</*kTransactionActive*/false>(offset, VisitReference(ref));
-  }
-
-  ALWAYS_INLINE void operator() (ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
-                                 ObjPtr<mirror::Reference> ref) const
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    operator()(ref, mirror::Reference::ReferentOffset(), /* is_static */ false);
-  }
-
- private:
-  mirror::Object* VisitReference(mirror::Object* ref) const REQUIRES_SHARED(Locks::mutator_lock_) {
-    return image_writer_->TryAssignBinSlot(*work_stack_, ref, oat_index_);
-  }
-
-  ImageWriter* const image_writer_;
-  WorkStack* const work_stack_;
-  const size_t oat_index_;
-};
-
-class ImageWriter::GetRootsVisitor : public RootVisitor  {
- public:
-  explicit GetRootsVisitor(std::vector<mirror::Object*>* roots) : roots_(roots) {}
-
-  void VisitRoots(mirror::Object*** roots,
-                  size_t count,
-                  const RootInfo& info ATTRIBUTE_UNUSED) OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    for (size_t i = 0; i < count; ++i) {
-      roots_->push_back(*roots[i]);
-    }
-  }
-
-  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots,
-                  size_t count,
-                  const RootInfo& info ATTRIBUTE_UNUSED) OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    for (size_t i = 0; i < count; ++i) {
-      roots_->push_back(roots[i]->AsMirrorPtr());
-    }
-  }
-
- private:
-  std::vector<mirror::Object*>* const roots_;
-};
-
-void ImageWriter::ProcessWorkStack(WorkStack* work_stack) {
-  while (!work_stack->empty()) {
-    std::pair<mirror::Object*, size_t> pair(work_stack->top());
-    work_stack->pop();
-    VisitReferencesVisitor visitor(this, work_stack, /*oat_index*/ pair.second);
-    // Walk references and assign bin slots for them.
-    pair.first->VisitReferences</*kVisitNativeRoots*/true, kVerifyNone, kWithoutReadBarrier>(
-        visitor,
-        visitor);
-  }
-}
-
-void ImageWriter::CalculateNewObjectOffsets() {
-  Thread* const self = Thread::Current();
-  VariableSizedHandleScope handles(self);
-  std::vector<Handle<ObjectArray<Object>>> image_roots;
-  for (size_t i = 0, size = oat_filenames_.size(); i != size; ++i) {
-    image_roots.push_back(handles.NewHandle(CreateImageRoots(i)));
-  }
-
-  Runtime* const runtime = Runtime::Current();
-  gc::Heap* const heap = runtime->GetHeap();
-
-  // Leave space for the header, but do not write it yet, we need to
-  // know where image_roots is going to end up
-  image_objects_offset_begin_ = RoundUp(sizeof(ImageHeader), kObjectAlignment);  // 64-bit-alignment
-
-  const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
-  // Write the image runtime methods.
-  image_methods_[ImageHeader::kResolutionMethod] = runtime->GetResolutionMethod();
-  image_methods_[ImageHeader::kImtConflictMethod] = runtime->GetImtConflictMethod();
-  image_methods_[ImageHeader::kImtUnimplementedMethod] = runtime->GetImtUnimplementedMethod();
-  image_methods_[ImageHeader::kSaveAllCalleeSavesMethod] =
-      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveAllCalleeSaves);
-  image_methods_[ImageHeader::kSaveRefsOnlyMethod] =
-      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsOnly);
-  image_methods_[ImageHeader::kSaveRefsAndArgsMethod] =
-      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs);
-  image_methods_[ImageHeader::kSaveEverythingMethod] =
-      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverything);
-  image_methods_[ImageHeader::kSaveEverythingMethodForClinit] =
-      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForClinit);
-  image_methods_[ImageHeader::kSaveEverythingMethodForSuspendCheck] =
-      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForSuspendCheck);
-  // Visit image methods first to have the main runtime methods in the first image.
-  for (auto* m : image_methods_) {
-    CHECK(m != nullptr);
-    CHECK(m->IsRuntimeMethod());
-    DCHECK_EQ(compile_app_image_, IsInBootImage(m)) << "Trampolines should be in boot image";
-    if (!IsInBootImage(m)) {
-      AssignMethodOffset(m, kNativeObjectRelocationTypeRuntimeMethod, GetDefaultOatIndex());
-    }
-  }
-
-  // Deflate monitors before we visit roots since deflating acquires the monitor lock. Acquiring
-  // this lock while holding other locks may cause lock order violations.
-  {
-    auto deflate_monitor = [](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-      Monitor::Deflate(Thread::Current(), obj);
-    };
-    heap->VisitObjects(deflate_monitor);
-  }
-
-  // Work list of <object, oat_index> for objects. Everything on the stack must already be
-  // assigned a bin slot.
-  WorkStack work_stack;
-
-  // Special case interned strings to put them in the image they are likely to be resolved from.
-  for (const DexFile* dex_file : compiler_driver_.GetDexFilesForOatFile()) {
-    auto it = dex_file_oat_index_map_.find(dex_file);
-    DCHECK(it != dex_file_oat_index_map_.end()) << dex_file->GetLocation();
-    const size_t oat_index = it->second;
-    InternTable* const intern_table = runtime->GetInternTable();
-    for (size_t i = 0, count = dex_file->NumStringIds(); i < count; ++i) {
-      uint32_t utf16_length;
-      const char* utf8_data = dex_file->StringDataAndUtf16LengthByIdx(dex::StringIndex(i),
-                                                                      &utf16_length);
-      mirror::String* string = intern_table->LookupStrong(self, utf16_length, utf8_data).Ptr();
-      TryAssignBinSlot(work_stack, string, oat_index);
-    }
-  }
-
-  // Get the GC roots and then visit them separately to avoid lock violations since the root visitor
-  // visits roots while holding various locks.
-  {
-    std::vector<mirror::Object*> roots;
-    GetRootsVisitor root_visitor(&roots);
-    runtime->VisitRoots(&root_visitor);
-    for (mirror::Object* obj : roots) {
-      TryAssignBinSlot(work_stack, obj, GetDefaultOatIndex());
-    }
-  }
-  ProcessWorkStack(&work_stack);
-
-  // For app images, there may be objects that are only held live by the by the boot image. One
-  // example is finalizer references. Forward these objects so that EnsureBinSlotAssignedCallback
-  // does not fail any checks. TODO: We should probably avoid copying these objects.
-  if (compile_app_image_) {
-    for (gc::space::ImageSpace* space : heap->GetBootImageSpaces()) {
-      DCHECK(space->IsImageSpace());
-      gc::accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
-      live_bitmap->VisitMarkedRange(reinterpret_cast<uintptr_t>(space->Begin()),
-                                    reinterpret_cast<uintptr_t>(space->Limit()),
-                                    [this, &work_stack](mirror::Object* obj)
-          REQUIRES_SHARED(Locks::mutator_lock_) {
-        VisitReferencesVisitor visitor(this, &work_stack, GetDefaultOatIndex());
-        // Visit all references and try to assign bin slots for them (calls TryAssignBinSlot).
-        obj->VisitReferences</*kVisitNativeRoots*/true, kVerifyNone, kWithoutReadBarrier>(
-            visitor,
-            visitor);
-      });
-    }
-    // Process the work stack in case anything was added by TryAssignBinSlot.
-    ProcessWorkStack(&work_stack);
-
-    // Store the class loader in the class roots.
-    CHECK_EQ(class_loaders_.size(), 1u);
-    CHECK_EQ(image_roots.size(), 1u);
-    CHECK(*class_loaders_.begin() != nullptr);
-    image_roots[0]->Set<false>(ImageHeader::kClassLoader, *class_loaders_.begin());
-  }
-
-  // Verify that all objects have assigned image bin slots.
-  {
-    auto ensure_bin_slots_assigned = [&](mirror::Object* obj)
-        REQUIRES_SHARED(Locks::mutator_lock_) {
-      if (!Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(obj)) {
-        CHECK(IsImageBinSlotAssigned(obj)) << mirror::Object::PrettyTypeOf(obj) << " " << obj;
-      }
-    };
-    heap->VisitObjects(ensure_bin_slots_assigned);
-  }
-
-  // Calculate size of the dex cache arrays slot and prepare offsets.
-  PrepareDexCacheArraySlots();
-
-  // Calculate the sizes of the intern tables, class tables, and fixup tables.
-  for (ImageInfo& image_info : image_infos_) {
-    // Calculate how big the intern table will be after being serialized.
-    InternTable* const intern_table = image_info.intern_table_.get();
-    CHECK_EQ(intern_table->WeakSize(), 0u) << " should have strong interned all the strings";
-    if (intern_table->StrongSize() != 0u) {
-      image_info.intern_table_bytes_ = intern_table->WriteToMemory(nullptr);
-    }
-
-    // Calculate the size of the class table.
-    ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
-    DCHECK_EQ(image_info.class_table_->NumReferencedZygoteClasses(), 0u);
-    if (image_info.class_table_->NumReferencedNonZygoteClasses() != 0u) {
-      image_info.class_table_bytes_ += image_info.class_table_->WriteToMemory(nullptr);
-    }
-  }
-
-  // Calculate bin slot offsets.
-  for (ImageInfo& image_info : image_infos_) {
-    size_t bin_offset = image_objects_offset_begin_;
-    for (size_t i = 0; i != kBinSize; ++i) {
-      switch (i) {
-        case kBinArtMethodClean:
-        case kBinArtMethodDirty: {
-          bin_offset = RoundUp(bin_offset, method_alignment);
-          break;
-        }
-        case kBinDexCacheArray:
-          bin_offset = RoundUp(bin_offset, DexCacheArraysLayout::Alignment(target_ptr_size_));
-          break;
-        case kBinImTable:
-        case kBinIMTConflictTable: {
-          bin_offset = RoundUp(bin_offset, static_cast<size_t>(target_ptr_size_));
-          break;
-        }
-        default: {
-          // Normal alignment.
-        }
-      }
-      image_info.bin_slot_offsets_[i] = bin_offset;
-      bin_offset += image_info.bin_slot_sizes_[i];
-    }
-    // NOTE: There may be additional padding between the bin slots and the intern table.
-    DCHECK_EQ(image_info.image_end_,
-              GetBinSizeSum(image_info, kBinMirrorCount) + image_objects_offset_begin_);
-  }
-
-  // Calculate image offsets.
-  size_t image_offset = 0;
-  for (ImageInfo& image_info : image_infos_) {
-    image_info.image_begin_ = global_image_begin_ + image_offset;
-    image_info.image_offset_ = image_offset;
-    ImageSection unused_sections[ImageHeader::kSectionCount];
-    image_info.image_size_ =
-        RoundUp(image_info.CreateImageSections(unused_sections, compile_app_image_), kPageSize);
-    // There should be no gaps until the next image.
-    image_offset += image_info.image_size_;
-  }
-
-  // Transform each object's bin slot into an offset which will be used to do the final copy.
-  {
-    auto unbin_objects_into_offset = [&](mirror::Object* obj)
-        REQUIRES_SHARED(Locks::mutator_lock_) {
-      if (!IsInBootImage(obj)) {
-        UnbinObjectsIntoOffset(obj);
-      }
-    };
-    heap->VisitObjects(unbin_objects_into_offset);
-  }
-
-  size_t i = 0;
-  for (ImageInfo& image_info : image_infos_) {
-    image_info.image_roots_address_ = PointerToLowMemUInt32(GetImageAddress(image_roots[i].Get()));
-    i++;
-  }
-
-  // Update the native relocations by adding their bin sums.
-  for (auto& pair : native_object_relocations_) {
-    NativeObjectRelocation& relocation = pair.second;
-    Bin bin_type = BinTypeForNativeRelocationType(relocation.type);
-    ImageInfo& image_info = GetImageInfo(relocation.oat_index);
-    relocation.offset += image_info.bin_slot_offsets_[bin_type];
-  }
-}
-
-size_t ImageWriter::ImageInfo::CreateImageSections(ImageSection* out_sections,
-                                                   bool app_image) const {
-  DCHECK(out_sections != nullptr);
-
-  // Do not round up any sections here that are represented by the bins since it will break
-  // offsets.
-
-  // Objects section
-  ImageSection* objects_section = &out_sections[ImageHeader::kSectionObjects];
-  *objects_section = ImageSection(0u, image_end_);
-
-  // Add field section.
-  ImageSection* field_section = &out_sections[ImageHeader::kSectionArtFields];
-  *field_section = ImageSection(bin_slot_offsets_[kBinArtField], bin_slot_sizes_[kBinArtField]);
-  CHECK_EQ(bin_slot_offsets_[kBinArtField], field_section->Offset());
-
-  // Add method section.
-  ImageSection* methods_section = &out_sections[ImageHeader::kSectionArtMethods];
-  *methods_section = ImageSection(
-      bin_slot_offsets_[kBinArtMethodClean],
-      bin_slot_sizes_[kBinArtMethodClean] + bin_slot_sizes_[kBinArtMethodDirty]);
-
-  // IMT section.
-  ImageSection* imt_section = &out_sections[ImageHeader::kSectionImTables];
-  *imt_section = ImageSection(bin_slot_offsets_[kBinImTable], bin_slot_sizes_[kBinImTable]);
-
-  // Conflict tables section.
-  ImageSection* imt_conflict_tables_section = &out_sections[ImageHeader::kSectionIMTConflictTables];
-  *imt_conflict_tables_section = ImageSection(bin_slot_offsets_[kBinIMTConflictTable],
-                                              bin_slot_sizes_[kBinIMTConflictTable]);
-
-  // Runtime methods section.
-  ImageSection* runtime_methods_section = &out_sections[ImageHeader::kSectionRuntimeMethods];
-  *runtime_methods_section = ImageSection(bin_slot_offsets_[kBinRuntimeMethod],
-                                          bin_slot_sizes_[kBinRuntimeMethod]);
-
-  // Add dex cache arrays section.
-  ImageSection* dex_cache_arrays_section = &out_sections[ImageHeader::kSectionDexCacheArrays];
-  *dex_cache_arrays_section = ImageSection(bin_slot_offsets_[kBinDexCacheArray],
-                                           bin_slot_sizes_[kBinDexCacheArray]);
-  // For boot image, round up to the page boundary to separate the interned strings and
-  // class table from the modifiable data. We shall mprotect() these pages read-only when
-  // we load the boot image. This is more than sufficient for the string table alignment,
-  // namely sizeof(uint64_t). See HashSet::WriteToMemory.
-  static_assert(IsAligned<sizeof(uint64_t)>(kPageSize), "String table alignment check.");
-  size_t cur_pos =
-      RoundUp(dex_cache_arrays_section->End(), app_image ? sizeof(uint64_t) : kPageSize);
-  // Calculate the size of the interned strings.
-  ImageSection* interned_strings_section = &out_sections[ImageHeader::kSectionInternedStrings];
-  *interned_strings_section = ImageSection(cur_pos, intern_table_bytes_);
-  cur_pos = interned_strings_section->End();
-  // Round up to the alignment the class table expects. See HashSet::WriteToMemory.
-  cur_pos = RoundUp(cur_pos, sizeof(uint64_t));
-  // Calculate the size of the class table section.
-  ImageSection* class_table_section = &out_sections[ImageHeader::kSectionClassTable];
-  *class_table_section = ImageSection(cur_pos, class_table_bytes_);
-  cur_pos = class_table_section->End();
-  // Image end goes right before the start of the image bitmap.
-  return cur_pos;
-}
-
-void ImageWriter::CreateHeader(size_t oat_index) {
-  ImageInfo& image_info = GetImageInfo(oat_index);
-  const uint8_t* oat_file_begin = image_info.oat_file_begin_;
-  const uint8_t* oat_file_end = oat_file_begin + image_info.oat_loaded_size_;
-  const uint8_t* oat_data_end = image_info.oat_data_begin_ + image_info.oat_size_;
-
-  // Create the image sections.
-  ImageSection sections[ImageHeader::kSectionCount];
-  const size_t image_end = image_info.CreateImageSections(sections, compile_app_image_);
-
-  // Finally bitmap section.
-  const size_t bitmap_bytes = image_info.image_bitmap_->Size();
-  auto* bitmap_section = &sections[ImageHeader::kSectionImageBitmap];
-  *bitmap_section = ImageSection(RoundUp(image_end, kPageSize), RoundUp(bitmap_bytes, kPageSize));
-  if (VLOG_IS_ON(compiler)) {
-    LOG(INFO) << "Creating header for " << oat_filenames_[oat_index];
-    size_t idx = 0;
-    for (const ImageSection& section : sections) {
-      LOG(INFO) << static_cast<ImageHeader::ImageSections>(idx) << " " << section;
-      ++idx;
-    }
-    LOG(INFO) << "Methods: clean=" << clean_methods_ << " dirty=" << dirty_methods_;
-    LOG(INFO) << "Image roots address=" << std::hex << image_info.image_roots_address_ << std::dec;
-    LOG(INFO) << "Image begin=" << std::hex << reinterpret_cast<uintptr_t>(global_image_begin_)
-              << " Image offset=" << image_info.image_offset_ << std::dec;
-    LOG(INFO) << "Oat file begin=" << std::hex << reinterpret_cast<uintptr_t>(oat_file_begin)
-              << " Oat data begin=" << reinterpret_cast<uintptr_t>(image_info.oat_data_begin_)
-              << " Oat data end=" << reinterpret_cast<uintptr_t>(oat_data_end)
-              << " Oat file end=" << reinterpret_cast<uintptr_t>(oat_file_end);
-  }
-  // Store boot image info for app image so that we can relocate.
-  uint32_t boot_image_begin = 0;
-  uint32_t boot_image_end = 0;
-  uint32_t boot_oat_begin = 0;
-  uint32_t boot_oat_end = 0;
-  gc::Heap* const heap = Runtime::Current()->GetHeap();
-  heap->GetBootImagesSize(&boot_image_begin, &boot_image_end, &boot_oat_begin, &boot_oat_end);
-
-  // Create the header, leave 0 for data size since we will fill this in as we are writing the
-  // image.
-  new (image_info.image_->Begin()) ImageHeader(PointerToLowMemUInt32(image_info.image_begin_),
-                                               image_end,
-                                               sections,
-                                               image_info.image_roots_address_,
-                                               image_info.oat_checksum_,
-                                               PointerToLowMemUInt32(oat_file_begin),
-                                               PointerToLowMemUInt32(image_info.oat_data_begin_),
-                                               PointerToLowMemUInt32(oat_data_end),
-                                               PointerToLowMemUInt32(oat_file_end),
-                                               boot_image_begin,
-                                               boot_image_end - boot_image_begin,
-                                               boot_oat_begin,
-                                               boot_oat_end - boot_oat_begin,
-                                               static_cast<uint32_t>(target_ptr_size_),
-                                               compile_pic_,
-                                               /*is_pic*/compile_app_image_,
-                                               image_storage_mode_,
-                                               /*data_size*/0u);
-}
-
-ArtMethod* ImageWriter::GetImageMethodAddress(ArtMethod* method) {
-  auto it = native_object_relocations_.find(method);
-  CHECK(it != native_object_relocations_.end()) << ArtMethod::PrettyMethod(method) << " @ "
-                                                << method;
-  size_t oat_index = GetOatIndex(method->GetDexCache());
-  ImageInfo& image_info = GetImageInfo(oat_index);
-  CHECK_GE(it->second.offset, image_info.image_end_) << "ArtMethods should be after Objects";
-  return reinterpret_cast<ArtMethod*>(image_info.image_begin_ + it->second.offset);
-}
-
-class ImageWriter::FixupRootVisitor : public RootVisitor {
- public:
-  explicit FixupRootVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {
-  }
-
-  void VisitRoots(mirror::Object*** roots ATTRIBUTE_UNUSED,
-                  size_t count ATTRIBUTE_UNUSED,
-                  const RootInfo& info ATTRIBUTE_UNUSED)
-      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
-    LOG(FATAL) << "Unsupported";
-  }
-
-  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
-                  const RootInfo& info ATTRIBUTE_UNUSED)
-      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
-    for (size_t i = 0; i < count; ++i) {
-      image_writer_->CopyReference(roots[i], roots[i]->AsMirrorPtr());
-    }
-  }
-
- private:
-  ImageWriter* const image_writer_;
-};
-
-void ImageWriter::CopyAndFixupImTable(ImTable* orig, ImTable* copy) {
-  for (size_t i = 0; i < ImTable::kSize; ++i) {
-    ArtMethod* method = orig->Get(i, target_ptr_size_);
-    void** address = reinterpret_cast<void**>(copy->AddressOfElement(i, target_ptr_size_));
-    CopyAndFixupPointer(address, method);
-    DCHECK_EQ(copy->Get(i, target_ptr_size_), NativeLocationInImage(method));
-  }
-}
-
-void ImageWriter::CopyAndFixupImtConflictTable(ImtConflictTable* orig, ImtConflictTable* copy) {
-  const size_t count = orig->NumEntries(target_ptr_size_);
-  for (size_t i = 0; i < count; ++i) {
-    ArtMethod* interface_method = orig->GetInterfaceMethod(i, target_ptr_size_);
-    ArtMethod* implementation_method = orig->GetImplementationMethod(i, target_ptr_size_);
-    CopyAndFixupPointer(copy->AddressOfInterfaceMethod(i, target_ptr_size_), interface_method);
-    CopyAndFixupPointer(copy->AddressOfImplementationMethod(i, target_ptr_size_),
-                        implementation_method);
-    DCHECK_EQ(copy->GetInterfaceMethod(i, target_ptr_size_),
-              NativeLocationInImage(interface_method));
-    DCHECK_EQ(copy->GetImplementationMethod(i, target_ptr_size_),
-              NativeLocationInImage(implementation_method));
-  }
-}
-
-void ImageWriter::CopyAndFixupNativeData(size_t oat_index) {
-  const ImageInfo& image_info = GetImageInfo(oat_index);
-  // Copy ArtFields and methods to their locations and update the array for convenience.
-  for (auto& pair : native_object_relocations_) {
-    NativeObjectRelocation& relocation = pair.second;
-    // Only work with fields and methods that are in the current oat file.
-    if (relocation.oat_index != oat_index) {
-      continue;
-    }
-    auto* dest = image_info.image_->Begin() + relocation.offset;
-    DCHECK_GE(dest, image_info.image_->Begin() + image_info.image_end_);
-    DCHECK(!IsInBootImage(pair.first));
-    switch (relocation.type) {
-      case kNativeObjectRelocationTypeArtField: {
-        memcpy(dest, pair.first, sizeof(ArtField));
-        CopyReference(
-            reinterpret_cast<ArtField*>(dest)->GetDeclaringClassAddressWithoutBarrier(),
-            reinterpret_cast<ArtField*>(pair.first)->GetDeclaringClass().Ptr());
-        break;
-      }
-      case kNativeObjectRelocationTypeRuntimeMethod:
-      case kNativeObjectRelocationTypeArtMethodClean:
-      case kNativeObjectRelocationTypeArtMethodDirty: {
-        CopyAndFixupMethod(reinterpret_cast<ArtMethod*>(pair.first),
-                           reinterpret_cast<ArtMethod*>(dest),
-                           image_info);
-        break;
-      }
-      // For arrays, copy just the header since the elements will get copied by their corresponding
-      // relocations.
-      case kNativeObjectRelocationTypeArtFieldArray: {
-        memcpy(dest, pair.first, LengthPrefixedArray<ArtField>::ComputeSize(0));
-        break;
-      }
-      case kNativeObjectRelocationTypeArtMethodArrayClean:
-      case kNativeObjectRelocationTypeArtMethodArrayDirty: {
-        size_t size = ArtMethod::Size(target_ptr_size_);
-        size_t alignment = ArtMethod::Alignment(target_ptr_size_);
-        memcpy(dest, pair.first, LengthPrefixedArray<ArtMethod>::ComputeSize(0, size, alignment));
-        // Clear padding to avoid non-deterministic data in the image (and placate valgrind).
-        reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(dest)->ClearPadding(size, alignment);
-        break;
-      }
-      case kNativeObjectRelocationTypeDexCacheArray:
-        // Nothing to copy here, everything is done in FixupDexCache().
-        break;
-      case kNativeObjectRelocationTypeIMTable: {
-        ImTable* orig_imt = reinterpret_cast<ImTable*>(pair.first);
-        ImTable* dest_imt = reinterpret_cast<ImTable*>(dest);
-        CopyAndFixupImTable(orig_imt, dest_imt);
-        break;
-      }
-      case kNativeObjectRelocationTypeIMTConflictTable: {
-        auto* orig_table = reinterpret_cast<ImtConflictTable*>(pair.first);
-        CopyAndFixupImtConflictTable(
-            orig_table,
-            new(dest)ImtConflictTable(orig_table->NumEntries(target_ptr_size_), target_ptr_size_));
-        break;
-      }
-    }
-  }
-  // Fixup the image method roots.
-  auto* image_header = reinterpret_cast<ImageHeader*>(image_info.image_->Begin());
-  for (size_t i = 0; i < ImageHeader::kImageMethodsCount; ++i) {
-    ArtMethod* method = image_methods_[i];
-    CHECK(method != nullptr);
-    if (!IsInBootImage(method)) {
-      method = NativeLocationInImage(method);
-    }
-    image_header->SetImageMethod(static_cast<ImageHeader::ImageMethod>(i), method);
-  }
-  FixupRootVisitor root_visitor(this);
-
-  // Write the intern table into the image.
-  if (image_info.intern_table_bytes_ > 0) {
-    const ImageSection& intern_table_section = image_header->GetInternedStringsSection();
-    InternTable* const intern_table = image_info.intern_table_.get();
-    uint8_t* const intern_table_memory_ptr =
-        image_info.image_->Begin() + intern_table_section.Offset();
-    const size_t intern_table_bytes = intern_table->WriteToMemory(intern_table_memory_ptr);
-    CHECK_EQ(intern_table_bytes, image_info.intern_table_bytes_);
-    // Fixup the pointers in the newly written intern table to contain image addresses.
-    InternTable temp_intern_table;
-    // Note that we require that ReadFromMemory does not make an internal copy of the elements so that
-    // the VisitRoots() will update the memory directly rather than the copies.
-    // This also relies on visit roots not doing any verification which could fail after we update
-    // the roots to be the image addresses.
-    temp_intern_table.AddTableFromMemory(intern_table_memory_ptr);
-    CHECK_EQ(temp_intern_table.Size(), intern_table->Size());
-    temp_intern_table.VisitRoots(&root_visitor, kVisitRootFlagAllRoots);
-  }
-  // Write the class table(s) into the image. class_table_bytes_ may be 0 if there are multiple
-  // class loaders. Writing multiple class tables into the image is currently unsupported.
-  if (image_info.class_table_bytes_ > 0u) {
-    const ImageSection& class_table_section = image_header->GetClassTableSection();
-    uint8_t* const class_table_memory_ptr =
-        image_info.image_->Begin() + class_table_section.Offset();
-    ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
-
-    ClassTable* table = image_info.class_table_.get();
-    CHECK(table != nullptr);
-    const size_t class_table_bytes = table->WriteToMemory(class_table_memory_ptr);
-    CHECK_EQ(class_table_bytes, image_info.class_table_bytes_);
-    // Fixup the pointers in the newly written class table to contain image addresses. See
-    // above comment for intern tables.
-    ClassTable temp_class_table;
-    temp_class_table.ReadFromMemory(class_table_memory_ptr);
-    CHECK_EQ(temp_class_table.NumReferencedZygoteClasses(),
-             table->NumReferencedNonZygoteClasses() + table->NumReferencedZygoteClasses());
-    UnbufferedRootVisitor visitor(&root_visitor, RootInfo(kRootUnknown));
-    temp_class_table.VisitRoots(visitor);
-  }
-}
-
-void ImageWriter::CopyAndFixupObjects() {
-  auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(obj != nullptr);
-    CopyAndFixupObject(obj);
-  };
-  Runtime::Current()->GetHeap()->VisitObjects(visitor);
-  // Fix up the object previously had hash codes.
-  for (const auto& hash_pair : saved_hashcode_map_) {
-    Object* obj = hash_pair.first;
-    DCHECK_EQ(obj->GetLockWord<kVerifyNone>(false).ReadBarrierState(), 0U);
-    obj->SetLockWord<kVerifyNone>(LockWord::FromHashCode(hash_pair.second, 0U), false);
-  }
-  saved_hashcode_map_.clear();
-}
-
-void ImageWriter::FixupPointerArray(mirror::Object* dst,
-                                    mirror::PointerArray* arr,
-                                    mirror::Class* klass,
-                                    Bin array_type) {
-  CHECK(klass->IsArrayClass());
-  CHECK(arr->IsIntArray() || arr->IsLongArray()) << klass->PrettyClass() << " " << arr;
-  // Fixup int and long pointers for the ArtMethod or ArtField arrays.
-  const size_t num_elements = arr->GetLength();
-  dst->SetClass(GetImageAddress(arr->GetClass()));
-  auto* dest_array = down_cast<mirror::PointerArray*>(dst);
-  for (size_t i = 0, count = num_elements; i < count; ++i) {
-    void* elem = arr->GetElementPtrSize<void*>(i, target_ptr_size_);
-    if (kIsDebugBuild && elem != nullptr && !IsInBootImage(elem)) {
-      auto it = native_object_relocations_.find(elem);
-      if (UNLIKELY(it == native_object_relocations_.end())) {
-        if (it->second.IsArtMethodRelocation()) {
-          auto* method = reinterpret_cast<ArtMethod*>(elem);
-          LOG(FATAL) << "No relocation entry for ArtMethod " << method->PrettyMethod() << " @ "
-                     << method << " idx=" << i << "/" << num_elements << " with declaring class "
-                     << Class::PrettyClass(method->GetDeclaringClass());
-        } else {
-          CHECK_EQ(array_type, kBinArtField);
-          auto* field = reinterpret_cast<ArtField*>(elem);
-          LOG(FATAL) << "No relocation entry for ArtField " << field->PrettyField() << " @ "
-              << field << " idx=" << i << "/" << num_elements << " with declaring class "
-              << Class::PrettyClass(field->GetDeclaringClass());
-        }
-        UNREACHABLE();
-      }
-    }
-    CopyAndFixupPointer(dest_array->ElementAddress(i, target_ptr_size_), elem);
-  }
-}
-
-void ImageWriter::CopyAndFixupObject(Object* obj) {
-  if (IsInBootImage(obj)) {
-    return;
-  }
-  size_t offset = GetImageOffset(obj);
-  size_t oat_index = GetOatIndex(obj);
-  ImageInfo& image_info = GetImageInfo(oat_index);
-  auto* dst = reinterpret_cast<Object*>(image_info.image_->Begin() + offset);
-  DCHECK_LT(offset, image_info.image_end_);
-  const auto* src = reinterpret_cast<const uint8_t*>(obj);
-
-  image_info.image_bitmap_->Set(dst);  // Mark the obj as live.
-
-  const size_t n = obj->SizeOf();
-  DCHECK_LE(offset + n, image_info.image_->Size());
-  memcpy(dst, src, n);
-
-  // Write in a hash code of objects which have inflated monitors or a hash code in their monitor
-  // word.
-  const auto it = saved_hashcode_map_.find(obj);
-  dst->SetLockWord(it != saved_hashcode_map_.end() ?
-      LockWord::FromHashCode(it->second, 0u) : LockWord::Default(), false);
-  if (kUseBakerReadBarrier && gc::collector::ConcurrentCopying::kGrayDirtyImmuneObjects) {
-    // Treat all of the objects in the image as marked to avoid unnecessary dirty pages. This is
-    // safe since we mark all of the objects that may reference non immune objects as gray.
-    CHECK(dst->AtomicSetMarkBit(0, 1));
-  }
-  FixupObject(obj, dst);
-}
-
-// Rewrite all the references in the copied object to point to their image address equivalent
-class ImageWriter::FixupVisitor {
- public:
-  FixupVisitor(ImageWriter* image_writer, Object* copy) : image_writer_(image_writer), copy_(copy) {
-  }
-
-  // Ignore class roots since we don't have a way to map them to the destination. These are handled
-  // with other logic.
-  void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED)
-      const {}
-  void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
-
-
-  void operator()(ObjPtr<Object> obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
-      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
-    ObjPtr<Object> ref = obj->GetFieldObject<Object, kVerifyNone>(offset);
-    // Copy the reference and record the fixup if necessary.
-    image_writer_->CopyReference(
-        copy_->GetFieldObjectReferenceAddr<kVerifyNone>(offset),
-        ref.Ptr());
-  }
-
-  // java.lang.ref.Reference visitor.
-  void operator()(ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
-                  ObjPtr<mirror::Reference> ref) const
-      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
-    operator()(ref, mirror::Reference::ReferentOffset(), /* is_static */ false);
-  }
-
- protected:
-  ImageWriter* const image_writer_;
-  mirror::Object* const copy_;
-};
-
-class ImageWriter::FixupClassVisitor FINAL : public FixupVisitor {
- public:
-  FixupClassVisitor(ImageWriter* image_writer, Object* copy) : FixupVisitor(image_writer, copy) {
-  }
-
-  void operator()(ObjPtr<Object> obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
-      REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
-    DCHECK(obj->IsClass());
-    FixupVisitor::operator()(obj, offset, /*is_static*/false);
-  }
-
-  void operator()(ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
-                  ObjPtr<mirror::Reference> ref ATTRIBUTE_UNUSED) const
-      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
-    LOG(FATAL) << "Reference not expected here.";
-  }
-};
-
-uintptr_t ImageWriter::NativeOffsetInImage(void* obj) {
-  DCHECK(obj != nullptr);
-  DCHECK(!IsInBootImage(obj));
-  auto it = native_object_relocations_.find(obj);
-  CHECK(it != native_object_relocations_.end()) << obj << " spaces "
-      << Runtime::Current()->GetHeap()->DumpSpaces();
-  const NativeObjectRelocation& relocation = it->second;
-  return relocation.offset;
-}
-
-template <typename T>
-std::string PrettyPrint(T* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
-  std::ostringstream oss;
-  oss << ptr;
-  return oss.str();
-}
-
-template <>
-std::string PrettyPrint(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
-  return ArtMethod::PrettyMethod(method);
-}
-
-template <typename T>
-T* ImageWriter::NativeLocationInImage(T* obj) {
-  if (obj == nullptr || IsInBootImage(obj)) {
-    return obj;
-  } else {
-    auto it = native_object_relocations_.find(obj);
-    CHECK(it != native_object_relocations_.end()) << obj << " " << PrettyPrint(obj)
-        << " spaces " << Runtime::Current()->GetHeap()->DumpSpaces();
-    const NativeObjectRelocation& relocation = it->second;
-    ImageInfo& image_info = GetImageInfo(relocation.oat_index);
-    return reinterpret_cast<T*>(image_info.image_begin_ + relocation.offset);
-  }
-}
-
-template <typename T>
-T* ImageWriter::NativeCopyLocation(T* obj, mirror::DexCache* dex_cache) {
-  if (obj == nullptr || IsInBootImage(obj)) {
-    return obj;
-  } else {
-    size_t oat_index = GetOatIndexForDexCache(dex_cache);
-    ImageInfo& image_info = GetImageInfo(oat_index);
-    return reinterpret_cast<T*>(image_info.image_->Begin() + NativeOffsetInImage(obj));
-  }
-}
-
-class ImageWriter::NativeLocationVisitor {
- public:
-  explicit NativeLocationVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {}
-
-  template <typename T>
-  T* operator()(T* ptr, void** dest_addr = nullptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (dest_addr != nullptr) {
-      image_writer_->CopyAndFixupPointer(dest_addr, ptr);
-    }
-    return image_writer_->NativeLocationInImage(ptr);
-  }
-
- private:
-  ImageWriter* const image_writer_;
-};
-
-void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) {
-  orig->FixupNativePointers(copy, target_ptr_size_, NativeLocationVisitor(this));
-  FixupClassVisitor visitor(this, copy);
-  ObjPtr<mirror::Object>(orig)->VisitReferences(visitor, visitor);
-
-  // Remove the clinitThreadId. This is required for image determinism.
-  copy->SetClinitThreadId(static_cast<pid_t>(0));
-}
-
-void ImageWriter::FixupObject(Object* orig, Object* copy) {
-  DCHECK(orig != nullptr);
-  DCHECK(copy != nullptr);
-  if (kUseBakerReadBarrier) {
-    orig->AssertReadBarrierState();
-  }
-  auto* klass = orig->GetClass();
-  if (klass->IsIntArrayClass() || klass->IsLongArrayClass()) {
-    // Is this a native pointer array?
-    auto it = pointer_arrays_.find(down_cast<mirror::PointerArray*>(orig));
-    if (it != pointer_arrays_.end()) {
-      // Should only need to fixup every pointer array exactly once.
-      FixupPointerArray(copy, down_cast<mirror::PointerArray*>(orig), klass, it->second);
-      pointer_arrays_.erase(it);
-      return;
-    }
-  }
-  if (orig->IsClass()) {
-    FixupClass(orig->AsClass<kVerifyNone>(), down_cast<mirror::Class*>(copy));
-  } else {
-    if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
-      // Need to go update the ArtMethod.
-      auto* dest = down_cast<mirror::Executable*>(copy);
-      auto* src = down_cast<mirror::Executable*>(orig);
-      ArtMethod* src_method = src->GetArtMethod();
-      dest->SetArtMethod(GetImageMethodAddress(src_method));
-    } else if (!klass->IsArrayClass()) {
-      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-      if (klass == class_linker->GetClassRoot(ClassLinker::kJavaLangDexCache)) {
-        FixupDexCache(down_cast<mirror::DexCache*>(orig), down_cast<mirror::DexCache*>(copy));
-      } else if (klass->IsClassLoaderClass()) {
-        mirror::ClassLoader* copy_loader = down_cast<mirror::ClassLoader*>(copy);
-        // If src is a ClassLoader, set the class table to null so that it gets recreated by the
-        // ClassLoader.
-        copy_loader->SetClassTable(nullptr);
-        // Also set allocator to null to be safe. The allocator is created when we create the class
-        // table. We also never expect to unload things in the image since they are held live as
-        // roots.
-        copy_loader->SetAllocator(nullptr);
-      }
-    }
-    FixupVisitor visitor(this, copy);
-    orig->VisitReferences(visitor, visitor);
-  }
-}
-
-class ImageWriter::ImageAddressVisitorForDexCacheArray {
- public:
-  explicit ImageAddressVisitorForDexCacheArray(ImageWriter* image_writer)
-      : image_writer_(image_writer) {}
-
-  template <typename T>
-  T* operator()(T* ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
-    return image_writer_->GetImageAddress(ptr);
-  }
-
- private:
-  ImageWriter* const image_writer_;
-};
-
-void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache,
-                                mirror::DexCache* copy_dex_cache) {
-  ImageAddressVisitorForDexCacheArray fixup_visitor(this);
-  // Though the DexCache array fields are usually treated as native pointers, we set the full
-  // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is
-  // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e.
-  //     static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))).
-  mirror::StringDexCacheType* orig_strings = orig_dex_cache->GetStrings();
-  if (orig_strings != nullptr) {
-    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::StringsOffset(),
-                                               NativeLocationInImage(orig_strings),
-                                               PointerSize::k64);
-    orig_dex_cache->FixupStrings(NativeCopyLocation(orig_strings, orig_dex_cache), fixup_visitor);
-  }
-  mirror::TypeDexCacheType* orig_types = orig_dex_cache->GetResolvedTypes();
-  if (orig_types != nullptr) {
-    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedTypesOffset(),
-                                               NativeLocationInImage(orig_types),
-                                               PointerSize::k64);
-    orig_dex_cache->FixupResolvedTypes(NativeCopyLocation(orig_types, orig_dex_cache),
-                                       fixup_visitor);
-  }
-  mirror::MethodDexCacheType* orig_methods = orig_dex_cache->GetResolvedMethods();
-  if (orig_methods != nullptr) {
-    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedMethodsOffset(),
-                                               NativeLocationInImage(orig_methods),
-                                               PointerSize::k64);
-    mirror::MethodDexCacheType* copy_methods = NativeCopyLocation(orig_methods, orig_dex_cache);
-    for (size_t i = 0, num = orig_dex_cache->NumResolvedMethods(); i != num; ++i) {
-      mirror::MethodDexCachePair orig_pair =
-          mirror::DexCache::GetNativePairPtrSize(orig_methods, i, target_ptr_size_);
-      // NativeLocationInImage also handles runtime methods since these have relocation info.
-      mirror::MethodDexCachePair copy_pair(NativeLocationInImage(orig_pair.object),
-                                           orig_pair.index);
-      mirror::DexCache::SetNativePairPtrSize(copy_methods, i, copy_pair, target_ptr_size_);
-    }
-  }
-  mirror::FieldDexCacheType* orig_fields = orig_dex_cache->GetResolvedFields();
-  if (orig_fields != nullptr) {
-    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedFieldsOffset(),
-                                               NativeLocationInImage(orig_fields),
-                                               PointerSize::k64);
-    mirror::FieldDexCacheType* copy_fields = NativeCopyLocation(orig_fields, orig_dex_cache);
-    for (size_t i = 0, num = orig_dex_cache->NumResolvedFields(); i != num; ++i) {
-      mirror::FieldDexCachePair orig =
-          mirror::DexCache::GetNativePairPtrSize(orig_fields, i, target_ptr_size_);
-      mirror::FieldDexCachePair copy = orig;
-      copy.object = NativeLocationInImage(orig.object);
-      mirror::DexCache::SetNativePairPtrSize(copy_fields, i, copy, target_ptr_size_);
-    }
-  }
-  mirror::MethodTypeDexCacheType* orig_method_types = orig_dex_cache->GetResolvedMethodTypes();
-  if (orig_method_types != nullptr) {
-    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedMethodTypesOffset(),
-                                               NativeLocationInImage(orig_method_types),
-                                               PointerSize::k64);
-    orig_dex_cache->FixupResolvedMethodTypes(NativeCopyLocation(orig_method_types, orig_dex_cache),
-                                             fixup_visitor);
-  }
-  GcRoot<mirror::CallSite>* orig_call_sites = orig_dex_cache->GetResolvedCallSites();
-  if (orig_call_sites != nullptr) {
-    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedCallSitesOffset(),
-                                               NativeLocationInImage(orig_call_sites),
-                                               PointerSize::k64);
-    orig_dex_cache->FixupResolvedCallSites(NativeCopyLocation(orig_call_sites, orig_dex_cache),
-                                           fixup_visitor);
-  }
-
-  // Remove the DexFile pointers. They will be fixed up when the runtime loads the oat file. Leaving
-  // compiler pointers in here will make the output non-deterministic.
-  copy_dex_cache->SetDexFile(nullptr);
-}
-
-const uint8_t* ImageWriter::GetOatAddress(OatAddress type) const {
-  DCHECK_LT(type, kOatAddressCount);
-  // If we are compiling an app image, we need to use the stubs of the boot image.
-  if (compile_app_image_) {
-    // Use the current image pointers.
-    const std::vector<gc::space::ImageSpace*>& image_spaces =
-        Runtime::Current()->GetHeap()->GetBootImageSpaces();
-    DCHECK(!image_spaces.empty());
-    const OatFile* oat_file = image_spaces[0]->GetOatFile();
-    CHECK(oat_file != nullptr);
-    const OatHeader& header = oat_file->GetOatHeader();
-    switch (type) {
-      // TODO: We could maybe clean this up if we stored them in an array in the oat header.
-      case kOatAddressQuickGenericJNITrampoline:
-        return static_cast<const uint8_t*>(header.GetQuickGenericJniTrampoline());
-      case kOatAddressInterpreterToInterpreterBridge:
-        return static_cast<const uint8_t*>(header.GetInterpreterToInterpreterBridge());
-      case kOatAddressInterpreterToCompiledCodeBridge:
-        return static_cast<const uint8_t*>(header.GetInterpreterToCompiledCodeBridge());
-      case kOatAddressJNIDlsymLookup:
-        return static_cast<const uint8_t*>(header.GetJniDlsymLookup());
-      case kOatAddressQuickIMTConflictTrampoline:
-        return static_cast<const uint8_t*>(header.GetQuickImtConflictTrampoline());
-      case kOatAddressQuickResolutionTrampoline:
-        return static_cast<const uint8_t*>(header.GetQuickResolutionTrampoline());
-      case kOatAddressQuickToInterpreterBridge:
-        return static_cast<const uint8_t*>(header.GetQuickToInterpreterBridge());
-      default:
-        UNREACHABLE();
-    }
-  }
-  const ImageInfo& primary_image_info = GetImageInfo(0);
-  return GetOatAddressForOffset(primary_image_info.oat_address_offsets_[type], primary_image_info);
-}
-
-const uint8_t* ImageWriter::GetQuickCode(ArtMethod* method,
-                                         const ImageInfo& image_info,
-                                         bool* quick_is_interpreted) {
-  DCHECK(!method->IsResolutionMethod()) << method->PrettyMethod();
-  DCHECK_NE(method, Runtime::Current()->GetImtConflictMethod()) << method->PrettyMethod();
-  DCHECK(!method->IsImtUnimplementedMethod()) << method->PrettyMethod();
-  DCHECK(method->IsInvokable()) << method->PrettyMethod();
-  DCHECK(!IsInBootImage(method)) << method->PrettyMethod();
-
-  // Use original code if it exists. Otherwise, set the code pointer to the resolution
-  // trampoline.
-
-  // Quick entrypoint:
-  const void* quick_oat_entry_point =
-      method->GetEntryPointFromQuickCompiledCodePtrSize(target_ptr_size_);
-  const uint8_t* quick_code;
-
-  if (UNLIKELY(IsInBootImage(method->GetDeclaringClass()))) {
-    DCHECK(method->IsCopied());
-    // If the code is not in the oat file corresponding to this image (e.g. default methods)
-    quick_code = reinterpret_cast<const uint8_t*>(quick_oat_entry_point);
-  } else {
-    uint32_t quick_oat_code_offset = PointerToLowMemUInt32(quick_oat_entry_point);
-    quick_code = GetOatAddressForOffset(quick_oat_code_offset, image_info);
-  }
-
-  *quick_is_interpreted = false;
-  if (quick_code != nullptr && (!method->IsStatic() || method->IsConstructor() ||
-      method->GetDeclaringClass()->IsInitialized())) {
-    // We have code for a non-static or initialized method, just use the code.
-  } else if (quick_code == nullptr && method->IsNative() &&
-      (!method->IsStatic() || method->GetDeclaringClass()->IsInitialized())) {
-    // Non-static or initialized native method missing compiled code, use generic JNI version.
-    quick_code = GetOatAddress(kOatAddressQuickGenericJNITrampoline);
-  } else if (quick_code == nullptr && !method->IsNative()) {
-    // We don't have code at all for a non-native method, use the interpreter.
-    quick_code = GetOatAddress(kOatAddressQuickToInterpreterBridge);
-    *quick_is_interpreted = true;
-  } else {
-    CHECK(!method->GetDeclaringClass()->IsInitialized());
-    // We have code for a static method, but need to go through the resolution stub for class
-    // initialization.
-    quick_code = GetOatAddress(kOatAddressQuickResolutionTrampoline);
-  }
-  if (!IsInBootOatFile(quick_code)) {
-    // DCHECK_GE(quick_code, oat_data_begin_);
-  }
-  return quick_code;
-}
-
-void ImageWriter::CopyAndFixupMethod(ArtMethod* orig,
-                                     ArtMethod* copy,
-                                     const ImageInfo& image_info) {
-  if (orig->IsAbstract()) {
-    // Ignore the single-implementation info for abstract method.
-    // Do this on orig instead of copy, otherwise there is a crash due to methods
-    // are copied before classes.
-    // TODO: handle fixup of single-implementation method for abstract method.
-    orig->SetHasSingleImplementation(false);
-    orig->SetSingleImplementation(
-        nullptr, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
-  }
-
-  memcpy(copy, orig, ArtMethod::Size(target_ptr_size_));
-
-  CopyReference(copy->GetDeclaringClassAddressWithoutBarrier(), orig->GetDeclaringClassUnchecked());
-
-  // OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
-  // oat_begin_
-
-  // The resolution method has a special trampoline to call.
-  Runtime* runtime = Runtime::Current();
-  if (orig->IsRuntimeMethod()) {
-    ImtConflictTable* orig_table = orig->GetImtConflictTable(target_ptr_size_);
-    if (orig_table != nullptr) {
-      // Special IMT conflict method, normal IMT conflict method or unimplemented IMT method.
-      copy->SetEntryPointFromQuickCompiledCodePtrSize(
-          GetOatAddress(kOatAddressQuickIMTConflictTrampoline), target_ptr_size_);
-      copy->SetImtConflictTable(NativeLocationInImage(orig_table), target_ptr_size_);
-    } else if (UNLIKELY(orig == runtime->GetResolutionMethod())) {
-      copy->SetEntryPointFromQuickCompiledCodePtrSize(
-          GetOatAddress(kOatAddressQuickResolutionTrampoline), target_ptr_size_);
-    } else {
-      bool found_one = false;
-      for (size_t i = 0; i < static_cast<size_t>(CalleeSaveType::kLastCalleeSaveType); ++i) {
-        auto idx = static_cast<CalleeSaveType>(i);
-        if (runtime->HasCalleeSaveMethod(idx) && runtime->GetCalleeSaveMethod(idx) == orig) {
-          found_one = true;
-          break;
-        }
-      }
-      CHECK(found_one) << "Expected to find callee save method but got " << orig->PrettyMethod();
-      CHECK(copy->IsRuntimeMethod());
-    }
-  } else {
-    // We assume all methods have code. If they don't currently then we set them to the use the
-    // resolution trampoline. Abstract methods never have code and so we need to make sure their
-    // use results in an AbstractMethodError. We use the interpreter to achieve this.
-    if (UNLIKELY(!orig->IsInvokable())) {
-      copy->SetEntryPointFromQuickCompiledCodePtrSize(
-          GetOatAddress(kOatAddressQuickToInterpreterBridge), target_ptr_size_);
-    } else {
-      bool quick_is_interpreted;
-      const uint8_t* quick_code = GetQuickCode(orig, image_info, &quick_is_interpreted);
-      copy->SetEntryPointFromQuickCompiledCodePtrSize(quick_code, target_ptr_size_);
-
-      // JNI entrypoint:
-      if (orig->IsNative()) {
-        // The native method's pointer is set to a stub to lookup via dlsym.
-        // Note this is not the code_ pointer, that is handled above.
-        copy->SetEntryPointFromJniPtrSize(
-            GetOatAddress(kOatAddressJNIDlsymLookup), target_ptr_size_);
-      }
-    }
-  }
-}
-
-size_t ImageWriter::GetBinSizeSum(ImageWriter::ImageInfo& image_info, ImageWriter::Bin up_to) const {
-  DCHECK_LE(up_to, kBinSize);
-  return std::accumulate(&image_info.bin_slot_sizes_[0],
-                         &image_info.bin_slot_sizes_[up_to],
-                         /*init*/0);
-}
-
-ImageWriter::BinSlot::BinSlot(uint32_t lockword) : lockword_(lockword) {
-  // These values may need to get updated if more bins are added to the enum Bin
-  static_assert(kBinBits == 3, "wrong number of bin bits");
-  static_assert(kBinShift == 27, "wrong number of shift");
-  static_assert(sizeof(BinSlot) == sizeof(LockWord), "BinSlot/LockWord must have equal sizes");
-
-  DCHECK_LT(GetBin(), kBinSize);
-  DCHECK_ALIGNED(GetIndex(), kObjectAlignment);
-}
-
-ImageWriter::BinSlot::BinSlot(Bin bin, uint32_t index)
-    : BinSlot(index | (static_cast<uint32_t>(bin) << kBinShift)) {
-  DCHECK_EQ(index, GetIndex());
-}
-
-ImageWriter::Bin ImageWriter::BinSlot::GetBin() const {
-  return static_cast<Bin>((lockword_ & kBinMask) >> kBinShift);
-}
-
-uint32_t ImageWriter::BinSlot::GetIndex() const {
-  return lockword_ & ~kBinMask;
-}
-
-ImageWriter::Bin ImageWriter::BinTypeForNativeRelocationType(NativeObjectRelocationType type) {
-  switch (type) {
-    case kNativeObjectRelocationTypeArtField:
-    case kNativeObjectRelocationTypeArtFieldArray:
-      return kBinArtField;
-    case kNativeObjectRelocationTypeArtMethodClean:
-    case kNativeObjectRelocationTypeArtMethodArrayClean:
-      return kBinArtMethodClean;
-    case kNativeObjectRelocationTypeArtMethodDirty:
-    case kNativeObjectRelocationTypeArtMethodArrayDirty:
-      return kBinArtMethodDirty;
-    case kNativeObjectRelocationTypeDexCacheArray:
-      return kBinDexCacheArray;
-    case kNativeObjectRelocationTypeRuntimeMethod:
-      return kBinRuntimeMethod;
-    case kNativeObjectRelocationTypeIMTable:
-      return kBinImTable;
-    case kNativeObjectRelocationTypeIMTConflictTable:
-      return kBinIMTConflictTable;
-  }
-  UNREACHABLE();
-}
-
-size_t ImageWriter::GetOatIndex(mirror::Object* obj) const {
-  if (!IsMultiImage()) {
-    return GetDefaultOatIndex();
-  }
-  auto it = oat_index_map_.find(obj);
-  DCHECK(it != oat_index_map_.end()) << obj;
-  return it->second;
-}
-
-size_t ImageWriter::GetOatIndexForDexFile(const DexFile* dex_file) const {
-  if (!IsMultiImage()) {
-    return GetDefaultOatIndex();
-  }
-  auto it = dex_file_oat_index_map_.find(dex_file);
-  DCHECK(it != dex_file_oat_index_map_.end()) << dex_file->GetLocation();
-  return it->second;
-}
-
-size_t ImageWriter::GetOatIndexForDexCache(ObjPtr<mirror::DexCache> dex_cache) const {
-  return (dex_cache == nullptr)
-      ? GetDefaultOatIndex()
-      : GetOatIndexForDexFile(dex_cache->GetDexFile());
-}
-
-void ImageWriter::UpdateOatFileLayout(size_t oat_index,
-                                      size_t oat_loaded_size,
-                                      size_t oat_data_offset,
-                                      size_t oat_data_size) {
-  const uint8_t* images_end = image_infos_.back().image_begin_ + image_infos_.back().image_size_;
-  for (const ImageInfo& info : image_infos_) {
-    DCHECK_LE(info.image_begin_ + info.image_size_, images_end);
-  }
-  DCHECK(images_end != nullptr);  // Image space must be ready.
-
-  ImageInfo& cur_image_info = GetImageInfo(oat_index);
-  cur_image_info.oat_file_begin_ = images_end + cur_image_info.oat_offset_;
-  cur_image_info.oat_loaded_size_ = oat_loaded_size;
-  cur_image_info.oat_data_begin_ = cur_image_info.oat_file_begin_ + oat_data_offset;
-  cur_image_info.oat_size_ = oat_data_size;
-
-  if (compile_app_image_) {
-    CHECK_EQ(oat_filenames_.size(), 1u) << "App image should have no next image.";
-    return;
-  }
-
-  // Update the oat_offset of the next image info.
-  if (oat_index + 1u != oat_filenames_.size()) {
-    // There is a following one.
-    ImageInfo& next_image_info = GetImageInfo(oat_index + 1u);
-    next_image_info.oat_offset_ = cur_image_info.oat_offset_ + oat_loaded_size;
-  }
-}
-
-void ImageWriter::UpdateOatFileHeader(size_t oat_index, const OatHeader& oat_header) {
-  ImageInfo& cur_image_info = GetImageInfo(oat_index);
-  cur_image_info.oat_checksum_ = oat_header.GetChecksum();
-
-  if (oat_index == GetDefaultOatIndex()) {
-    // Primary oat file, read the trampolines.
-    cur_image_info.oat_address_offsets_[kOatAddressInterpreterToInterpreterBridge] =
-        oat_header.GetInterpreterToInterpreterBridgeOffset();
-    cur_image_info.oat_address_offsets_[kOatAddressInterpreterToCompiledCodeBridge] =
-        oat_header.GetInterpreterToCompiledCodeBridgeOffset();
-    cur_image_info.oat_address_offsets_[kOatAddressJNIDlsymLookup] =
-        oat_header.GetJniDlsymLookupOffset();
-    cur_image_info.oat_address_offsets_[kOatAddressQuickGenericJNITrampoline] =
-        oat_header.GetQuickGenericJniTrampolineOffset();
-    cur_image_info.oat_address_offsets_[kOatAddressQuickIMTConflictTrampoline] =
-        oat_header.GetQuickImtConflictTrampolineOffset();
-    cur_image_info.oat_address_offsets_[kOatAddressQuickResolutionTrampoline] =
-        oat_header.GetQuickResolutionTrampolineOffset();
-    cur_image_info.oat_address_offsets_[kOatAddressQuickToInterpreterBridge] =
-        oat_header.GetQuickToInterpreterBridgeOffset();
-  }
-}
-
-ImageWriter::ImageWriter(
-    const CompilerDriver& compiler_driver,
-    uintptr_t image_begin,
-    bool compile_pic,
-    bool compile_app_image,
-    ImageHeader::StorageMode image_storage_mode,
-    const std::vector<const char*>& oat_filenames,
-    const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map,
-    const std::unordered_set<std::string>* dirty_image_objects)
-    : compiler_driver_(compiler_driver),
-      global_image_begin_(reinterpret_cast<uint8_t*>(image_begin)),
-      image_objects_offset_begin_(0),
-      compile_pic_(compile_pic),
-      compile_app_image_(compile_app_image),
-      target_ptr_size_(InstructionSetPointerSize(compiler_driver_.GetInstructionSet())),
-      image_infos_(oat_filenames.size()),
-      dirty_methods_(0u),
-      clean_methods_(0u),
-      image_storage_mode_(image_storage_mode),
-      oat_filenames_(oat_filenames),
-      dex_file_oat_index_map_(dex_file_oat_index_map),
-      dirty_image_objects_(dirty_image_objects) {
-  CHECK_NE(image_begin, 0U);
-  std::fill_n(image_methods_, arraysize(image_methods_), nullptr);
-  CHECK_EQ(compile_app_image, !Runtime::Current()->GetHeap()->GetBootImageSpaces().empty())
-      << "Compiling a boot image should occur iff there are no boot image spaces loaded";
-}
-
-ImageWriter::ImageInfo::ImageInfo()
-    : intern_table_(new InternTable),
-      class_table_(new ClassTable) {}
-
-void ImageWriter::CopyReference(mirror::HeapReference<mirror::Object>* dest,
-                                ObjPtr<mirror::Object> src) {
-  dest->Assign(GetImageAddress(src.Ptr()));
-}
-
-void ImageWriter::CopyReference(mirror::CompressedReference<mirror::Object>* dest,
-                                ObjPtr<mirror::Object> src) {
-  dest->Assign(GetImageAddress(src.Ptr()));
-}
-
-void ImageWriter::CopyAndFixupPointer(void** target, void* value) {
-  void* new_value = value;
-  if (value != nullptr && !IsInBootImage(value)) {
-    auto it = native_object_relocations_.find(value);
-    CHECK(it != native_object_relocations_.end()) << value;
-    const NativeObjectRelocation& relocation = it->second;
-    ImageInfo& image_info = GetImageInfo(relocation.oat_index);
-    new_value = reinterpret_cast<void*>(image_info.image_begin_ + relocation.offset);
-  }
-  if (target_ptr_size_ == PointerSize::k32) {
-    *reinterpret_cast<uint32_t*>(target) = PointerToLowMemUInt32(new_value);
-  } else {
-    *reinterpret_cast<uint64_t*>(target) = reinterpret_cast<uintptr_t>(new_value);
-  }
-}
-
-
-}  // namespace art
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
deleted file mode 100644
index 2fc394e..0000000
--- a/compiler/image_writer.h
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * Copyright (C) 2011 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_COMPILER_IMAGE_WRITER_H_
-#define ART_COMPILER_IMAGE_WRITER_H_
-
-#include <stdint.h>
-#include "base/memory_tool.h"
-
-#include <cstddef>
-#include <memory>
-#include <ostream>
-#include <set>
-#include <stack>
-#include <string>
-
-#include "art_method.h"
-#include "base/bit_utils.h"
-#include "base/dchecked_vector.h"
-#include "base/enums.h"
-#include "base/length_prefixed_array.h"
-#include "base/macros.h"
-#include "class_table.h"
-#include "driver/compiler_driver.h"
-#include "image.h"
-#include "intern_table.h"
-#include "lock_word.h"
-#include "mem_map.h"
-#include "mirror/dex_cache.h"
-#include "oat_file.h"
-#include "obj_ptr.h"
-#include "os.h"
-#include "safe_map.h"
-#include "utils.h"
-
-namespace art {
-namespace gc {
-namespace accounting {
-template <size_t kAlignment> class SpaceBitmap;
-typedef SpaceBitmap<kObjectAlignment> ContinuousSpaceBitmap;
-}  // namespace accounting
-namespace space {
-class ImageSpace;
-}  // namespace space
-}  // namespace gc
-
-namespace mirror {
-class ClassLoader;
-}  // namespace mirror
-
-class ClassLoaderVisitor;
-class ImtConflictTable;
-
-static constexpr int kInvalidFd = -1;
-
-// Write a Space built during compilation for use during execution.
-class ImageWriter FINAL {
- public:
-  ImageWriter(const CompilerDriver& compiler_driver,
-              uintptr_t image_begin,
-              bool compile_pic,
-              bool compile_app_image,
-              ImageHeader::StorageMode image_storage_mode,
-              const std::vector<const char*>& oat_filenames,
-              const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map,
-              const std::unordered_set<std::string>* dirty_image_objects);
-
-  bool PrepareImageAddressSpace();
-
-  bool IsImageAddressSpaceReady() const {
-    DCHECK(!image_infos_.empty());
-    for (const ImageInfo& image_info : image_infos_) {
-      if (image_info.image_roots_address_ == 0u) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  ObjPtr<mirror::ClassLoader> GetClassLoader() {
-    CHECK_EQ(class_loaders_.size(), compile_app_image_ ? 1u : 0u);
-    return compile_app_image_ ? *class_loaders_.begin() : nullptr;
-  }
-
-  template <typename T>
-  T* GetImageAddress(T* object) const REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (object == nullptr || IsInBootImage(object)) {
-      return object;
-    } else {
-      size_t oat_index = GetOatIndex(object);
-      const ImageInfo& image_info = GetImageInfo(oat_index);
-      return reinterpret_cast<T*>(image_info.image_begin_ + GetImageOffset(object));
-    }
-  }
-
-  ArtMethod* GetImageMethodAddress(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  size_t GetOatFileOffset(size_t oat_index) const {
-    return GetImageInfo(oat_index).oat_offset_;
-  }
-
-  const uint8_t* GetOatFileBegin(size_t oat_index) const {
-    return GetImageInfo(oat_index).oat_file_begin_;
-  }
-
-  // If image_fd is not kInvalidFd, then we use that for the image file. Otherwise we open
-  // the names in image_filenames.
-  // If oat_fd is not kInvalidFd, then we use that for the oat file. Otherwise we open
-  // the names in oat_filenames.
-  bool Write(int image_fd,
-             const std::vector<const char*>& image_filenames,
-             const std::vector<const char*>& oat_filenames)
-      REQUIRES(!Locks::mutator_lock_);
-
-  uintptr_t GetOatDataBegin(size_t oat_index) {
-    return reinterpret_cast<uintptr_t>(GetImageInfo(oat_index).oat_data_begin_);
-  }
-
-  // Get the index of the oat file containing the dex file.
-  //
-  // This "oat_index" is used to retrieve information about the the memory layout
-  // of the oat file and its associated image file, needed for link-time patching
-  // of references to the image or across oat files.
-  size_t GetOatIndexForDexFile(const DexFile* dex_file) const;
-
-  // Get the index of the oat file containing the dex file served by the dex cache.
-  size_t GetOatIndexForDexCache(ObjPtr<mirror::DexCache> dex_cache) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Update the oat layout for the given oat file.
-  // This will make the oat_offset for the next oat file valid.
-  void UpdateOatFileLayout(size_t oat_index,
-                           size_t oat_loaded_size,
-                           size_t oat_data_offset,
-                           size_t oat_data_size);
-  // Update information about the oat header, i.e. checksum and trampoline offsets.
-  void UpdateOatFileHeader(size_t oat_index, const OatHeader& oat_header);
-
- private:
-  using WorkStack = std::stack<std::pair<mirror::Object*, size_t>>;
-
-  bool AllocMemory();
-
-  // Mark the objects defined in this space in the given live bitmap.
-  void RecordImageAllocations() REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Classify different kinds of bins that objects end up getting packed into during image writing.
-  // Ordered from dirtiest to cleanest (until ArtMethods).
-  enum Bin {
-    kBinKnownDirty,               // Known dirty objects from --dirty-image-objects list
-    kBinMiscDirty,                // Dex caches, object locks, etc...
-    kBinClassVerified,            // Class verified, but initializers haven't been run
-    // Unknown mix of clean/dirty:
-    kBinRegular,
-    kBinClassInitialized,         // Class initializers have been run
-    // All classes get their own bins since their fields often dirty
-    kBinClassInitializedFinalStatics,  // Class initializers have been run, no non-final statics
-    // Likely-clean:
-    kBinString,                        // [String] Almost always immutable (except for obj header).
-    // Add more bins here if we add more segregation code.
-    // Non mirror fields must be below.
-    // ArtFields should be always clean.
-    kBinArtField,
-    // If the class is initialized, then the ArtMethods are probably clean.
-    kBinArtMethodClean,
-    // ArtMethods may be dirty if the class has native methods or a declaring class that isn't
-    // initialized.
-    kBinArtMethodDirty,
-    // IMT (clean)
-    kBinImTable,
-    // Conflict tables (clean).
-    kBinIMTConflictTable,
-    // Runtime methods (always clean, do not have a length prefix array).
-    kBinRuntimeMethod,
-    // Dex cache arrays have a special slot for PC-relative addressing. Since they are
-    // huge, and as such their dirtiness is not important for the clean/dirty separation,
-    // we arbitrarily keep them at the end of the native data.
-    kBinDexCacheArray,            // Arrays belonging to dex cache.
-    kBinSize,
-    // Number of bins which are for mirror objects.
-    kBinMirrorCount = kBinArtField,
-  };
-  friend std::ostream& operator<<(std::ostream& stream, const Bin& bin);
-
-  enum NativeObjectRelocationType {
-    kNativeObjectRelocationTypeArtField,
-    kNativeObjectRelocationTypeArtFieldArray,
-    kNativeObjectRelocationTypeArtMethodClean,
-    kNativeObjectRelocationTypeArtMethodArrayClean,
-    kNativeObjectRelocationTypeArtMethodDirty,
-    kNativeObjectRelocationTypeArtMethodArrayDirty,
-    kNativeObjectRelocationTypeRuntimeMethod,
-    kNativeObjectRelocationTypeIMTable,
-    kNativeObjectRelocationTypeIMTConflictTable,
-    kNativeObjectRelocationTypeDexCacheArray,
-  };
-  friend std::ostream& operator<<(std::ostream& stream, const NativeObjectRelocationType& type);
-
-  enum OatAddress {
-    kOatAddressInterpreterToInterpreterBridge,
-    kOatAddressInterpreterToCompiledCodeBridge,
-    kOatAddressJNIDlsymLookup,
-    kOatAddressQuickGenericJNITrampoline,
-    kOatAddressQuickIMTConflictTrampoline,
-    kOatAddressQuickResolutionTrampoline,
-    kOatAddressQuickToInterpreterBridge,
-    // Number of elements in the enum.
-    kOatAddressCount,
-  };
-  friend std::ostream& operator<<(std::ostream& stream, const OatAddress& oat_address);
-
-  static constexpr size_t kBinBits = MinimumBitsToStore<uint32_t>(kBinMirrorCount - 1);
-  // uint32 = typeof(lockword_)
-  // Subtract read barrier bits since we want these to remain 0, or else it may result in DCHECK
-  // failures due to invalid read barrier bits during object field reads.
-  static const size_t kBinShift = BitSizeOf<uint32_t>() - kBinBits - LockWord::kGCStateSize;
-  // 111000.....0
-  static const size_t kBinMask = ((static_cast<size_t>(1) << kBinBits) - 1) << kBinShift;
-
-  // We use the lock word to store the bin # and bin index of the object in the image.
-  //
-  // The struct size must be exactly sizeof(LockWord), currently 32-bits, since this will end up
-  // stored in the lock word bit-for-bit when object forwarding addresses are being calculated.
-  struct BinSlot {
-    explicit BinSlot(uint32_t lockword);
-    BinSlot(Bin bin, uint32_t index);
-
-    // The bin an object belongs to, i.e. regular, class/verified, class/initialized, etc.
-    Bin GetBin() const;
-    // The offset in bytes from the beginning of the bin. Aligned to object size.
-    uint32_t GetIndex() const;
-    // Pack into a single uint32_t, for storing into a lock word.
-    uint32_t Uint32Value() const { return lockword_; }
-    // Comparison operator for map support
-    bool operator<(const BinSlot& other) const  { return lockword_ < other.lockword_; }
-
-  private:
-    // Must be the same size as LockWord, any larger and we would truncate the data.
-    const uint32_t lockword_;
-  };
-
-  struct ImageInfo {
-    ImageInfo();
-    ImageInfo(ImageInfo&&) = default;
-
-    // Create the image sections into the out sections variable, returns the size of the image
-    // excluding the bitmap.
-    size_t CreateImageSections(ImageSection* out_sections, bool app_image) const;
-
-    std::unique_ptr<MemMap> image_;  // Memory mapped for generating the image.
-
-    // Target begin of this image. Notes: It is not valid to write here, this is the address
-    // of the target image, not necessarily where image_ is mapped. The address is only valid
-    // after layouting (otherwise null).
-    uint8_t* image_begin_ = nullptr;
-
-    // Offset to the free space in image_, initially size of image header.
-    size_t image_end_ = RoundUp(sizeof(ImageHeader), kObjectAlignment);
-    uint32_t image_roots_address_ = 0;  // The image roots address in the image.
-    size_t image_offset_ = 0;  // Offset of this image from the start of the first image.
-
-    // Image size is the *address space* covered by this image. As the live bitmap is aligned
-    // to the page size, the live bitmap will cover more address space than necessary. But live
-    // bitmaps may not overlap, so an image has a "shadow," which is accounted for in the size.
-    // The next image may only start at image_begin_ + image_size_ (which is guaranteed to be
-    // page-aligned).
-    size_t image_size_ = 0;
-
-    // Oat data.
-    // Offset of the oat file for this image from start of oat files. This is
-    // valid when the previous oat file has been written.
-    size_t oat_offset_ = 0;
-    // Layout of the loaded ELF file containing the oat file, valid after UpdateOatFileLayout().
-    const uint8_t* oat_file_begin_ = nullptr;
-    size_t oat_loaded_size_ = 0;
-    const uint8_t* oat_data_begin_ = nullptr;
-    size_t oat_size_ = 0;  // Size of the corresponding oat data.
-    // The oat header checksum, valid after UpdateOatFileHeader().
-    uint32_t oat_checksum_ = 0u;
-
-    // Image bitmap which lets us know where the objects inside of the image reside.
-    std::unique_ptr<gc::accounting::ContinuousSpaceBitmap> image_bitmap_;
-
-    // The start offsets of the dex cache arrays.
-    SafeMap<const DexFile*, size_t> dex_cache_array_starts_;
-
-    // Offset from oat_data_begin_ to the stubs.
-    uint32_t oat_address_offsets_[kOatAddressCount] = {};
-
-    // Bin slot tracking for dirty object packing.
-    size_t bin_slot_sizes_[kBinSize] = {};  // Number of bytes in a bin.
-    size_t bin_slot_offsets_[kBinSize] = {};  // Number of bytes in previous bins.
-    size_t bin_slot_count_[kBinSize] = {};  // Number of objects in a bin.
-
-    // Cached size of the intern table for when we allocate memory.
-    size_t intern_table_bytes_ = 0;
-
-    // Number of image class table bytes.
-    size_t class_table_bytes_ = 0;
-
-    // Number of object fixup bytes.
-    size_t object_fixup_bytes_ = 0;
-
-    // Number of pointer fixup bytes.
-    size_t pointer_fixup_bytes_ = 0;
-
-    // Intern table associated with this image for serialization.
-    std::unique_ptr<InternTable> intern_table_;
-
-    // Class table associated with this image for serialization.
-    std::unique_ptr<ClassTable> class_table_;
-  };
-
-  // We use the lock word to store the offset of the object in the image.
-  void AssignImageOffset(mirror::Object* object, BinSlot bin_slot)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void SetImageOffset(mirror::Object* object, size_t offset)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  bool IsImageOffsetAssigned(mirror::Object* object) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  size_t GetImageOffset(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_);
-  void UpdateImageOffset(mirror::Object* obj, uintptr_t offset)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  void PrepareDexCacheArraySlots() REQUIRES_SHARED(Locks::mutator_lock_);
-  void AssignImageBinSlot(mirror::Object* object, size_t oat_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  mirror::Object* TryAssignBinSlot(WorkStack& work_stack, mirror::Object* obj, size_t oat_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void SetImageBinSlot(mirror::Object* object, BinSlot bin_slot)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  bool IsImageBinSlotAssigned(mirror::Object* object) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  BinSlot GetImageBinSlot(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_);
-
-  void AddDexCacheArrayRelocation(void* array, size_t offset, ObjPtr<mirror::DexCache> dex_cache)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void AddMethodPointerArray(mirror::PointerArray* arr) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  static void* GetImageAddressCallback(void* writer, mirror::Object* obj)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    return reinterpret_cast<ImageWriter*>(writer)->GetImageAddress(obj);
-  }
-
-  mirror::Object* GetLocalAddress(mirror::Object* object) const
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    size_t offset = GetImageOffset(object);
-    size_t oat_index = GetOatIndex(object);
-    const ImageInfo& image_info = GetImageInfo(oat_index);
-    uint8_t* dst = image_info.image_->Begin() + offset;
-    return reinterpret_cast<mirror::Object*>(dst);
-  }
-
-  // Returns the address in the boot image if we are compiling the app image.
-  const uint8_t* GetOatAddress(OatAddress type) const;
-
-  const uint8_t* GetOatAddressForOffset(uint32_t offset, const ImageInfo& image_info) const {
-    // With Quick, code is within the OatFile, as there are all in one
-    // .o ELF object. But interpret it as signed.
-    DCHECK_LE(static_cast<int32_t>(offset), static_cast<int32_t>(image_info.oat_size_));
-    DCHECK(image_info.oat_data_begin_ != nullptr);
-    return offset == 0u ? nullptr : image_info.oat_data_begin_ + static_cast<int32_t>(offset);
-  }
-
-  // Returns true if the class was in the original requested image classes list.
-  bool KeepClass(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Debug aid that list of requested image classes.
-  void DumpImageClasses();
-
-  // Preinitializes some otherwise lazy fields (such as Class name) to avoid runtime image dirtying.
-  void ComputeLazyFieldsForImageClasses()
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Visit all class loaders.
-  void VisitClassLoaders(ClassLoaderVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Remove unwanted classes from various roots.
-  void PruneNonImageClasses() REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Remove unwanted classes from the DexCache roots and preload deterministic DexCache contents.
-  void PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache,
-                               ObjPtr<mirror::ClassLoader> class_loader)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::classlinker_classes_lock_);
-
-  // Verify unwanted classes removed.
-  void CheckNonImageClassesRemoved() REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Lays out where the image objects will be at runtime.
-  void CalculateNewObjectOffsets()
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void ProcessWorkStack(WorkStack* work_stack)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void CreateHeader(size_t oat_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  mirror::ObjectArray<mirror::Object>* CreateImageRoots(size_t oat_index) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void CalculateObjectBinSlots(mirror::Object* obj)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void UnbinObjectsIntoOffset(mirror::Object* obj)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Creates the contiguous image in memory and adjusts pointers.
-  void CopyAndFixupNativeData(size_t oat_index) REQUIRES_SHARED(Locks::mutator_lock_);
-  void CopyAndFixupObjects() REQUIRES_SHARED(Locks::mutator_lock_);
-  void CopyAndFixupObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
-  void CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy, const ImageInfo& image_info)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void CopyAndFixupImTable(ImTable* orig, ImTable* copy) REQUIRES_SHARED(Locks::mutator_lock_);
-  void CopyAndFixupImtConflictTable(ImtConflictTable* orig, ImtConflictTable* copy)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void FixupClass(mirror::Class* orig, mirror::Class* copy)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void FixupObject(mirror::Object* orig, mirror::Object* copy)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void FixupDexCache(mirror::DexCache* orig_dex_cache, mirror::DexCache* copy_dex_cache)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void FixupPointerArray(mirror::Object* dst,
-                         mirror::PointerArray* arr,
-                         mirror::Class* klass,
-                         Bin array_type)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Get quick code for non-resolution/imt_conflict/abstract method.
-  const uint8_t* GetQuickCode(ArtMethod* method,
-                              const ImageInfo& image_info,
-                              bool* quick_is_interpreted)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Calculate the sum total of the bin slot sizes in [0, up_to). Defaults to all bins.
-  size_t GetBinSizeSum(ImageInfo& image_info, Bin up_to = kBinSize) const;
-
-  // Return true if a method is likely to be dirtied at runtime.
-  bool WillMethodBeDirty(ArtMethod* m) const REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Assign the offset for an ArtMethod.
-  void AssignMethodOffset(ArtMethod* method,
-                          NativeObjectRelocationType type,
-                          size_t oat_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Return true if imt was newly inserted.
-  bool TryAssignImTableOffset(ImTable* imt, size_t oat_index) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Assign the offset for an IMT conflict table. Does nothing if the table already has a native
-  // relocation.
-  void TryAssignConflictTableOffset(ImtConflictTable* table, size_t oat_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Return true if klass is loaded by the boot class loader but not in the boot image.
-  bool IsBootClassLoaderNonImageClass(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Return true if klass depends on a boot class loader non image class. We want to prune these
-  // classes since we do not want any boot class loader classes in the image. This means that
-  // we also cannot have any classes which refer to these boot class loader non image classes.
-  // PruneAppImageClass also prunes if klass depends on a non-image class according to the compiler
-  // driver.
-  bool PruneAppImageClass(ObjPtr<mirror::Class> klass)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // early_exit is true if we had a cyclic dependency anywhere down the chain.
-  bool PruneAppImageClassInternal(ObjPtr<mirror::Class> klass,
-                                  bool* early_exit,
-                                  std::unordered_set<mirror::Object*>* visited)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  bool IsMultiImage() const {
-    return image_infos_.size() > 1;
-  }
-
-  static Bin BinTypeForNativeRelocationType(NativeObjectRelocationType type);
-
-  uintptr_t NativeOffsetInImage(void* obj) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Location of where the object will be when the image is loaded at runtime.
-  template <typename T>
-  T* NativeLocationInImage(T* obj) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Location of where the temporary copy of the object currently is.
-  template <typename T>
-  T* NativeCopyLocation(T* obj, mirror::DexCache* dex_cache) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Return true of obj is inside of the boot image space. This may only return true if we are
-  // compiling an app image.
-  bool IsInBootImage(const void* obj) const;
-
-  // Return true if ptr is within the boot oat file.
-  bool IsInBootOatFile(const void* ptr) const;
-
-  // Get the index of the oat file associated with the object.
-  size_t GetOatIndex(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // The oat index for shared data in multi-image and all data in single-image compilation.
-  size_t GetDefaultOatIndex() const {
-    return 0u;
-  }
-
-  ImageInfo& GetImageInfo(size_t oat_index) {
-    return image_infos_[oat_index];
-  }
-
-  const ImageInfo& GetImageInfo(size_t oat_index) const {
-    return image_infos_[oat_index];
-  }
-
-  // Find an already strong interned string in the other images or in the boot image. Used to
-  // remove duplicates in the multi image and app image case.
-  mirror::String* FindInternedString(mirror::String* string) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Return true if there already exists a native allocation for an object.
-  bool NativeRelocationAssigned(void* ptr) const;
-
-  void CopyReference(mirror::HeapReference<mirror::Object>* dest, ObjPtr<mirror::Object> src)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  void CopyReference(mirror::CompressedReference<mirror::Object>* dest, ObjPtr<mirror::Object> src)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  void CopyAndFixupPointer(void** target, void* value);
-
-  const CompilerDriver& compiler_driver_;
-
-  // Beginning target image address for the first image.
-  uint8_t* global_image_begin_;
-
-  // Offset from image_begin_ to where the first object is in image_.
-  size_t image_objects_offset_begin_;
-
-  // Pointer arrays that need to be updated. Since these are only some int and long arrays, we need
-  // to keep track. These include vtable arrays, iftable arrays, and dex caches.
-  std::unordered_map<mirror::PointerArray*, Bin> pointer_arrays_;
-
-  // Saved hash codes. We use these to restore lockwords which were temporarily used to have
-  // forwarding addresses as well as copying over hash codes.
-  std::unordered_map<mirror::Object*, uint32_t> saved_hashcode_map_;
-
-  // Oat index map for objects.
-  std::unordered_map<mirror::Object*, uint32_t> oat_index_map_;
-
-  // Boolean flags.
-  const bool compile_pic_;
-  const bool compile_app_image_;
-
-  // Size of pointers on the target architecture.
-  PointerSize target_ptr_size_;
-
-  // Image data indexed by the oat file index.
-  dchecked_vector<ImageInfo> image_infos_;
-
-  // ArtField, ArtMethod relocating map. These are allocated as array of structs but we want to
-  // have one entry per art field for convenience. ArtFields are placed right after the end of the
-  // image objects (aka sum of bin_slot_sizes_). ArtMethods are placed right after the ArtFields.
-  struct NativeObjectRelocation {
-    size_t oat_index;
-    uintptr_t offset;
-    NativeObjectRelocationType type;
-
-    bool IsArtMethodRelocation() const {
-      return type == kNativeObjectRelocationTypeArtMethodClean ||
-          type == kNativeObjectRelocationTypeArtMethodDirty ||
-          type == kNativeObjectRelocationTypeRuntimeMethod;
-    }
-  };
-  std::unordered_map<void*, NativeObjectRelocation> native_object_relocations_;
-
-  // Runtime ArtMethods which aren't reachable from any Class but need to be copied into the image.
-  ArtMethod* image_methods_[ImageHeader::kImageMethodsCount];
-
-  // Counters for measurements, used for logging only.
-  uint64_t dirty_methods_;
-  uint64_t clean_methods_;
-
-  // Prune class memoization table to speed up ContainsBootClassLoaderNonImageClass.
-  std::unordered_map<mirror::Class*, bool> prune_class_memo_;
-
-  // Class loaders with a class table to write out. There should only be one class loader because
-  // dex2oat loads the dex files to be compiled into a single class loader. For the boot image,
-  // null is a valid entry.
-  std::unordered_set<mirror::ClassLoader*> class_loaders_;
-
-  // Which mode the image is stored as, see image.h
-  const ImageHeader::StorageMode image_storage_mode_;
-
-  // The file names of oat files.
-  const std::vector<const char*>& oat_filenames_;
-
-  // Map of dex files to the indexes of oat files that they were compiled into.
-  const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map_;
-
-  // Set of objects known to be dirty in the image. Can be nullptr if there are none.
-  const std::unordered_set<std::string>* dirty_image_objects_;
-
-  class ComputeLazyFieldsForClassesVisitor;
-  class FixupClassVisitor;
-  class FixupRootVisitor;
-  class FixupVisitor;
-  class GetRootsVisitor;
-  class ImageAddressVisitorForDexCacheArray;
-  class NativeLocationVisitor;
-  class PruneClassesVisitor;
-  class PruneClassLoaderClassesVisitor;
-  class RegisterBootClassPathClassesVisitor;
-  class VisitReferencesVisitor;
-  class PruneObjectReferenceVisitor;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageWriter);
-};
-
-}  // namespace art
-
-#endif  // ART_COMPILER_IMAGE_WRITER_H_
diff --git a/compiler/linker/buffered_output_stream.cc b/compiler/linker/buffered_output_stream.cc
index 4c66c76..07066b7 100644
--- a/compiler/linker/buffered_output_stream.cc
+++ b/compiler/linker/buffered_output_stream.cc
@@ -19,6 +19,7 @@
 #include <string.h>
 
 namespace art {
+namespace linker {
 
 BufferedOutputStream::BufferedOutputStream(std::unique_ptr<OutputStream> out)
     : OutputStream(out->GetLocation()),  // Before out is moved to out_.
@@ -67,4 +68,5 @@
   return out_->Seek(offset, whence);
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/buffered_output_stream.h b/compiler/linker/buffered_output_stream.h
index a2eefbb..66994e8 100644
--- a/compiler/linker/buffered_output_stream.h
+++ b/compiler/linker/buffered_output_stream.h
@@ -24,6 +24,7 @@
 #include "globals.h"
 
 namespace art {
+namespace linker {
 
 class BufferedOutputStream FINAL : public OutputStream {
  public:
@@ -49,6 +50,7 @@
   DISALLOW_COPY_AND_ASSIGN(BufferedOutputStream);
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_BUFFERED_OUTPUT_STREAM_H_
diff --git a/compiler/elf_builder.h b/compiler/linker/elf_builder.h
similarity index 99%
rename from compiler/elf_builder.h
rename to compiler/linker/elf_builder.h
index 2ef9fa1..7941237 100644
--- a/compiler/elf_builder.h
+++ b/compiler/linker/elf_builder.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ART_COMPILER_ELF_BUILDER_H_
-#define ART_COMPILER_ELF_BUILDER_H_
+#ifndef ART_COMPILER_LINKER_ELF_BUILDER_H_
+#define ART_COMPILER_LINKER_ELF_BUILDER_H_
 
 #include <vector>
 
@@ -30,6 +30,7 @@
 #include "linker/error_delaying_output_stream.h"
 
 namespace art {
+namespace linker {
 
 // Writes ELF file.
 //
@@ -1021,6 +1022,7 @@
   DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
 };
 
+}  // namespace linker
 }  // namespace art
 
-#endif  // ART_COMPILER_ELF_BUILDER_H_
+#endif  // ART_COMPILER_LINKER_ELF_BUILDER_H_
diff --git a/compiler/linker/error_delaying_output_stream.h b/compiler/linker/error_delaying_output_stream.h
index 99410e4..33e6b5a 100644
--- a/compiler/linker/error_delaying_output_stream.h
+++ b/compiler/linker/error_delaying_output_stream.h
@@ -22,6 +22,7 @@
 #include "base/logging.h"
 
 namespace art {
+namespace linker {
 
 // OutputStream wrapper that delays reporting an error until Flush().
 class ErrorDelayingOutputStream FINAL : public OutputStream {
@@ -96,6 +97,7 @@
   off_t output_offset_;  // Keep track of the current position in the stream.
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_ERROR_DELAYING_OUTPUT_STREAM_H_
diff --git a/compiler/linker/file_output_stream.cc b/compiler/linker/file_output_stream.cc
index bbfbdfd..477846e 100644
--- a/compiler/linker/file_output_stream.cc
+++ b/compiler/linker/file_output_stream.cc
@@ -22,6 +22,7 @@
 #include "base/unix_file/fd_file.h"
 
 namespace art {
+namespace linker {
 
 FileOutputStream::FileOutputStream(File* file) : OutputStream(file->GetPath()), file_(file) {}
 
@@ -37,4 +38,5 @@
   return file_->Flush() == 0;
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/file_output_stream.h b/compiler/linker/file_output_stream.h
index f2d8453..28296a4 100644
--- a/compiler/linker/file_output_stream.h
+++ b/compiler/linker/file_output_stream.h
@@ -22,6 +22,7 @@
 #include "os.h"
 
 namespace art {
+namespace linker {
 
 class FileOutputStream FINAL : public OutputStream {
  public:
@@ -41,6 +42,7 @@
   DISALLOW_COPY_AND_ASSIGN(FileOutputStream);
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_FILE_OUTPUT_STREAM_H_
diff --git a/compiler/linker/multi_oat_relative_patcher.cc b/compiler/linker/multi_oat_relative_patcher.cc
deleted file mode 100644
index 4ae75d6..0000000
--- a/compiler/linker/multi_oat_relative_patcher.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2016 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 "multi_oat_relative_patcher.h"
-
-#include "base/bit_utils.h"
-#include "base/logging.h"
-#include "globals.h"
-
-namespace art {
-namespace linker {
-
-MultiOatRelativePatcher::MultiOatRelativePatcher(InstructionSet instruction_set,
-                                                 const InstructionSetFeatures* features)
-    : method_offset_map_(),
-      relative_patcher_(
-          linker::RelativePatcher::Create(instruction_set, features, &method_offset_map_)),
-      adjustment_(0u),
-      instruction_set_(instruction_set),
-      start_size_code_alignment_(0u),
-      start_size_relative_call_thunks_(0u),
-      start_size_misc_thunks_(0u) {
-}
-
-void MultiOatRelativePatcher::StartOatFile(uint32_t adjustment) {
-  DCHECK_ALIGNED(adjustment, kPageSize);
-  adjustment_ = adjustment;
-
-  start_size_code_alignment_ = relative_patcher_->CodeAlignmentSize();
-  start_size_relative_call_thunks_ = relative_patcher_->RelativeCallThunksSize();
-  start_size_misc_thunks_ = relative_patcher_->MiscThunksSize();
-}
-
-uint32_t MultiOatRelativePatcher::CodeAlignmentSize() const {
-  DCHECK_GE(relative_patcher_->CodeAlignmentSize(), start_size_code_alignment_);
-  return relative_patcher_->CodeAlignmentSize() - start_size_code_alignment_;
-}
-
-uint32_t MultiOatRelativePatcher::RelativeCallThunksSize() const {
-  DCHECK_GE(relative_patcher_->RelativeCallThunksSize(), start_size_relative_call_thunks_);
-  return relative_patcher_->RelativeCallThunksSize() - start_size_relative_call_thunks_;
-}
-
-uint32_t MultiOatRelativePatcher::MiscThunksSize() const {
-  DCHECK_GE(relative_patcher_->MiscThunksSize(), start_size_misc_thunks_);
-  return relative_patcher_->MiscThunksSize() - start_size_misc_thunks_;
-}
-
-std::pair<bool, uint32_t> MultiOatRelativePatcher::MethodOffsetMap::FindMethodOffset(
-    MethodReference ref) {
-  auto it = map.find(ref);
-  if (it == map.end()) {
-    return std::pair<bool, uint32_t>(false, 0u);
-  } else {
-    return std::pair<bool, uint32_t>(true, it->second);
-  }
-}
-}  // namespace linker
-}  // namespace art
diff --git a/compiler/linker/multi_oat_relative_patcher.h b/compiler/linker/multi_oat_relative_patcher.h
deleted file mode 100644
index 02cd4b0..0000000
--- a/compiler/linker/multi_oat_relative_patcher.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2016 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_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
-#define ART_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
-
-#include "arch/instruction_set.h"
-#include "debug/method_debug_info.h"
-#include "method_reference.h"
-#include "relative_patcher.h"
-#include "safe_map.h"
-
-namespace art {
-
-class CompiledMethod;
-class LinkerPatch;
-class InstructionSetFeatures;
-
-namespace linker {
-
-// MultiOatRelativePatcher is a helper class for handling patching across
-// any number of oat files. It provides storage for method code offsets
-// and wraps RelativePatcher calls, adjusting relative offsets according
-// to the value set by SetAdjustment().
-class MultiOatRelativePatcher FINAL {
- public:
-  using const_iterator = SafeMap<MethodReference, uint32_t>::const_iterator;
-
-  MultiOatRelativePatcher(InstructionSet instruction_set, const InstructionSetFeatures* features);
-
-  // Mark the start of a new oat file (for statistics retrieval) and set the
-  // adjustment for a new oat file to apply to all relative offsets that are
-  // passed to the MultiOatRelativePatcher.
-  //
-  // The adjustment should be the global offset of the base from which relative
-  // offsets are calculated, such as the start of .rodata for the current oat file.
-  // It must must never point directly to a method's code to avoid relative offsets
-  // with value 0 because this value is used as a missing offset indication in
-  // GetOffset() and an error indication in WriteThunks(). Additionally, it must be
-  // page-aligned, so that it does not skew alignment calculations, say arm64 ADRP.
-  void StartOatFile(uint32_t adjustment);
-
-  // Get relative offset. Returns 0 when the offset has not been set yet.
-  uint32_t GetOffset(MethodReference method_ref) {
-    auto it = method_offset_map_.map.find(method_ref);
-    return (it != method_offset_map_.map.end()) ? it->second - adjustment_ : 0u;
-  }
-
-  // Set the offset.
-  void SetOffset(MethodReference method_ref, uint32_t offset) {
-    method_offset_map_.map.Put(method_ref, offset + adjustment_);
-  }
-
-  // Wrapper around RelativePatcher::ReserveSpace(), doing offset adjustment.
-  uint32_t ReserveSpace(uint32_t offset,
-                        const CompiledMethod* compiled_method,
-                        MethodReference method_ref) {
-    offset += adjustment_;
-    offset = relative_patcher_->ReserveSpace(offset, compiled_method, method_ref);
-    offset -= adjustment_;
-    return offset;
-  }
-
-  // Wrapper around RelativePatcher::ReserveSpaceEnd(), doing offset adjustment.
-  uint32_t ReserveSpaceEnd(uint32_t offset) {
-    offset += adjustment_;
-    offset = relative_patcher_->ReserveSpaceEnd(offset);
-    offset -= adjustment_;
-    return offset;
-  }
-
-  // Wrapper around RelativePatcher::WriteThunks(), doing offset adjustment.
-  uint32_t WriteThunks(OutputStream* out, uint32_t offset) {
-    offset += adjustment_;
-    offset = relative_patcher_->WriteThunks(out, offset);
-    if (offset != 0u) {  // 0u indicates write error.
-      offset -= adjustment_;
-    }
-    return offset;
-  }
-
-  // Wrapper around RelativePatcher::PatchCall(), doing offset adjustment.
-  void PatchCall(std::vector<uint8_t>* code,
-                 uint32_t literal_offset,
-                 uint32_t patch_offset,
-                 uint32_t target_offset) {
-    patch_offset += adjustment_;
-    target_offset += adjustment_;
-    relative_patcher_->PatchCall(code, literal_offset, patch_offset, target_offset);
-  }
-
-  // Wrapper around RelativePatcher::PatchPcRelativeReference(), doing offset adjustment.
-  void PatchPcRelativeReference(std::vector<uint8_t>* code,
-                                const LinkerPatch& patch,
-                                uint32_t patch_offset,
-                                uint32_t target_offset) {
-    patch_offset += adjustment_;
-    target_offset += adjustment_;
-    relative_patcher_->PatchPcRelativeReference(code, patch, patch_offset, target_offset);
-  }
-
-  void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code,
-                                   const LinkerPatch& patch,
-                                   uint32_t patch_offset) {
-    patch_offset += adjustment_;
-    relative_patcher_->PatchBakerReadBarrierBranch(code, patch, patch_offset);
-  }
-
-  std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(size_t executable_offset) {
-    executable_offset += adjustment_;
-    return relative_patcher_->GenerateThunkDebugInfo(executable_offset);
-  }
-
-  // Wrappers around RelativePatcher for statistics retrieval.
-  uint32_t CodeAlignmentSize() const;
-  uint32_t RelativeCallThunksSize() const;
-  uint32_t MiscThunksSize() const;
-
- private:
-  // Map method reference to assigned offset.
-  // Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
-  class MethodOffsetMap : public linker::RelativePatcherTargetProvider {
-   public:
-    std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) OVERRIDE;
-    SafeMap<MethodReference, uint32_t> map;
-  };
-
-  MethodOffsetMap method_offset_map_;
-  std::unique_ptr<RelativePatcher> relative_patcher_;
-  uint32_t adjustment_;
-  InstructionSet instruction_set_;
-
-  uint32_t start_size_code_alignment_;
-  uint32_t start_size_relative_call_thunks_;
-  uint32_t start_size_misc_thunks_;
-
-  friend class MultiOatRelativePatcherTest;
-
-  DISALLOW_COPY_AND_ASSIGN(MultiOatRelativePatcher);
-};
-
-}  // namespace linker
-}  // namespace art
-
-#endif  // ART_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
diff --git a/compiler/linker/multi_oat_relative_patcher_test.cc b/compiler/linker/multi_oat_relative_patcher_test.cc
deleted file mode 100644
index 5c359dc..0000000
--- a/compiler/linker/multi_oat_relative_patcher_test.cc
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2016 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 "multi_oat_relative_patcher.h"
-
-#include "compiled_method.h"
-#include "debug/method_debug_info.h"
-#include "gtest/gtest.h"
-#include "vector_output_stream.h"
-
-namespace art {
-namespace linker {
-
-static const MethodReference kNullMethodRef = MethodReference(nullptr, 0u);
-
-class MultiOatRelativePatcherTest : public testing::Test {
- protected:
-  class MockPatcher : public RelativePatcher {
-   public:
-    MockPatcher() { }
-
-    uint32_t ReserveSpace(uint32_t offset,
-                          const CompiledMethod* compiled_method ATTRIBUTE_UNUSED,
-                          MethodReference method_ref) OVERRIDE {
-      last_reserve_offset_ = offset;
-      last_reserve_method_ = method_ref;
-      offset += next_reserve_adjustment_;
-      next_reserve_adjustment_ = 0u;
-      return offset;
-    }
-
-    uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE {
-      last_reserve_offset_ = offset;
-      last_reserve_method_ = kNullMethodRef;
-      offset += next_reserve_adjustment_;
-      next_reserve_adjustment_ = 0u;
-      return offset;
-    }
-
-    uint32_t WriteThunks(OutputStream* out, uint32_t offset) OVERRIDE {
-      last_write_offset_ = offset;
-      if (next_write_alignment_ != 0u) {
-        offset += next_write_alignment_;
-        bool success = WriteCodeAlignment(out, next_write_alignment_);
-        CHECK(success);
-        next_write_alignment_ = 0u;
-      }
-      if (next_write_call_thunk_ != 0u) {
-        offset += next_write_call_thunk_;
-        std::vector<uint8_t> thunk(next_write_call_thunk_, 'c');
-        bool success = WriteThunk(out, ArrayRef<const uint8_t>(thunk));
-        CHECK(success);
-        next_write_call_thunk_ = 0u;
-      }
-      if (next_write_misc_thunk_ != 0u) {
-        offset += next_write_misc_thunk_;
-        std::vector<uint8_t> thunk(next_write_misc_thunk_, 'm');
-        bool success = WriteMiscThunk(out, ArrayRef<const uint8_t>(thunk));
-        CHECK(success);
-        next_write_misc_thunk_ = 0u;
-      }
-      return offset;
-    }
-
-    void PatchCall(std::vector<uint8_t>* code ATTRIBUTE_UNUSED,
-                   uint32_t literal_offset,
-                   uint32_t patch_offset,
-                   uint32_t target_offset) OVERRIDE {
-      last_literal_offset_ = literal_offset;
-      last_patch_offset_ = patch_offset;
-      last_target_offset_ = target_offset;
-    }
-
-    void PatchPcRelativeReference(std::vector<uint8_t>* code ATTRIBUTE_UNUSED,
-                                  const LinkerPatch& patch,
-                                  uint32_t patch_offset,
-                                  uint32_t target_offset) OVERRIDE {
-      last_literal_offset_ = patch.LiteralOffset();
-      last_patch_offset_ = patch_offset;
-      last_target_offset_ = target_offset;
-    }
-
-    void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code ATTRIBUTE_UNUSED,
-                                     const LinkerPatch& patch ATTRIBUTE_UNUSED,
-                                     uint32_t patch_offset ATTRIBUTE_UNUSED) {
-      LOG(FATAL) << "UNIMPLEMENTED";
-    }
-
-    std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(
-        uint32_t executable_offset ATTRIBUTE_UNUSED) {
-      LOG(FATAL) << "UNIMPLEMENTED";
-      UNREACHABLE();
-    }
-
-    uint32_t last_reserve_offset_ = 0u;
-    MethodReference last_reserve_method_ = kNullMethodRef;
-    uint32_t next_reserve_adjustment_ = 0u;
-
-    uint32_t last_write_offset_ = 0u;
-    uint32_t next_write_alignment_ = 0u;
-    uint32_t next_write_call_thunk_ = 0u;
-    uint32_t next_write_misc_thunk_ = 0u;
-
-    uint32_t last_literal_offset_ = 0u;
-    uint32_t last_patch_offset_ = 0u;
-    uint32_t last_target_offset_ = 0u;
-  };
-
-  MultiOatRelativePatcherTest()
-      : instruction_set_features_(InstructionSetFeatures::FromCppDefines()),
-        patcher_(kRuntimeISA, instruction_set_features_.get()) {
-    std::unique_ptr<MockPatcher> mock(new MockPatcher());
-    mock_ = mock.get();
-    patcher_.relative_patcher_ = std::move(mock);
-  }
-
-  std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
-  MultiOatRelativePatcher patcher_;
-  MockPatcher* mock_;
-};
-
-TEST_F(MultiOatRelativePatcherTest, Offsets) {
-  const DexFile* dex_file = reinterpret_cast<const DexFile*>(1);
-  MethodReference ref1(dex_file, 1u);
-  MethodReference ref2(dex_file, 2u);
-  EXPECT_EQ(0u, patcher_.GetOffset(ref1));
-  EXPECT_EQ(0u, patcher_.GetOffset(ref2));
-
-  uint32_t adjustment1 = 0x1000;
-  patcher_.StartOatFile(adjustment1);
-  EXPECT_EQ(0u, patcher_.GetOffset(ref1));
-  EXPECT_EQ(0u, patcher_.GetOffset(ref2));
-
-  uint32_t off1 = 0x1234;
-  patcher_.SetOffset(ref1, off1);
-  EXPECT_EQ(off1, patcher_.GetOffset(ref1));
-  EXPECT_EQ(0u, patcher_.GetOffset(ref2));
-
-  uint32_t adjustment2 = 0x30000;
-  patcher_.StartOatFile(adjustment2);
-  EXPECT_EQ(off1 + adjustment1 - adjustment2, patcher_.GetOffset(ref1));
-  EXPECT_EQ(0u, patcher_.GetOffset(ref2));
-
-  uint32_t off2 = 0x4321;
-  patcher_.SetOffset(ref2, off2);
-  EXPECT_EQ(off1 + adjustment1 - adjustment2, patcher_.GetOffset(ref1));
-  EXPECT_EQ(off2, patcher_.GetOffset(ref2));
-
-  uint32_t adjustment3 = 0x78000;
-  patcher_.StartOatFile(adjustment3);
-  EXPECT_EQ(off1 + adjustment1 - adjustment3, patcher_.GetOffset(ref1));
-  EXPECT_EQ(off2 + adjustment2 - adjustment3, patcher_.GetOffset(ref2));
-}
-
-TEST_F(MultiOatRelativePatcherTest, OffsetsInReserve) {
-  const DexFile* dex_file = reinterpret_cast<const DexFile*>(1);
-  MethodReference ref1(dex_file, 1u);
-  MethodReference ref2(dex_file, 2u);
-  MethodReference ref3(dex_file, 3u);
-  const CompiledMethod* method = reinterpret_cast<const CompiledMethod*>(-1);
-
-  uint32_t adjustment1 = 0x1000;
-  patcher_.StartOatFile(adjustment1);
-
-  uint32_t method1_offset = 0x100;
-  uint32_t method1_offset_check = patcher_.ReserveSpace(method1_offset, method, ref1);
-  ASSERT_EQ(adjustment1 + method1_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(ref1 == mock_->last_reserve_method_);
-  ASSERT_EQ(method1_offset, method1_offset_check);
-
-  uint32_t method2_offset = 0x1230;
-  uint32_t method2_reserve_adjustment = 0x10;
-  mock_->next_reserve_adjustment_ = method2_reserve_adjustment;
-  uint32_t method2_offset_adjusted = patcher_.ReserveSpace(method2_offset, method, ref2);
-  ASSERT_EQ(adjustment1 + method2_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(ref2 == mock_->last_reserve_method_);
-  ASSERT_EQ(method2_offset + method2_reserve_adjustment, method2_offset_adjusted);
-
-  uint32_t end1_offset = 0x4320;
-  uint32_t end1_offset_check = patcher_.ReserveSpaceEnd(end1_offset);
-  ASSERT_EQ(adjustment1 + end1_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(kNullMethodRef == mock_->last_reserve_method_);
-  ASSERT_EQ(end1_offset, end1_offset_check);
-
-  uint32_t adjustment2 = 0xd000;
-  patcher_.StartOatFile(adjustment2);
-
-  uint32_t method3_offset = 0xf00;
-  uint32_t method3_offset_check = patcher_.ReserveSpace(method3_offset, method, ref3);
-  ASSERT_EQ(adjustment2 + method3_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(ref3 == mock_->last_reserve_method_);
-  ASSERT_EQ(method3_offset, method3_offset_check);
-
-  uint32_t end2_offset = 0x2400;
-  uint32_t end2_reserve_adjustment = 0x20;
-  mock_->next_reserve_adjustment_ = end2_reserve_adjustment;
-  uint32_t end2_offset_adjusted = patcher_.ReserveSpaceEnd(end2_offset);
-  ASSERT_EQ(adjustment2 + end2_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(kNullMethodRef == mock_->last_reserve_method_);
-  ASSERT_EQ(end2_offset + end2_reserve_adjustment, end2_offset_adjusted);
-}
-
-TEST_F(MultiOatRelativePatcherTest, Write) {
-  std::vector<uint8_t> output;
-  VectorOutputStream vos("output", &output);
-
-  uint32_t adjustment1 = 0x1000;
-  patcher_.StartOatFile(adjustment1);
-
-  uint32_t method1_offset = 0x100;
-  uint32_t method1_offset_check = patcher_.WriteThunks(&vos, method1_offset);
-  ASSERT_EQ(adjustment1 + method1_offset, mock_->last_write_offset_);
-  ASSERT_EQ(method1_offset, method1_offset_check);
-  vos.WriteFully("1", 1);  // Mark method1.
-
-  uint32_t method2_offset = 0x1230;
-  uint32_t method2_alignment_size = 1;
-  uint32_t method2_call_thunk_size = 2;
-  mock_->next_write_alignment_ = method2_alignment_size;
-  mock_->next_write_call_thunk_ = method2_call_thunk_size;
-  uint32_t method2_offset_adjusted = patcher_.WriteThunks(&vos, method2_offset);
-  ASSERT_EQ(adjustment1 + method2_offset, mock_->last_write_offset_);
-  ASSERT_EQ(method2_offset + method2_alignment_size + method2_call_thunk_size,
-            method2_offset_adjusted);
-  vos.WriteFully("2", 1);  // Mark method2.
-
-  EXPECT_EQ(method2_alignment_size, patcher_.CodeAlignmentSize());
-  EXPECT_EQ(method2_call_thunk_size, patcher_.RelativeCallThunksSize());
-
-  uint32_t adjustment2 = 0xd000;
-  patcher_.StartOatFile(adjustment2);
-
-  uint32_t method3_offset = 0xf00;
-  uint32_t method3_alignment_size = 2;
-  uint32_t method3_misc_thunk_size = 1;
-  mock_->next_write_alignment_ = method3_alignment_size;
-  mock_->next_write_misc_thunk_ = method3_misc_thunk_size;
-  uint32_t method3_offset_adjusted = patcher_.WriteThunks(&vos, method3_offset);
-  ASSERT_EQ(adjustment2 + method3_offset, mock_->last_write_offset_);
-  ASSERT_EQ(method3_offset + method3_alignment_size + method3_misc_thunk_size,
-            method3_offset_adjusted);
-  vos.WriteFully("3", 1);  // Mark method3.
-
-  EXPECT_EQ(method3_alignment_size, patcher_.CodeAlignmentSize());
-  EXPECT_EQ(method3_misc_thunk_size, patcher_.MiscThunksSize());
-
-  uint8_t expected_output[] = {
-      '1',
-      0, 'c', 'c', '2',
-      0, 0, 'm', '3',
-  };
-  ASSERT_EQ(arraysize(expected_output), output.size());
-  for (size_t i = 0; i != arraysize(expected_output); ++i) {
-    ASSERT_EQ(expected_output[i], output[i]) << i;
-  }
-}
-
-TEST_F(MultiOatRelativePatcherTest, Patch) {
-  std::vector<uint8_t> code(16);
-
-  uint32_t adjustment1 = 0x1000;
-  patcher_.StartOatFile(adjustment1);
-
-  uint32_t method1_literal_offset = 4u;
-  uint32_t method1_patch_offset = 0x1234u;
-  uint32_t method1_target_offset = 0x8888u;
-  patcher_.PatchCall(&code, method1_literal_offset, method1_patch_offset, method1_target_offset);
-  DCHECK_EQ(method1_literal_offset, mock_->last_literal_offset_);
-  DCHECK_EQ(method1_patch_offset + adjustment1, mock_->last_patch_offset_);
-  DCHECK_EQ(method1_target_offset + adjustment1, mock_->last_target_offset_);
-
-  uint32_t method2_literal_offset = 12u;
-  uint32_t method2_patch_offset = 0x7654u;
-  uint32_t method2_target_offset = 0xccccu;
-  LinkerPatch method2_patch =
-      LinkerPatch::StringBssEntryPatch(method2_literal_offset, nullptr, 0u, 1u);
-  patcher_.PatchPcRelativeReference(
-      &code, method2_patch, method2_patch_offset, method2_target_offset);
-  DCHECK_EQ(method2_literal_offset, mock_->last_literal_offset_);
-  DCHECK_EQ(method2_patch_offset + adjustment1, mock_->last_patch_offset_);
-  DCHECK_EQ(method2_target_offset + adjustment1, mock_->last_target_offset_);
-
-  uint32_t adjustment2 = 0xd000;
-  patcher_.StartOatFile(adjustment2);
-
-  uint32_t method3_literal_offset = 8u;
-  uint32_t method3_patch_offset = 0x108u;
-  uint32_t method3_target_offset = 0x200u;
-  patcher_.PatchCall(&code, method3_literal_offset, method3_patch_offset, method3_target_offset);
-  DCHECK_EQ(method3_literal_offset, mock_->last_literal_offset_);
-  DCHECK_EQ(method3_patch_offset + adjustment2, mock_->last_patch_offset_);
-  DCHECK_EQ(method3_target_offset + adjustment2, mock_->last_target_offset_);
-}
-
-}  // namespace linker
-}  // namespace art
diff --git a/compiler/linker/output_stream.cc b/compiler/linker/output_stream.cc
index a8b64ca..f5a1913 100644
--- a/compiler/linker/output_stream.cc
+++ b/compiler/linker/output_stream.cc
@@ -17,6 +17,7 @@
 #include "output_stream.h"
 
 namespace art {
+namespace linker {
 
 std::ostream& operator<<(std::ostream& os, const Whence& rhs) {
   switch (rhs) {
@@ -28,4 +29,5 @@
   return os;
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/output_stream.h b/compiler/linker/output_stream.h
index 96a5f48..5310e2f 100644
--- a/compiler/linker/output_stream.h
+++ b/compiler/linker/output_stream.h
@@ -23,6 +23,7 @@
 #include "base/macros.h"
 
 namespace art {
+namespace linker {
 
 enum Whence {
   kSeekSet = SEEK_SET,
@@ -59,6 +60,7 @@
   DISALLOW_COPY_AND_ASSIGN(OutputStream);
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_OUTPUT_STREAM_H_
diff --git a/compiler/linker/output_stream_test.cc b/compiler/linker/output_stream_test.cc
index 87cb100..ad29840 100644
--- a/compiler/linker/output_stream_test.cc
+++ b/compiler/linker/output_stream_test.cc
@@ -23,6 +23,7 @@
 #include "common_runtime_test.h"
 
 namespace art {
+namespace linker {
 
 class OutputStreamTest : public CommonRuntimeTest {
  protected:
@@ -133,4 +134,5 @@
   ASSERT_TRUE(checking_output_stream->flush_called);
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/relative_patcher.h b/compiler/linker/relative_patcher.h
index 53a0966..e079946 100644
--- a/compiler/linker/relative_patcher.h
+++ b/compiler/linker/relative_patcher.h
@@ -29,7 +29,6 @@
 
 class CompiledMethod;
 class LinkerPatch;
-class OutputStream;
 
 namespace debug {
 struct MethodDebugInfo;
@@ -37,6 +36,8 @@
 
 namespace linker {
 
+class OutputStream;
+
 /**
  * @class RelativePatcherTargetProvider
  * @brief Interface for providing method offsets for relative call targets.
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index ca8743a..f7dbc1e 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -252,8 +252,8 @@
   }
 
   // Map method reference to assinged offset.
-  // Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
-  class MethodOffsetMap FINAL : public linker::RelativePatcherTargetProvider {
+  // Wrap the map in a class implementing RelativePatcherTargetProvider.
+  class MethodOffsetMap FINAL : public RelativePatcherTargetProvider {
    public:
     std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) OVERRIDE {
       auto it = map.find(ref);
diff --git a/compiler/linker/vector_output_stream.cc b/compiler/linker/vector_output_stream.cc
index f758005..75f90e5 100644
--- a/compiler/linker/vector_output_stream.cc
+++ b/compiler/linker/vector_output_stream.cc
@@ -19,6 +19,7 @@
 #include "base/logging.h"
 
 namespace art {
+namespace linker {
 
 VectorOutputStream::VectorOutputStream(const std::string& location, std::vector<uint8_t>* vector)
     : OutputStream(location), offset_(vector->size()), vector_(vector) {}
@@ -45,4 +46,5 @@
   return offset_;
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/vector_output_stream.h b/compiler/linker/vector_output_stream.h
index a9b93e7..92caf59 100644
--- a/compiler/linker/vector_output_stream.h
+++ b/compiler/linker/vector_output_stream.h
@@ -24,6 +24,7 @@
 #include <vector>
 
 namespace art {
+namespace linker {
 
 class VectorOutputStream FINAL : public OutputStream {
  public:
@@ -64,6 +65,7 @@
   DISALLOW_COPY_AND_ASSIGN(VectorOutputStream);
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_VECTOR_OUTPUT_STREAM_H_
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
deleted file mode 100644
index 6f89049..0000000
--- a/compiler/oat_test.cc
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
- * Copyright (C) 2011 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 "android-base/stringprintf.h"
-
-#include "arch/instruction_set_features.h"
-#include "art_method-inl.h"
-#include "base/enums.h"
-#include "base/stl_util.h"
-#include "base/unix_file/fd_file.h"
-#include "class_linker.h"
-#include "common_compiler_test.h"
-#include "compiled_method.h"
-#include "compiler.h"
-#include "debug/method_debug_info.h"
-#include "dex/quick_compiler_callbacks.h"
-#include "dex/verification_results.h"
-#include "driver/compiler_driver.h"
-#include "driver/compiler_options.h"
-#include "elf_writer.h"
-#include "elf_writer_quick.h"
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "linker/buffered_output_stream.h"
-#include "linker/file_output_stream.h"
-#include "linker/multi_oat_relative_patcher.h"
-#include "linker/vector_output_stream.h"
-#include "mirror/class-inl.h"
-#include "mirror/object-inl.h"
-#include "mirror/object_array-inl.h"
-#include "oat_file-inl.h"
-#include "oat_writer.h"
-#include "scoped_thread_state_change-inl.h"
-#include "utils/test_dex_file_builder.h"
-
-namespace art {
-
-NO_RETURN static void Usage(const char* fmt, ...) {
-  va_list ap;
-  va_start(ap, fmt);
-  std::string error;
-  android::base::StringAppendV(&error, fmt, ap);
-  LOG(FATAL) << error;
-  va_end(ap);
-  UNREACHABLE();
-}
-
-class OatTest : public CommonCompilerTest {
- protected:
-  static const bool kCompile = false;  // DISABLED_ due to the time to compile libcore
-
-  void CheckMethod(ArtMethod* method,
-                   const OatFile::OatMethod& oat_method,
-                   const DexFile& dex_file)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    const CompiledMethod* compiled_method =
-        compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
-                                                            method->GetDexMethodIndex()));
-
-    if (compiled_method == nullptr) {
-      EXPECT_TRUE(oat_method.GetQuickCode() == nullptr) << method->PrettyMethod() << " "
-                                                        << oat_method.GetQuickCode();
-      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), 0U);
-      EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
-      EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
-    } else {
-      const void* quick_oat_code = oat_method.GetQuickCode();
-      EXPECT_TRUE(quick_oat_code != nullptr) << method->PrettyMethod();
-      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
-      EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
-      EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
-      uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(quick_oat_code), 2);
-      quick_oat_code = reinterpret_cast<const void*>(oat_code_aligned);
-      ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
-      EXPECT_FALSE(quick_code.empty());
-      size_t code_size = quick_code.size() * sizeof(quick_code[0]);
-      EXPECT_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size))
-          << method->PrettyMethod() << " " << code_size;
-      CHECK_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size));
-    }
-  }
-
-  void SetupCompiler(Compiler::Kind compiler_kind,
-                     InstructionSet insn_set,
-                     const std::vector<std::string>& compiler_options,
-                     /*out*/std::string* error_msg) {
-    ASSERT_TRUE(error_msg != nullptr);
-    insn_features_ = InstructionSetFeatures::FromVariant(insn_set, "default", error_msg);
-    ASSERT_TRUE(insn_features_ != nullptr) << error_msg;
-    compiler_options_.reset(new CompilerOptions);
-    for (const std::string& option : compiler_options) {
-      compiler_options_->ParseCompilerOption(option, Usage);
-    }
-    verification_results_.reset(new VerificationResults(compiler_options_.get()));
-    callbacks_.reset(new QuickCompilerCallbacks(CompilerCallbacks::CallbackMode::kCompileApp));
-    callbacks_->SetVerificationResults(verification_results_.get());
-    Runtime::Current()->SetCompilerCallbacks(callbacks_.get());
-    timer_.reset(new CumulativeLogger("Compilation times"));
-    compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
-                                              verification_results_.get(),
-                                              compiler_kind,
-                                              insn_set,
-                                              insn_features_.get(),
-                                              /* image_classes */ nullptr,
-                                              /* compiled_classes */ nullptr,
-                                              /* compiled_methods */ nullptr,
-                                              /* thread_count */ 2,
-                                              /* dump_stats */ true,
-                                              /* dump_passes */ true,
-                                              timer_.get(),
-                                              /* swap_fd */ -1,
-                                              /* profile_compilation_info */ nullptr));
-  }
-
-  bool WriteElf(File* vdex_file,
-                File* oat_file,
-                const std::vector<const DexFile*>& dex_files,
-                SafeMap<std::string, std::string>& key_value_store,
-                bool verify) {
-    TimingLogger timings("WriteElf", false, false);
-    OatWriter oat_writer(/*compiling_boot_image*/false,
-                         &timings,
-                         /*profile_compilation_info*/nullptr);
-    for (const DexFile* dex_file : dex_files) {
-      ArrayRef<const uint8_t> raw_dex_file(
-          reinterpret_cast<const uint8_t*>(&dex_file->GetHeader()),
-          dex_file->GetHeader().file_size_);
-      if (!oat_writer.AddRawDexFileSource(raw_dex_file,
-                                          dex_file->GetLocation().c_str(),
-                                          dex_file->GetLocationChecksum())) {
-        return false;
-      }
-    }
-    return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
-  }
-
-  bool WriteElf(File* vdex_file,
-                File* oat_file,
-                const std::vector<const char*>& dex_filenames,
-                SafeMap<std::string, std::string>& key_value_store,
-                bool verify,
-                ProfileCompilationInfo* profile_compilation_info) {
-    TimingLogger timings("WriteElf", false, false);
-    OatWriter oat_writer(/*compiling_boot_image*/false, &timings, profile_compilation_info);
-    for (const char* dex_filename : dex_filenames) {
-      if (!oat_writer.AddDexFileSource(dex_filename, dex_filename)) {
-        return false;
-      }
-    }
-    return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
-  }
-
-  bool WriteElf(File* vdex_file,
-                File* oat_file,
-                File&& zip_fd,
-                const char* location,
-                SafeMap<std::string, std::string>& key_value_store,
-                bool verify) {
-    TimingLogger timings("WriteElf", false, false);
-    OatWriter oat_writer(/*compiling_boot_image*/false,
-                         &timings,
-                         /*profile_compilation_info*/nullptr);
-    if (!oat_writer.AddZippedDexFilesSource(std::move(zip_fd), location)) {
-      return false;
-    }
-    return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
-  }
-
-  bool DoWriteElf(File* vdex_file,
-                  File* oat_file,
-                  OatWriter& oat_writer,
-                  SafeMap<std::string, std::string>& key_value_store,
-                  bool verify) {
-    std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick(
-        compiler_driver_->GetInstructionSet(),
-        compiler_driver_->GetInstructionSetFeatures(),
-        &compiler_driver_->GetCompilerOptions(),
-        oat_file);
-    elf_writer->Start();
-    OutputStream* oat_rodata = elf_writer->StartRoData();
-    std::unique_ptr<MemMap> opened_dex_files_map;
-    std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
-    if (!oat_writer.WriteAndOpenDexFiles(kIsVdexEnabled ? vdex_file : oat_file,
-                                         oat_rodata,
-                                         compiler_driver_->GetInstructionSet(),
-                                         compiler_driver_->GetInstructionSetFeatures(),
-                                         &key_value_store,
-                                         verify,
-                                         /* update_input_vdex */ false,
-                                         &opened_dex_files_map,
-                                         &opened_dex_files)) {
-      return false;
-    }
-
-    Runtime* runtime = Runtime::Current();
-    ClassLinker* const class_linker = runtime->GetClassLinker();
-    std::vector<const DexFile*> dex_files;
-    for (const std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
-      dex_files.push_back(dex_file.get());
-      ScopedObjectAccess soa(Thread::Current());
-      class_linker->RegisterDexFile(*dex_file, nullptr);
-    }
-    linker::MultiOatRelativePatcher patcher(compiler_driver_->GetInstructionSet(),
-                                            instruction_set_features_.get());
-    oat_writer.Initialize(compiler_driver_.get(), nullptr, dex_files);
-    oat_writer.PrepareLayout(&patcher);
-    size_t rodata_size = oat_writer.GetOatHeader().GetExecutableOffset();
-    size_t text_size = oat_writer.GetOatSize() - rodata_size;
-    elf_writer->PrepareDynamicSection(rodata_size,
-                                      text_size,
-                                      oat_writer.GetBssSize(),
-                                      oat_writer.GetBssMethodsOffset(),
-                                      oat_writer.GetBssRootsOffset());
-
-    if (kIsVdexEnabled) {
-      std::unique_ptr<BufferedOutputStream> vdex_out =
-            std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
-      if (!oat_writer.WriteVerifierDeps(vdex_out.get(), nullptr)) {
-        return false;
-      }
-      if (!oat_writer.WriteChecksumsAndVdexHeader(vdex_out.get())) {
-        return false;
-      }
-    }
-
-    if (!oat_writer.WriteRodata(oat_rodata)) {
-      return false;
-    }
-    elf_writer->EndRoData(oat_rodata);
-
-    OutputStream* text = elf_writer->StartText();
-    if (!oat_writer.WriteCode(text)) {
-      return false;
-    }
-    elf_writer->EndText(text);
-
-    if (!oat_writer.WriteHeader(elf_writer->GetStream(), 42U, 4096U, 0)) {
-      return false;
-    }
-
-    elf_writer->WriteDynamicSection();
-    elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo());
-
-    if (!elf_writer->End()) {
-      return false;
-    }
-
-    opened_dex_files_maps_.emplace_back(std::move(opened_dex_files_map));
-    for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
-      opened_dex_files_.emplace_back(dex_file.release());
-    }
-    return true;
-  }
-
-  void TestDexFileInput(bool verify, bool low_4gb, bool use_profile);
-  void TestZipFileInput(bool verify);
-  void TestZipFileInputWithEmptyDex();
-
-  std::unique_ptr<const InstructionSetFeatures> insn_features_;
-  std::unique_ptr<QuickCompilerCallbacks> callbacks_;
-
-  std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps_;
-  std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
-};
-
-class ZipBuilder {
- public:
-  explicit ZipBuilder(File* zip_file) : zip_file_(zip_file) { }
-
-  bool AddFile(const char* location, const void* data, size_t size) {
-    off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR);
-    if (offset == static_cast<off_t>(-1)) {
-      return false;
-    }
-
-    ZipFileHeader file_header;
-    file_header.crc32 = crc32(0u, reinterpret_cast<const Bytef*>(data), size);
-    file_header.compressed_size = size;
-    file_header.uncompressed_size = size;
-    file_header.filename_length = strlen(location);
-
-    if (!zip_file_->WriteFully(&file_header, sizeof(file_header)) ||
-        !zip_file_->WriteFully(location, file_header.filename_length) ||
-        !zip_file_->WriteFully(data, size)) {
-      return false;
-    }
-
-    CentralDirectoryFileHeader cdfh;
-    cdfh.crc32 = file_header.crc32;
-    cdfh.compressed_size = size;
-    cdfh.uncompressed_size = size;
-    cdfh.filename_length = file_header.filename_length;
-    cdfh.relative_offset_of_local_file_header = offset;
-    file_data_.push_back(FileData { cdfh, location });
-    return true;
-  }
-
-  bool Finish() {
-    off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR);
-    if (offset == static_cast<off_t>(-1)) {
-      return false;
-    }
-
-    size_t central_directory_size = 0u;
-    for (const FileData& file_data : file_data_) {
-      if (!zip_file_->WriteFully(&file_data.cdfh, sizeof(file_data.cdfh)) ||
-          !zip_file_->WriteFully(file_data.location, file_data.cdfh.filename_length)) {
-        return false;
-      }
-      central_directory_size += sizeof(file_data.cdfh) + file_data.cdfh.filename_length;
-    }
-    EndOfCentralDirectoryRecord eocd_record;
-    eocd_record.number_of_central_directory_records_on_this_disk = file_data_.size();
-    eocd_record.total_number_of_central_directory_records = file_data_.size();
-    eocd_record.size_of_central_directory = central_directory_size;
-    eocd_record.offset_of_start_of_central_directory = offset;
-    return
-        zip_file_->WriteFully(&eocd_record, sizeof(eocd_record)) &&
-        zip_file_->Flush() == 0;
-  }
-
- private:
-  struct PACKED(1) ZipFileHeader {
-    uint32_t signature = 0x04034b50;
-    uint16_t version_needed_to_extract = 10;
-    uint16_t general_purpose_bit_flag = 0;
-    uint16_t compression_method = 0;            // 0 = store only.
-    uint16_t file_last_modification_time = 0u;
-    uint16_t file_last_modification_date = 0u;
-    uint32_t crc32;
-    uint32_t compressed_size;
-    uint32_t uncompressed_size;
-    uint16_t filename_length;
-    uint16_t extra_field_length = 0u;           // No extra fields.
-  };
-
-  struct PACKED(1) CentralDirectoryFileHeader {
-    uint32_t signature = 0x02014b50;
-    uint16_t version_made_by = 10;
-    uint16_t version_needed_to_extract = 10;
-    uint16_t general_purpose_bit_flag = 0;
-    uint16_t compression_method = 0;            // 0 = store only.
-    uint16_t file_last_modification_time = 0u;
-    uint16_t file_last_modification_date = 0u;
-    uint32_t crc32;
-    uint32_t compressed_size;
-    uint32_t uncompressed_size;
-    uint16_t filename_length;
-    uint16_t extra_field_length = 0u;           // No extra fields.
-    uint16_t file_comment_length = 0u;          // No file comment.
-    uint16_t disk_number_where_file_starts = 0u;
-    uint16_t internal_file_attributes = 0u;
-    uint32_t external_file_attributes = 0u;
-    uint32_t relative_offset_of_local_file_header;
-  };
-
-  struct PACKED(1) EndOfCentralDirectoryRecord {
-    uint32_t signature = 0x06054b50;
-    uint16_t number_of_this_disk = 0u;
-    uint16_t disk_where_central_directory_starts = 0u;
-    uint16_t number_of_central_directory_records_on_this_disk;
-    uint16_t total_number_of_central_directory_records;
-    uint32_t size_of_central_directory;
-    uint32_t offset_of_start_of_central_directory;
-    uint16_t comment_length = 0u;               // No file comment.
-  };
-
-  struct FileData {
-    CentralDirectoryFileHeader cdfh;
-    const char* location;
-  };
-
-  File* zip_file_;
-  std::vector<FileData> file_data_;
-};
-
-TEST_F(OatTest, WriteRead) {
-  TimingLogger timings("OatTest::WriteRead", false, false);
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-
-  // TODO: make selectable.
-  Compiler::Kind compiler_kind = Compiler::kQuick;
-  InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
-  std::string error_msg;
-  SetupCompiler(compiler_kind, insn_set, std::vector<std::string>(), /*out*/ &error_msg);
-
-  jobject class_loader = nullptr;
-  if (kCompile) {
-    TimingLogger timings2("OatTest::WriteRead", false, false);
-    compiler_driver_->SetDexFilesForOatFile(class_linker->GetBootClassPath());
-    compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings2);
-  }
-
-  ScratchFile tmp_oat, tmp_vdex(tmp_oat, ".vdex");
-  SafeMap<std::string, std::string> key_value_store;
-  key_value_store.Put(OatHeader::kImageLocationKey, "lue.art");
-  bool success = WriteElf(tmp_vdex.GetFile(),
-                          tmp_oat.GetFile(),
-                          class_linker->GetBootClassPath(),
-                          key_value_store,
-                          false);
-  ASSERT_TRUE(success);
-
-  if (kCompile) {  // OatWriter strips the code, regenerate to compare
-    compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings);
-  }
-  std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp_oat.GetFilename(),
-                                                  tmp_oat.GetFilename(),
-                                                  nullptr,
-                                                  nullptr,
-                                                  false,
-                                                  /*low_4gb*/true,
-                                                  nullptr,
-                                                  &error_msg));
-  ASSERT_TRUE(oat_file.get() != nullptr) << error_msg;
-  const OatHeader& oat_header = oat_file->GetOatHeader();
-  ASSERT_TRUE(oat_header.IsValid());
-  ASSERT_EQ(class_linker->GetBootClassPath().size(), oat_header.GetDexFileCount());  // core
-  ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
-  ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatDataBegin());
-  ASSERT_EQ("lue.art", std::string(oat_header.GetStoreValueByKey(OatHeader::kImageLocationKey)));
-
-  ASSERT_TRUE(java_lang_dex_file_ != nullptr);
-  const DexFile& dex_file = *java_lang_dex_file_;
-  uint32_t dex_file_checksum = dex_file.GetLocationChecksum();
-  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str(),
-                                                                    &dex_file_checksum);
-  ASSERT_TRUE(oat_dex_file != nullptr);
-  CHECK_EQ(dex_file.GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
-  ScopedObjectAccess soa(Thread::Current());
-  auto pointer_size = class_linker->GetImagePointerSize();
-  for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
-    const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
-    const uint8_t* class_data = dex_file.GetClassData(class_def);
-
-    size_t num_virtual_methods = 0;
-    if (class_data != nullptr) {
-      ClassDataItemIterator it(dex_file, class_data);
-      num_virtual_methods = it.NumVirtualMethods();
-    }
-
-    const char* descriptor = dex_file.GetClassDescriptor(class_def);
-    mirror::Class* klass = class_linker->FindClass(soa.Self(),
-                                                   descriptor,
-                                                   ScopedNullHandle<mirror::ClassLoader>());
-
-    const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(i);
-    CHECK_EQ(mirror::Class::Status::kStatusNotReady, oat_class.GetStatus()) << descriptor;
-    CHECK_EQ(kCompile ? OatClassType::kOatClassAllCompiled : OatClassType::kOatClassNoneCompiled,
-             oat_class.GetType()) << descriptor;
-
-    size_t method_index = 0;
-    for (auto& m : klass->GetDirectMethods(pointer_size)) {
-      CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
-      ++method_index;
-    }
-    size_t visited_virtuals = 0;
-    // TODO We should also check copied methods in this test.
-    for (auto& m : klass->GetDeclaredVirtualMethods(pointer_size)) {
-      if (!klass->IsInterface()) {
-        EXPECT_FALSE(m.IsCopied());
-      }
-      CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
-      ++method_index;
-      ++visited_virtuals;
-    }
-    EXPECT_EQ(visited_virtuals, num_virtual_methods);
-  }
-}
-
-TEST_F(OatTest, OatHeaderSizeCheck) {
-  // If this test is failing and you have to update these constants,
-  // it is time to update OatHeader::kOatVersion
-  EXPECT_EQ(76U, sizeof(OatHeader));
-  EXPECT_EQ(4U, sizeof(OatMethodOffsets));
-  EXPECT_EQ(24U, sizeof(OatQuickMethodHeader));
-  EXPECT_EQ(161 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
-            sizeof(QuickEntryPoints));
-}
-
-TEST_F(OatTest, OatHeaderIsValid) {
-  InstructionSet insn_set = kX86;
-  std::string error_msg;
-  std::unique_ptr<const InstructionSetFeatures> insn_features(
-    InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg));
-  ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
-  std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set,
-                                                          insn_features.get(),
-                                                          0u,
-                                                          nullptr));
-  ASSERT_NE(oat_header.get(), nullptr);
-  ASSERT_TRUE(oat_header->IsValid());
-
-  char* magic = const_cast<char*>(oat_header->GetMagic());
-  strcpy(magic, "");  // bad magic
-  ASSERT_FALSE(oat_header->IsValid());
-  strcpy(magic, "oat\n000");  // bad version
-  ASSERT_FALSE(oat_header->IsValid());
-}
-
-TEST_F(OatTest, EmptyTextSection) {
-  TimingLogger timings("OatTest::EmptyTextSection", false, false);
-
-  // TODO: make selectable.
-  Compiler::Kind compiler_kind = Compiler::kQuick;
-  InstructionSet insn_set = kRuntimeISA;
-  if (insn_set == kArm) insn_set = kThumb2;
-  std::string error_msg;
-  std::vector<std::string> compiler_options;
-  compiler_options.push_back("--compiler-filter=extract");
-  SetupCompiler(compiler_kind, insn_set, compiler_options, /*out*/ &error_msg);
-
-  jobject class_loader;
-  {
-    ScopedObjectAccess soa(Thread::Current());
-    class_loader = LoadDex("Main");
-  }
-  ASSERT_TRUE(class_loader != nullptr);
-  std::vector<const DexFile*> dex_files = GetDexFiles(class_loader);
-  ASSERT_TRUE(!dex_files.empty());
-
-  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-  for (const DexFile* dex_file : dex_files) {
-    ScopedObjectAccess soa(Thread::Current());
-    class_linker->RegisterDexFile(*dex_file,
-                                  soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
-  }
-  compiler_driver_->SetDexFilesForOatFile(dex_files);
-  compiler_driver_->CompileAll(class_loader, dex_files, &timings);
-
-  ScratchFile tmp_oat, tmp_vdex(tmp_oat, ".vdex");
-  SafeMap<std::string, std::string> key_value_store;
-  key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
-  bool success = WriteElf(tmp_vdex.GetFile(), tmp_oat.GetFile(), dex_files, key_value_store, false);
-  ASSERT_TRUE(success);
-
-  std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp_oat.GetFilename(),
-                                                  tmp_oat.GetFilename(),
-                                                  nullptr,
-                                                  nullptr,
-                                                  false,
-                                                  /*low_4gb*/false,
-                                                  nullptr,
-                                                  &error_msg));
-  ASSERT_TRUE(oat_file != nullptr);
-  EXPECT_LT(static_cast<size_t>(oat_file->Size()),
-            static_cast<size_t>(tmp_oat.GetFile()->GetLength()));
-}
-
-static void MaybeModifyDexFileToFail(bool verify, std::unique_ptr<const DexFile>& data) {
-  // If in verify mode (= fail the verifier mode), make sure we fail early. We'll fail already
-  // because of the missing map, but that may lead to out of bounds reads.
-  if (verify) {
-    const_cast<DexFile::Header*>(&data->GetHeader())->checksum_++;
-  }
-}
-
-void OatTest::TestDexFileInput(bool verify, bool low_4gb, bool use_profile) {
-  TimingLogger timings("OatTest::DexFileInput", false, false);
-
-  std::vector<const char*> input_filenames;
-
-  ScratchFile dex_file1;
-  TestDexFileBuilder builder1;
-  builder1.AddField("Lsome.TestClass;", "int", "someField");
-  builder1.AddMethod("Lsome.TestClass;", "()I", "foo");
-  std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());
-
-  MaybeModifyDexFileToFail(verify, dex_file1_data);
-
-  bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(),
-                                                 dex_file1_data->GetHeader().file_size_);
-  ASSERT_TRUE(success);
-  success = dex_file1.GetFile()->Flush() == 0;
-  ASSERT_TRUE(success);
-  input_filenames.push_back(dex_file1.GetFilename().c_str());
-
-  ScratchFile dex_file2;
-  TestDexFileBuilder builder2;
-  builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField");
-  builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar");
-  std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());
-
-  MaybeModifyDexFileToFail(verify, dex_file2_data);
-
-  success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(),
-                                            dex_file2_data->GetHeader().file_size_);
-  ASSERT_TRUE(success);
-  success = dex_file2.GetFile()->Flush() == 0;
-  ASSERT_TRUE(success);
-  input_filenames.push_back(dex_file2.GetFilename().c_str());
-
-  ScratchFile oat_file, vdex_file(oat_file, ".vdex");
-  SafeMap<std::string, std::string> key_value_store;
-  key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
-  std::unique_ptr<ProfileCompilationInfo>
-      profile_compilation_info(use_profile ? new ProfileCompilationInfo() : nullptr);
-  success = WriteElf(vdex_file.GetFile(),
-                     oat_file.GetFile(),
-                     input_filenames,
-                     key_value_store,
-                     verify,
-                     profile_compilation_info.get());
-
-  // In verify mode, we expect failure.
-  if (verify) {
-    ASSERT_FALSE(success);
-    return;
-  }
-
-  ASSERT_TRUE(success);
-
-  std::string error_msg;
-  std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
-                                                         oat_file.GetFilename(),
-                                                         nullptr,
-                                                         nullptr,
-                                                         false,
-                                                         low_4gb,
-                                                         nullptr,
-                                                         &error_msg));
-  if (low_4gb) {
-    uintptr_t begin = reinterpret_cast<uintptr_t>(opened_oat_file->Begin());
-    EXPECT_EQ(begin, static_cast<uint32_t>(begin));
-  }
-  ASSERT_TRUE(opened_oat_file != nullptr);
-  ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
-  std::unique_ptr<const DexFile> opened_dex_file1 =
-      opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
-  std::unique_ptr<const DexFile> opened_dex_file2 =
-      opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
-
-  ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
-  ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
-                      &opened_dex_file1->GetHeader(),
-                      dex_file1_data->GetHeader().file_size_));
-  ASSERT_EQ(dex_file1_data->GetLocation(), opened_dex_file1->GetLocation());
-
-  ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
-  ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
-                      &opened_dex_file2->GetHeader(),
-                      dex_file2_data->GetHeader().file_size_));
-  ASSERT_EQ(dex_file2_data->GetLocation(), opened_dex_file2->GetLocation());
-}
-
-TEST_F(OatTest, DexFileInputCheckOutput) {
-  TestDexFileInput(/*verify*/false, /*low_4gb*/false, /*use_profile*/false);
-}
-
-TEST_F(OatTest, DexFileInputCheckOutputLow4GB) {
-  TestDexFileInput(/*verify*/false, /*low_4gb*/true, /*use_profile*/false);
-}
-
-TEST_F(OatTest, DexFileInputCheckVerifier) {
-  TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/false);
-}
-
-TEST_F(OatTest, DexFileFailsVerifierWithLayout) {
-  TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/true);
-}
-
-void OatTest::TestZipFileInput(bool verify) {
-  TimingLogger timings("OatTest::DexFileInput", false, false);
-
-  ScratchFile zip_file;
-  ZipBuilder zip_builder(zip_file.GetFile());
-
-  ScratchFile dex_file1;
-  TestDexFileBuilder builder1;
-  builder1.AddField("Lsome.TestClass;", "long", "someField");
-  builder1.AddMethod("Lsome.TestClass;", "()D", "foo");
-  std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());
-
-  MaybeModifyDexFileToFail(verify, dex_file1_data);
-
-  bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(),
-                                                 dex_file1_data->GetHeader().file_size_);
-  ASSERT_TRUE(success);
-  success = dex_file1.GetFile()->Flush() == 0;
-  ASSERT_TRUE(success);
-  success = zip_builder.AddFile("classes.dex",
-                                &dex_file1_data->GetHeader(),
-                                dex_file1_data->GetHeader().file_size_);
-  ASSERT_TRUE(success);
-
-  ScratchFile dex_file2;
-  TestDexFileBuilder builder2;
-  builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField");
-  builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar");
-  std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());
-
-  MaybeModifyDexFileToFail(verify, dex_file2_data);
-
-  success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(),
-                                            dex_file2_data->GetHeader().file_size_);
-  ASSERT_TRUE(success);
-  success = dex_file2.GetFile()->Flush() == 0;
-  ASSERT_TRUE(success);
-  success = zip_builder.AddFile("classes2.dex",
-                                &dex_file2_data->GetHeader(),
-                                dex_file2_data->GetHeader().file_size_);
-  ASSERT_TRUE(success);
-
-  success = zip_builder.Finish();
-  ASSERT_TRUE(success) << strerror(errno);
-
-  SafeMap<std::string, std::string> key_value_store;
-  key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
-  {
-    // Test using the AddDexFileSource() interface with the zip file.
-    std::vector<const char*> input_filenames { zip_file.GetFilename().c_str() };  // NOLINT [readability/braces] [4]
-
-    ScratchFile oat_file, vdex_file(oat_file, ".vdex");
-    success = WriteElf(vdex_file.GetFile(), oat_file.GetFile(), input_filenames,
-                       key_value_store, verify, /*profile_compilation_info*/nullptr);
-
-    if (verify) {
-      ASSERT_FALSE(success);
-    } else {
-      ASSERT_TRUE(success);
-
-      std::string error_msg;
-      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
-                                                             oat_file.GetFilename(),
-                                                             nullptr,
-                                                             nullptr,
-                                                             false,
-                                                             /*low_4gb*/false,
-                                                             nullptr,
-                                                             &error_msg));
-      ASSERT_TRUE(opened_oat_file != nullptr);
-      ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
-      std::unique_ptr<const DexFile> opened_dex_file1 =
-          opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
-      std::unique_ptr<const DexFile> opened_dex_file2 =
-          opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
-
-      ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
-      ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
-                          &opened_dex_file1->GetHeader(),
-                          dex_file1_data->GetHeader().file_size_));
-      ASSERT_EQ(DexFile::GetMultiDexLocation(0, zip_file.GetFilename().c_str()),
-                opened_dex_file1->GetLocation());
-
-      ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
-      ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
-                          &opened_dex_file2->GetHeader(),
-                          dex_file2_data->GetHeader().file_size_));
-      ASSERT_EQ(DexFile::GetMultiDexLocation(1, zip_file.GetFilename().c_str()),
-                opened_dex_file2->GetLocation());
-    }
-  }
-
-  {
-    // Test using the AddZipDexFileSource() interface with the zip file handle.
-    File zip_fd(dup(zip_file.GetFd()), /* check_usage */ false);
-    ASSERT_NE(-1, zip_fd.Fd());
-
-    ScratchFile oat_file, vdex_file(oat_file, ".vdex");
-    success = WriteElf(vdex_file.GetFile(),
-                       oat_file.GetFile(),
-                       std::move(zip_fd),
-                       zip_file.GetFilename().c_str(),
-                       key_value_store,
-                       verify);
-    if (verify) {
-      ASSERT_FALSE(success);
-    } else {
-      ASSERT_TRUE(success);
-
-      std::string error_msg;
-      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
-                                                             oat_file.GetFilename(),
-                                                             nullptr,
-                                                             nullptr,
-                                                             false,
-                                                             /*low_4gb*/false,
-                                                             nullptr,
-                                                             &error_msg));
-      ASSERT_TRUE(opened_oat_file != nullptr);
-      ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
-      std::unique_ptr<const DexFile> opened_dex_file1 =
-          opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
-      std::unique_ptr<const DexFile> opened_dex_file2 =
-          opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
-
-      ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
-      ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
-                          &opened_dex_file1->GetHeader(),
-                          dex_file1_data->GetHeader().file_size_));
-      ASSERT_EQ(DexFile::GetMultiDexLocation(0, zip_file.GetFilename().c_str()),
-                opened_dex_file1->GetLocation());
-
-      ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
-      ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
-                          &opened_dex_file2->GetHeader(),
-                          dex_file2_data->GetHeader().file_size_));
-      ASSERT_EQ(DexFile::GetMultiDexLocation(1, zip_file.GetFilename().c_str()),
-                opened_dex_file2->GetLocation());
-    }
-  }
-}
-
-TEST_F(OatTest, ZipFileInputCheckOutput) {
-  TestZipFileInput(false);
-}
-
-TEST_F(OatTest, ZipFileInputCheckVerifier) {
-  TestZipFileInput(true);
-}
-
-void OatTest::TestZipFileInputWithEmptyDex() {
-  ScratchFile zip_file;
-  ZipBuilder zip_builder(zip_file.GetFile());
-  bool success = zip_builder.AddFile("classes.dex", nullptr, 0);
-  ASSERT_TRUE(success);
-  success = zip_builder.Finish();
-  ASSERT_TRUE(success) << strerror(errno);
-
-  SafeMap<std::string, std::string> key_value_store;
-  key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
-  std::vector<const char*> input_filenames { zip_file.GetFilename().c_str() };  // NOLINT [readability/braces] [4]
-  ScratchFile oat_file, vdex_file(oat_file, ".vdex");
-  std::unique_ptr<ProfileCompilationInfo> profile_compilation_info(new ProfileCompilationInfo());
-  success = WriteElf(vdex_file.GetFile(), oat_file.GetFile(), input_filenames,
-                     key_value_store, /*verify*/false, profile_compilation_info.get());
-  ASSERT_FALSE(success);
-}
-
-TEST_F(OatTest, ZipFileInputWithEmptyDex) {
-  TestZipFileInputWithEmptyDex();
-}
-
-TEST_F(OatTest, UpdateChecksum) {
-  InstructionSet insn_set = kX86;
-  std::string error_msg;
-  std::unique_ptr<const InstructionSetFeatures> insn_features(
-    InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg));
-  ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
-  std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set,
-                                                          insn_features.get(),
-                                                          0u,
-                                                          nullptr));
-  // The starting adler32 value is 1.
-  EXPECT_EQ(1U, oat_header->GetChecksum());
-
-  oat_header->UpdateChecksum(OatHeader::kOatMagic, sizeof(OatHeader::kOatMagic));
-  EXPECT_EQ(64291151U, oat_header->GetChecksum());
-
-  // Make sure that null data does not reset the checksum.
-  oat_header->UpdateChecksum(nullptr, 0);
-  EXPECT_EQ(64291151U, oat_header->GetChecksum());
-
-  oat_header->UpdateChecksum(OatHeader::kOatMagic, sizeof(OatHeader::kOatMagic));
-  EXPECT_EQ(216138397U, oat_header->GetChecksum());
-}
-
-}  // namespace art
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
deleted file mode 100644
index ce1b755..0000000
--- a/compiler/oat_writer.cc
+++ /dev/null
@@ -1,3632 +0,0 @@
-/*
- * Copyright (C) 2011 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 "oat_writer.h"
-
-#include <unistd.h>
-#include <zlib.h>
-
-#include "arch/arm64/instruction_set_features_arm64.h"
-#include "art_method-inl.h"
-#include "base/allocator.h"
-#include "base/bit_vector-inl.h"
-#include "base/enums.h"
-#include "base/file_magic.h"
-#include "base/stl_util.h"
-#include "base/unix_file/fd_file.h"
-#include "class_linker.h"
-#include "class_table-inl.h"
-#include "compiled_method.h"
-#include "debug/method_debug_info.h"
-#include "dex/verification_results.h"
-#include "dex_file-inl.h"
-#include "dex_file_types.h"
-#include "dexlayout.h"
-#include "driver/compiler_driver-inl.h"
-#include "driver/compiler_options.h"
-#include "gc/space/image_space.h"
-#include "gc/space/space.h"
-#include "handle_scope-inl.h"
-#include "image_writer.h"
-#include "linker/buffered_output_stream.h"
-#include "linker/file_output_stream.h"
-#include "linker/method_bss_mapping_encoder.h"
-#include "linker/multi_oat_relative_patcher.h"
-#include "linker/output_stream.h"
-#include "mirror/array.h"
-#include "mirror/class_loader.h"
-#include "mirror/dex_cache-inl.h"
-#include "mirror/object-inl.h"
-#include "oat_quick_method_header.h"
-#include "os.h"
-#include "safe_map.h"
-#include "scoped_thread_state_change-inl.h"
-#include "type_lookup_table.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
-#include "vdex_file.h"
-#include "verifier/verifier_deps.h"
-#include "zip_archive.h"
-
-namespace art {
-
-namespace {  // anonymous namespace
-
-// If we write dex layout info in the oat file.
-static constexpr bool kWriteDexLayoutInfo = true;
-
-typedef DexFile::Header __attribute__((aligned(1))) UnalignedDexFileHeader;
-
-const UnalignedDexFileHeader* AsUnalignedDexFileHeader(const uint8_t* raw_data) {
-    return reinterpret_cast<const UnalignedDexFileHeader*>(raw_data);
-}
-
-class ChecksumUpdatingOutputStream : public OutputStream {
- public:
-  ChecksumUpdatingOutputStream(OutputStream* out, OatHeader* oat_header)
-      : OutputStream(out->GetLocation()), out_(out), oat_header_(oat_header) { }
-
-  bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE {
-    oat_header_->UpdateChecksum(buffer, byte_count);
-    return out_->WriteFully(buffer, byte_count);
-  }
-
-  off_t Seek(off_t offset, Whence whence) OVERRIDE {
-    return out_->Seek(offset, whence);
-  }
-
-  bool Flush() OVERRIDE {
-    return out_->Flush();
-  }
-
- private:
-  OutputStream* const out_;
-  OatHeader* const oat_header_;
-};
-
-inline uint32_t CodeAlignmentSize(uint32_t header_offset, const CompiledMethod& compiled_method) {
-  // We want to align the code rather than the preheader.
-  uint32_t unaligned_code_offset = header_offset + sizeof(OatQuickMethodHeader);
-  uint32_t aligned_code_offset =  compiled_method.AlignCode(unaligned_code_offset);
-  return aligned_code_offset - unaligned_code_offset;
-}
-
-}  // anonymous namespace
-
-// Defines the location of the raw dex file to write.
-class OatWriter::DexFileSource {
- public:
-  enum Type {
-    kNone,
-    kZipEntry,
-    kRawFile,
-    kRawData,
-  };
-
-  explicit DexFileSource(ZipEntry* zip_entry)
-      : type_(kZipEntry), source_(zip_entry) {
-    DCHECK(source_ != nullptr);
-  }
-
-  explicit DexFileSource(File* raw_file)
-      : type_(kRawFile), source_(raw_file) {
-    DCHECK(source_ != nullptr);
-  }
-
-  explicit DexFileSource(const uint8_t* dex_file)
-      : type_(kRawData), source_(dex_file) {
-    DCHECK(source_ != nullptr);
-  }
-
-  Type GetType() const { return type_; }
-  bool IsZipEntry() const { return type_ == kZipEntry; }
-  bool IsRawFile() const { return type_ == kRawFile; }
-  bool IsRawData() const { return type_ == kRawData; }
-
-  ZipEntry* GetZipEntry() const {
-    DCHECK(IsZipEntry());
-    DCHECK(source_ != nullptr);
-    return static_cast<ZipEntry*>(const_cast<void*>(source_));
-  }
-
-  File* GetRawFile() const {
-    DCHECK(IsRawFile());
-    DCHECK(source_ != nullptr);
-    return static_cast<File*>(const_cast<void*>(source_));
-  }
-
-  const uint8_t* GetRawData() const {
-    DCHECK(IsRawData());
-    DCHECK(source_ != nullptr);
-    return static_cast<const uint8_t*>(source_);
-  }
-
-  void Clear() {
-    type_ = kNone;
-    source_ = nullptr;
-  }
-
- private:
-  Type type_;
-  const void* source_;
-};
-
-// OatClassHeader is the header only part of the oat class that is required even when compilation
-// is not enabled.
-class OatWriter::OatClassHeader {
- public:
-  OatClassHeader(uint32_t offset,
-                 uint32_t num_non_null_compiled_methods,
-                 uint32_t num_methods,
-                 mirror::Class::Status status)
-      : status_(status),
-        offset_(offset) {
-    // We just arbitrarily say that 0 methods means kOatClassNoneCompiled and that we won't use
-    // kOatClassAllCompiled unless there is at least one compiled method. This means in an
-    // interpreter only system, we can assert that all classes are kOatClassNoneCompiled.
-    if (num_non_null_compiled_methods == 0) {
-      type_ = kOatClassNoneCompiled;
-    } else if (num_non_null_compiled_methods == num_methods) {
-      type_ = kOatClassAllCompiled;
-    } else {
-      type_ = kOatClassSomeCompiled;
-    }
-  }
-
-  bool Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const;
-
-  static size_t SizeOf() {
-    return sizeof(status_) + sizeof(type_);
-  }
-
-  // Data to write.
-  static_assert(mirror::Class::Status::kStatusMax < (1 << 16), "class status won't fit in 16bits");
-  int16_t status_;
-
-  static_assert(OatClassType::kOatClassMax < (1 << 16), "oat_class type won't fit in 16bits");
-  uint16_t type_;
-
-  // Offset of start of OatClass from beginning of OatHeader. It is
-  // used to validate file position when writing.
-  uint32_t offset_;
-};
-
-// The actual oat class body contains the information about compiled methods. It is only required
-// for compiler filters that have any compilation.
-class OatWriter::OatClass {
- public:
-  OatClass(const dchecked_vector<CompiledMethod*>& compiled_methods,
-           uint32_t compiled_methods_with_code,
-           uint16_t oat_class_type);
-  OatClass(OatClass&& src) = default;
-  size_t SizeOf() const;
-  bool Write(OatWriter* oat_writer, OutputStream* out) const;
-
-  CompiledMethod* GetCompiledMethod(size_t class_def_method_index) const {
-    return compiled_methods_[class_def_method_index];
-  }
-
-  // CompiledMethods for each class_def_method_index, or null if no method is available.
-  dchecked_vector<CompiledMethod*> compiled_methods_;
-
-  // Offset from OatClass::offset_ to the OatMethodOffsets for the
-  // class_def_method_index. If 0, it means the corresponding
-  // CompiledMethod entry in OatClass::compiled_methods_ should be
-  // null and that the OatClass::type_ should be kOatClassBitmap.
-  dchecked_vector<uint32_t> oat_method_offsets_offsets_from_oat_class_;
-
-  // Data to write.
-  uint32_t method_bitmap_size_;
-
-  // bit vector indexed by ClassDef method index. When
-  // OatClassType::type_ is kOatClassBitmap, a set bit indicates the
-  // method has an OatMethodOffsets in methods_offsets_, otherwise
-  // the entry was ommited to save space. If OatClassType::type_ is
-  // not is kOatClassBitmap, the bitmap will be null.
-  std::unique_ptr<BitVector> method_bitmap_;
-
-  // OatMethodOffsets and OatMethodHeaders for each CompiledMethod
-  // present in the OatClass. Note that some may be missing if
-  // OatClass::compiled_methods_ contains null values (and
-  // oat_method_offsets_offsets_from_oat_class_ should contain 0
-  // values in this case).
-  dchecked_vector<OatMethodOffsets> method_offsets_;
-  dchecked_vector<OatQuickMethodHeader> method_headers_;
-
- private:
-  size_t GetMethodOffsetsRawSize() const {
-    return method_offsets_.size() * sizeof(method_offsets_[0]);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(OatClass);
-};
-
-class OatWriter::OatDexFile {
- public:
-  OatDexFile(const char* dex_file_location,
-             DexFileSource source,
-             CreateTypeLookupTable create_type_lookup_table);
-  OatDexFile(OatDexFile&& src) = default;
-
-  const char* GetLocation() const {
-    return dex_file_location_data_;
-  }
-
-  size_t SizeOf() const;
-  bool Write(OatWriter* oat_writer, OutputStream* out) const;
-  bool WriteClassOffsets(OatWriter* oat_writer, OutputStream* out);
-
-  size_t GetClassOffsetsRawSize() const {
-    return class_offsets_.size() * sizeof(class_offsets_[0]);
-  }
-
-  // The source of the dex file.
-  DexFileSource source_;
-
-  // Whether to create the type lookup table.
-  CreateTypeLookupTable create_type_lookup_table_;
-
-  // Dex file size. Initialized when writing the dex file.
-  size_t dex_file_size_;
-
-  // Offset of start of OatDexFile from beginning of OatHeader. It is
-  // used to validate file position when writing.
-  size_t offset_;
-
-  // Data to write.
-  uint32_t dex_file_location_size_;
-  const char* dex_file_location_data_;
-  uint32_t dex_file_location_checksum_;
-  uint32_t dex_file_offset_;
-  uint32_t class_offsets_offset_;
-  uint32_t lookup_table_offset_;
-  uint32_t method_bss_mapping_offset_;
-  uint32_t dex_sections_layout_offset_;
-
-  // Data to write to a separate section.
-  dchecked_vector<uint32_t> class_offsets_;
-
-  // Dex section layout info to serialize.
-  DexLayoutSections dex_sections_layout_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(OatDexFile);
-};
-
-#define DCHECK_OFFSET() \
-  DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out->Seek(0, kSeekCurrent)) \
-    << "file_offset=" << file_offset << " relative_offset=" << relative_offset
-
-#define DCHECK_OFFSET_() \
-  DCHECK_EQ(static_cast<off_t>(file_offset + offset_), out->Seek(0, kSeekCurrent)) \
-    << "file_offset=" << file_offset << " offset_=" << offset_
-
-OatWriter::OatWriter(bool compiling_boot_image, TimingLogger* timings, ProfileCompilationInfo* info)
-  : write_state_(WriteState::kAddingDexFileSources),
-    timings_(timings),
-    raw_dex_files_(),
-    zip_archives_(),
-    zipped_dex_files_(),
-    zipped_dex_file_locations_(),
-    compiler_driver_(nullptr),
-    image_writer_(nullptr),
-    compiling_boot_image_(compiling_boot_image),
-    dex_files_(nullptr),
-    vdex_size_(0u),
-    vdex_dex_files_offset_(0u),
-    vdex_verifier_deps_offset_(0u),
-    vdex_quickening_info_offset_(0u),
-    oat_size_(0u),
-    bss_start_(0u),
-    bss_size_(0u),
-    bss_methods_offset_(0u),
-    bss_roots_offset_(0u),
-    bss_method_entry_references_(),
-    bss_method_entries_(),
-    bss_type_entries_(),
-    bss_string_entries_(),
-    map_boot_image_tables_to_bss_(false),
-    oat_data_offset_(0u),
-    oat_header_(nullptr),
-    size_vdex_header_(0),
-    size_vdex_checksums_(0),
-    size_dex_file_alignment_(0),
-    size_executable_offset_alignment_(0),
-    size_oat_header_(0),
-    size_oat_header_key_value_store_(0),
-    size_dex_file_(0),
-    size_verifier_deps_(0),
-    size_verifier_deps_alignment_(0),
-    size_quickening_info_(0),
-    size_quickening_info_alignment_(0),
-    size_interpreter_to_interpreter_bridge_(0),
-    size_interpreter_to_compiled_code_bridge_(0),
-    size_jni_dlsym_lookup_(0),
-    size_quick_generic_jni_trampoline_(0),
-    size_quick_imt_conflict_trampoline_(0),
-    size_quick_resolution_trampoline_(0),
-    size_quick_to_interpreter_bridge_(0),
-    size_trampoline_alignment_(0),
-    size_method_header_(0),
-    size_code_(0),
-    size_code_alignment_(0),
-    size_relative_call_thunks_(0),
-    size_misc_thunks_(0),
-    size_vmap_table_(0),
-    size_method_info_(0),
-    size_oat_dex_file_location_size_(0),
-    size_oat_dex_file_location_data_(0),
-    size_oat_dex_file_location_checksum_(0),
-    size_oat_dex_file_offset_(0),
-    size_oat_dex_file_class_offsets_offset_(0),
-    size_oat_dex_file_lookup_table_offset_(0),
-    size_oat_dex_file_dex_layout_sections_offset_(0),
-    size_oat_dex_file_dex_layout_sections_(0),
-    size_oat_dex_file_dex_layout_sections_alignment_(0),
-    size_oat_dex_file_method_bss_mapping_offset_(0),
-    size_oat_lookup_table_alignment_(0),
-    size_oat_lookup_table_(0),
-    size_oat_class_offsets_alignment_(0),
-    size_oat_class_offsets_(0),
-    size_oat_class_type_(0),
-    size_oat_class_status_(0),
-    size_oat_class_method_bitmaps_(0),
-    size_oat_class_method_offsets_(0),
-    size_method_bss_mappings_(0u),
-    relative_patcher_(nullptr),
-    absolute_patch_locations_(),
-    profile_compilation_info_(info) {
-}
-
-bool OatWriter::AddDexFileSource(const char* filename,
-                                 const char* location,
-                                 CreateTypeLookupTable create_type_lookup_table) {
-  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
-  uint32_t magic;
-  std::string error_msg;
-  File fd = OpenAndReadMagic(filename, &magic, &error_msg);
-  if (fd.Fd() == -1) {
-    PLOG(ERROR) << "Failed to read magic number from dex file: '" << filename << "'";
-    return false;
-  } else if (IsDexMagic(magic)) {
-    // The file is open for reading, not writing, so it's OK to let the File destructor
-    // close it without checking for explicit Close(), so pass checkUsage = false.
-    raw_dex_files_.emplace_back(new File(fd.Release(), location, /* checkUsage */ false));
-    oat_dex_files_.emplace_back(location,
-                                DexFileSource(raw_dex_files_.back().get()),
-                                create_type_lookup_table);
-  } else if (IsZipMagic(magic)) {
-    if (!AddZippedDexFilesSource(std::move(fd), location, create_type_lookup_table)) {
-      return false;
-    }
-  } else {
-    LOG(ERROR) << "Expected valid zip or dex file: '" << filename << "'";
-    return false;
-  }
-  return true;
-}
-
-// Add dex file source(s) from a zip file specified by a file handle.
-bool OatWriter::AddZippedDexFilesSource(File&& zip_fd,
-                                        const char* location,
-                                        CreateTypeLookupTable create_type_lookup_table) {
-  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
-  std::string error_msg;
-  zip_archives_.emplace_back(ZipArchive::OpenFromFd(zip_fd.Release(), location, &error_msg));
-  ZipArchive* zip_archive = zip_archives_.back().get();
-  if (zip_archive == nullptr) {
-    LOG(ERROR) << "Failed to open zip from file descriptor for '" << location << "': "
-        << error_msg;
-    return false;
-  }
-  for (size_t i = 0; ; ++i) {
-    std::string entry_name = DexFile::GetMultiDexClassesDexName(i);
-    std::unique_ptr<ZipEntry> entry(zip_archive->Find(entry_name.c_str(), &error_msg));
-    if (entry == nullptr) {
-      break;
-    }
-    zipped_dex_files_.push_back(std::move(entry));
-    zipped_dex_file_locations_.push_back(DexFile::GetMultiDexLocation(i, location));
-    const char* full_location = zipped_dex_file_locations_.back().c_str();
-    oat_dex_files_.emplace_back(full_location,
-                                DexFileSource(zipped_dex_files_.back().get()),
-                                create_type_lookup_table);
-  }
-  if (zipped_dex_file_locations_.empty()) {
-    LOG(ERROR) << "No dex files in zip file '" << location << "': " << error_msg;
-    return false;
-  }
-  return true;
-}
-
-// Add dex file source(s) from a vdex file specified by a file handle.
-bool OatWriter::AddVdexDexFilesSource(const VdexFile& vdex_file,
-                                      const char* location,
-                                      CreateTypeLookupTable create_type_lookup_table) {
-  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
-  const uint8_t* current_dex_data = nullptr;
-  for (size_t i = 0; i < vdex_file.GetHeader().GetNumberOfDexFiles(); ++i) {
-    current_dex_data = vdex_file.GetNextDexFileData(current_dex_data);
-    if (current_dex_data == nullptr) {
-      LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
-      return false;
-    }
-    if (!DexFile::IsMagicValid(current_dex_data)) {
-      LOG(ERROR) << "Invalid magic in vdex file created from " << location;
-      return false;
-    }
-    // We used `zipped_dex_file_locations_` to keep the strings in memory.
-    zipped_dex_file_locations_.push_back(DexFile::GetMultiDexLocation(i, location));
-    const char* full_location = zipped_dex_file_locations_.back().c_str();
-    oat_dex_files_.emplace_back(full_location,
-                                DexFileSource(current_dex_data),
-                                create_type_lookup_table);
-    oat_dex_files_.back().dex_file_location_checksum_ = vdex_file.GetLocationChecksum(i);
-  }
-
-  if (vdex_file.GetNextDexFileData(current_dex_data) != nullptr) {
-    LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
-    return false;
-  }
-
-  if (oat_dex_files_.empty()) {
-    LOG(ERROR) << "No dex files in vdex file created from " << location;
-    return false;
-  }
-  return true;
-}
-
-// Add dex file source from raw memory.
-bool OatWriter::AddRawDexFileSource(const ArrayRef<const uint8_t>& data,
-                                    const char* location,
-                                    uint32_t location_checksum,
-                                    CreateTypeLookupTable create_type_lookup_table) {
-  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
-  if (data.size() < sizeof(DexFile::Header)) {
-    LOG(ERROR) << "Provided data is shorter than dex file header. size: "
-               << data.size() << " File: " << location;
-    return false;
-  }
-  if (!ValidateDexFileHeader(data.data(), location)) {
-    return false;
-  }
-  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(data.data());
-  if (data.size() < header->file_size_) {
-    LOG(ERROR) << "Truncated dex file data. Data size: " << data.size()
-               << " file size from header: " << header->file_size_ << " File: " << location;
-    return false;
-  }
-
-  oat_dex_files_.emplace_back(location, DexFileSource(data.data()), create_type_lookup_table);
-  oat_dex_files_.back().dex_file_location_checksum_ = location_checksum;
-  return true;
-}
-
-dchecked_vector<std::string> OatWriter::GetSourceLocations() const {
-  dchecked_vector<std::string> locations;
-  locations.reserve(oat_dex_files_.size());
-  for (const OatDexFile& oat_dex_file : oat_dex_files_) {
-    locations.push_back(oat_dex_file.GetLocation());
-  }
-  return locations;
-}
-
-bool OatWriter::MayHaveCompiledMethods() const {
-  return CompilerFilter::IsAnyCompilationEnabled(
-      GetCompilerDriver()->GetCompilerOptions().GetCompilerFilter());
-}
-
-bool OatWriter::WriteAndOpenDexFiles(
-    File* vdex_file,
-    OutputStream* oat_rodata,
-    InstructionSet instruction_set,
-    const InstructionSetFeatures* instruction_set_features,
-    SafeMap<std::string, std::string>* key_value_store,
-    bool verify,
-    bool update_input_vdex,
-    /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
-    /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
-  CHECK(write_state_ == WriteState::kAddingDexFileSources);
-
-  // Record the ELF rodata section offset, i.e. the beginning of the OAT data.
-  if (!RecordOatDataOffset(oat_rodata)) {
-     return false;
-  }
-
-  std::unique_ptr<MemMap> dex_files_map;
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-
-  // Initialize VDEX and OAT headers.
-  if (kIsVdexEnabled) {
-    // Reserve space for Vdex header and checksums.
-    vdex_size_ = sizeof(VdexFile::Header) + oat_dex_files_.size() * sizeof(VdexFile::VdexChecksum);
-  }
-  oat_size_ = InitOatHeader(instruction_set,
-                            instruction_set_features,
-                            dchecked_integral_cast<uint32_t>(oat_dex_files_.size()),
-                            key_value_store);
-
-  ChecksumUpdatingOutputStream checksum_updating_rodata(oat_rodata, oat_header_.get());
-
-  if (kIsVdexEnabled) {
-    std::unique_ptr<BufferedOutputStream> vdex_out =
-        std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
-    // Write DEX files into VDEX, mmap and open them.
-    if (!WriteDexFiles(vdex_out.get(), vdex_file, update_input_vdex) ||
-        !OpenDexFiles(vdex_file, verify, &dex_files_map, &dex_files)) {
-      return false;
-    }
-  } else {
-    DCHECK(!update_input_vdex);
-    // Write DEX files into OAT, mmap and open them.
-    if (!WriteDexFiles(oat_rodata, vdex_file, update_input_vdex) ||
-        !OpenDexFiles(vdex_file, verify, &dex_files_map, &dex_files)) {
-      return false;
-    }
-
-    // Do a bulk checksum update for Dex[]. Doing it piece by piece would be
-    // difficult because we're not using the OutputStream directly.
-    if (!oat_dex_files_.empty()) {
-      size_t size = oat_size_ - oat_dex_files_[0].dex_file_offset_;
-      oat_header_->UpdateChecksum(dex_files_map->Begin(), size);
-    }
-  }
-
-  // Write type lookup tables into the oat file.
-  if (!WriteTypeLookupTables(&checksum_updating_rodata, dex_files)) {
-    return false;
-  }
-
-  // Write dex layout sections into the oat file.
-  if (!WriteDexLayoutSections(&checksum_updating_rodata, dex_files)) {
-    return false;
-  }
-
-  *opened_dex_files_map = std::move(dex_files_map);
-  *opened_dex_files = std::move(dex_files);
-  write_state_ = WriteState::kPrepareLayout;
-  return true;
-}
-
-void OatWriter::PrepareLayout(linker::MultiOatRelativePatcher* relative_patcher) {
-  CHECK(write_state_ == WriteState::kPrepareLayout);
-
-  relative_patcher_ = relative_patcher;
-  SetMultiOatRelativePatcherAdjustment();
-
-  if (compiling_boot_image_) {
-    CHECK(image_writer_ != nullptr);
-  }
-  InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
-  CHECK_EQ(instruction_set, oat_header_->GetInstructionSet());
-
-  {
-    TimingLogger::ScopedTiming split("InitBssLayout", timings_);
-    InitBssLayout(instruction_set);
-  }
-
-  uint32_t offset = oat_size_;
-  {
-    TimingLogger::ScopedTiming split("InitClassOffsets", timings_);
-    offset = InitClassOffsets(offset);
-  }
-  {
-    TimingLogger::ScopedTiming split("InitOatClasses", timings_);
-    offset = InitOatClasses(offset);
-  }
-  {
-    TimingLogger::ScopedTiming split("InitMethodBssMappings", timings_);
-    offset = InitMethodBssMappings(offset);
-  }
-  {
-    TimingLogger::ScopedTiming split("InitOatMaps", timings_);
-    offset = InitOatMaps(offset);
-  }
-  {
-    TimingLogger::ScopedTiming split("InitOatDexFiles", timings_);
-    oat_header_->SetOatDexFilesOffset(offset);
-    offset = InitOatDexFiles(offset);
-  }
-  {
-    TimingLogger::ScopedTiming split("InitOatCode", timings_);
-    offset = InitOatCode(offset);
-  }
-  {
-    TimingLogger::ScopedTiming split("InitOatCodeDexFiles", timings_);
-    offset = InitOatCodeDexFiles(offset);
-  }
-  oat_size_ = offset;
-  bss_start_ = (bss_size_ != 0u) ? RoundUp(oat_size_, kPageSize) : 0u;
-
-  CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
-  if (compiling_boot_image_) {
-    CHECK_EQ(image_writer_ != nullptr,
-             oat_header_->GetStoreValueByKey(OatHeader::kImageLocationKey) == nullptr);
-  }
-
-  write_state_ = WriteState::kWriteRoData;
-}
-
-OatWriter::~OatWriter() {
-}
-
-class OatWriter::DexMethodVisitor {
- public:
-  DexMethodVisitor(OatWriter* writer, size_t offset)
-      : writer_(writer),
-        offset_(offset),
-        dex_file_(nullptr),
-        class_def_index_(dex::kDexNoIndex) {}
-
-  virtual bool StartClass(const DexFile* dex_file, size_t class_def_index) {
-    DCHECK(dex_file_ == nullptr);
-    DCHECK_EQ(class_def_index_, dex::kDexNoIndex);
-    dex_file_ = dex_file;
-    class_def_index_ = class_def_index;
-    return true;
-  }
-
-  virtual bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) = 0;
-
-  virtual bool EndClass() {
-    if (kIsDebugBuild) {
-      dex_file_ = nullptr;
-      class_def_index_ = dex::kDexNoIndex;
-    }
-    return true;
-  }
-
-  size_t GetOffset() const {
-    return offset_;
-  }
-
- protected:
-  virtual ~DexMethodVisitor() { }
-
-  OatWriter* const writer_;
-
-  // The offset is usually advanced for each visited method by the derived class.
-  size_t offset_;
-
-  // The dex file and class def index are set in StartClass().
-  const DexFile* dex_file_;
-  size_t class_def_index_;
-};
-
-class OatWriter::OatDexMethodVisitor : public DexMethodVisitor {
- public:
-  OatDexMethodVisitor(OatWriter* writer, size_t offset)
-      : DexMethodVisitor(writer, offset),
-        oat_class_index_(0u),
-        method_offsets_index_(0u) {}
-
-  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE {
-    DexMethodVisitor::StartClass(dex_file, class_def_index);
-    if (kIsDebugBuild && writer_->MayHaveCompiledMethods()) {
-      // There are no oat classes if there aren't any compiled methods.
-      CHECK_LT(oat_class_index_, writer_->oat_classes_.size());
-    }
-    method_offsets_index_ = 0u;
-    return true;
-  }
-
-  bool EndClass() OVERRIDE {
-    ++oat_class_index_;
-    return DexMethodVisitor::EndClass();
-  }
-
- protected:
-  size_t oat_class_index_;
-  size_t method_offsets_index_;
-};
-
-static bool HasCompiledCode(const CompiledMethod* method) {
-  // The dextodexcompiler puts the quickening info table into the CompiledMethod
-  // for simplicity. For such methods, we will emit an OatQuickMethodHeader
-  // only when vdex is disabled.
-  return method != nullptr && (!method->GetQuickCode().empty() || !kIsVdexEnabled);
-}
-
-static bool HasQuickeningInfo(const CompiledMethod* method) {
-  return method != nullptr && method->GetQuickCode().empty() && !method->GetVmapTable().empty();
-}
-
-class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
- public:
-  explicit InitBssLayoutMethodVisitor(OatWriter* writer)
-      : DexMethodVisitor(writer, /* offset */ 0u) {}
-
-  bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
-                   const ClassDataItemIterator& it) OVERRIDE {
-    // Look for patches with .bss references and prepare maps with placeholders for their offsets.
-    CompiledMethod* compiled_method = writer_->compiler_driver_->GetCompiledMethod(
-        MethodReference(dex_file_, it.GetMemberIndex()));
-    if (HasCompiledCode(compiled_method)) {
-      for (const LinkerPatch& patch : compiled_method->GetPatches()) {
-        if (patch.GetType() == LinkerPatch::Type::kMethodBssEntry) {
-          MethodReference target_method = patch.TargetMethod();
-          auto refs_it = writer_->bss_method_entry_references_.find(target_method.dex_file);
-          if (refs_it == writer_->bss_method_entry_references_.end()) {
-            refs_it = writer_->bss_method_entry_references_.Put(
-                target_method.dex_file,
-                BitVector(target_method.dex_file->NumMethodIds(),
-                          /* expandable */ false,
-                          Allocator::GetMallocAllocator()));
-            refs_it->second.ClearAllBits();
-          }
-          refs_it->second.SetBit(target_method.index);
-          writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u);
-        } else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) {
-          TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
-          writer_->bss_type_entries_.Overwrite(ref, /* placeholder */ 0u);
-        } else if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
-          StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
-          writer_->bss_string_entries_.Overwrite(ref, /* placeholder */ 0u);
-        } else if (patch.GetType() == LinkerPatch::Type::kStringInternTable ||
-                   patch.GetType() == LinkerPatch::Type::kTypeClassTable) {
-          writer_->map_boot_image_tables_to_bss_ = true;
-        }
-      }
-    } else {
-      DCHECK(compiled_method == nullptr || compiled_method->GetPatches().empty());
-    }
-    return true;
-  }
-};
-
-class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor {
- public:
-  InitOatClassesMethodVisitor(OatWriter* writer, size_t offset)
-      : DexMethodVisitor(writer, offset),
-        compiled_methods_(),
-        compiled_methods_with_code_(0u) {
-    size_t num_classes = 0u;
-    for (const OatDexFile& oat_dex_file : writer_->oat_dex_files_) {
-      num_classes += oat_dex_file.class_offsets_.size();
-    }
-    // If we aren't compiling only reserve headers.
-    writer_->oat_class_headers_.reserve(num_classes);
-    if (writer->MayHaveCompiledMethods()) {
-      writer->oat_classes_.reserve(num_classes);
-    }
-    compiled_methods_.reserve(256u);
-    // If there are any classes, the class offsets allocation aligns the offset.
-    DCHECK(num_classes == 0u || IsAligned<4u>(offset));
-  }
-
-  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE {
-    DexMethodVisitor::StartClass(dex_file, class_def_index);
-    compiled_methods_.clear();
-    compiled_methods_with_code_ = 0u;
-    return true;
-  }
-
-  bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
-                   const ClassDataItemIterator& it) OVERRIDE {
-    // Fill in the compiled_methods_ array for methods that have a
-    // CompiledMethod. We track the number of non-null entries in
-    // compiled_methods_with_code_ since we only want to allocate
-    // OatMethodOffsets for the compiled methods.
-    uint32_t method_idx = it.GetMemberIndex();
-    CompiledMethod* compiled_method =
-        writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx));
-    compiled_methods_.push_back(compiled_method);
-    if (HasCompiledCode(compiled_method)) {
-      ++compiled_methods_with_code_;
-    }
-    return true;
-  }
-
-  bool EndClass() OVERRIDE {
-    ClassReference class_ref(dex_file_, class_def_index_);
-    mirror::Class::Status status;
-    bool found = writer_->compiler_driver_->GetCompiledClass(class_ref, &status);
-    if (!found) {
-      VerificationResults* results = writer_->compiler_driver_->GetVerificationResults();
-      if (results != nullptr && results->IsClassRejected(class_ref)) {
-        // The oat class status is used only for verification of resolved classes,
-        // so use kStatusErrorResolved whether the class was resolved or unresolved
-        // during compile-time verification.
-        status = mirror::Class::kStatusErrorResolved;
-      } else {
-        status = mirror::Class::kStatusNotReady;
-      }
-    }
-
-    writer_->oat_class_headers_.emplace_back(offset_,
-                                             compiled_methods_with_code_,
-                                             compiled_methods_.size(),
-                                             status);
-    OatClassHeader& header = writer_->oat_class_headers_.back();
-    offset_ += header.SizeOf();
-    if (writer_->MayHaveCompiledMethods()) {
-      writer_->oat_classes_.emplace_back(compiled_methods_,
-                                         compiled_methods_with_code_,
-                                         header.type_);
-      offset_ += writer_->oat_classes_.back().SizeOf();
-    }
-    return DexMethodVisitor::EndClass();
-  }
-
- private:
-  dchecked_vector<CompiledMethod*> compiled_methods_;
-  size_t compiled_methods_with_code_;
-};
-
-class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
- public:
-  InitCodeMethodVisitor(OatWriter* writer, size_t offset)
-      : InitCodeMethodVisitor(writer, offset, writer->GetCompilerDriver()->GetCompilerOptions()) {}
-
-  bool EndClass() OVERRIDE {
-    OatDexMethodVisitor::EndClass();
-    if (oat_class_index_ == writer_->oat_classes_.size()) {
-      offset_ = relative_patcher_->ReserveSpaceEnd(offset_);
-      if (generate_debug_info_) {
-        std::vector<debug::MethodDebugInfo> thunk_infos =
-            relative_patcher_->GenerateThunkDebugInfo(executable_offset_);
-        writer_->method_info_.insert(writer_->method_info_.end(),
-                                     std::make_move_iterator(thunk_infos.begin()),
-                                     std::make_move_iterator(thunk_infos.end()));
-      }
-    }
-    return true;
-  }
-
-  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
-    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
-
-    if (HasCompiledCode(compiled_method)) {
-      // Derived from CompiledMethod.
-      uint32_t quick_code_offset = 0;
-
-      ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
-      uint32_t code_size = quick_code.size() * sizeof(uint8_t);
-      uint32_t thumb_offset = compiled_method->CodeDelta();
-
-      // Deduplicate code arrays if we are not producing debuggable code.
-      bool deduped = true;
-      MethodReference method_ref(dex_file_, it.GetMemberIndex());
-      if (debuggable_) {
-        quick_code_offset = relative_patcher_->GetOffset(method_ref);
-        if (quick_code_offset != 0u) {
-          // Duplicate methods, we want the same code for both of them so that the oat writer puts
-          // the same code in both ArtMethods so that we do not get different oat code at runtime.
-        } else {
-          quick_code_offset = NewQuickCodeOffset(compiled_method, it, thumb_offset);
-          deduped = false;
-        }
-      } else {
-        quick_code_offset = dedupe_map_.GetOrCreate(
-            compiled_method,
-            [this, &deduped, compiled_method, &it, thumb_offset]() {
-              deduped = false;
-              return NewQuickCodeOffset(compiled_method, it, thumb_offset);
-            });
-      }
-
-      if (code_size != 0) {
-        if (relative_patcher_->GetOffset(method_ref) != 0u) {
-          // TODO: Should this be a hard failure?
-          LOG(WARNING) << "Multiple definitions of "
-              << method_ref.PrettyMethod()
-              << " offsets " << relative_patcher_->GetOffset(method_ref)
-              << " " << quick_code_offset;
-        } else {
-          relative_patcher_->SetOffset(method_ref, quick_code_offset);
-        }
-      }
-
-      // Update quick method header.
-      DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
-      OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
-      uint32_t vmap_table_offset = method_header->GetVmapTableOffset();
-      uint32_t method_info_offset = method_header->GetMethodInfoOffset();
-      // The code offset was 0 when the mapping/vmap table offset was set, so it's set
-      // to 0-offset and we need to adjust it by code_offset.
-      uint32_t code_offset = quick_code_offset - thumb_offset;
-      if (!compiled_method->GetQuickCode().empty()) {
-        // If the code is compiled, we write the offset of the stack map relative
-        // to the code,
-        if (vmap_table_offset != 0u) {
-          vmap_table_offset += code_offset;
-          DCHECK_LT(vmap_table_offset, code_offset);
-        }
-        if (method_info_offset != 0u) {
-          method_info_offset += code_offset;
-          DCHECK_LT(method_info_offset, code_offset);
-        }
-      } else {
-        CHECK(!kIsVdexEnabled);
-        // We write the offset of the quickening info relative to the code.
-        vmap_table_offset += code_offset;
-        DCHECK_LT(vmap_table_offset, code_offset);
-      }
-      uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
-      uint32_t core_spill_mask = compiled_method->GetCoreSpillMask();
-      uint32_t fp_spill_mask = compiled_method->GetFpSpillMask();
-      *method_header = OatQuickMethodHeader(vmap_table_offset,
-                                            method_info_offset,
-                                            frame_size_in_bytes,
-                                            core_spill_mask,
-                                            fp_spill_mask,
-                                            code_size);
-
-      if (!deduped) {
-        // Update offsets. (Checksum is updated when writing.)
-        offset_ += sizeof(*method_header);  // Method header is prepended before code.
-        offset_ += code_size;
-        // Record absolute patch locations.
-        if (!compiled_method->GetPatches().empty()) {
-          uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset();
-          for (const LinkerPatch& patch : compiled_method->GetPatches()) {
-            if (!patch.IsPcRelative()) {
-              writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
-            }
-          }
-        }
-      }
-
-      // Exclude quickened dex methods (code_size == 0) since they have no native code.
-      if (generate_debug_info_ && code_size != 0) {
-        bool has_code_info = method_header->IsOptimized();
-        // Record debug information for this function if we are doing that.
-        debug::MethodDebugInfo info = {};
-        DCHECK(info.trampoline_name.empty());
-        info.dex_file = dex_file_;
-        info.class_def_index = class_def_index_;
-        info.dex_method_index = it.GetMemberIndex();
-        info.access_flags = it.GetMethodAccessFlags();
-        info.code_item = it.GetMethodCodeItem();
-        info.isa = compiled_method->GetInstructionSet();
-        info.deduped = deduped;
-        info.is_native_debuggable = native_debuggable_;
-        info.is_optimized = method_header->IsOptimized();
-        info.is_code_address_text_relative = true;
-        info.code_address = code_offset - executable_offset_;
-        info.code_size = code_size;
-        info.frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
-        info.code_info = has_code_info ? compiled_method->GetVmapTable().data() : nullptr;
-        info.cfi = compiled_method->GetCFIInfo();
-        writer_->method_info_.push_back(info);
-      }
-
-      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
-      OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_];
-      offsets->code_offset_ = quick_code_offset;
-      ++method_offsets_index_;
-    }
-
-    return true;
-  }
-
- private:
-  InitCodeMethodVisitor(OatWriter* writer, size_t offset, const CompilerOptions& compiler_options)
-      : OatDexMethodVisitor(writer, offset),
-        relative_patcher_(writer->relative_patcher_),
-        executable_offset_(writer->oat_header_->GetExecutableOffset()),
-        debuggable_(compiler_options.GetDebuggable()),
-        native_debuggable_(compiler_options.GetNativeDebuggable()),
-        generate_debug_info_(compiler_options.GenerateAnyDebugInfo()) {
-    writer->absolute_patch_locations_.reserve(
-        writer->GetCompilerDriver()->GetNonRelativeLinkerPatchCount());
-  }
-
-  struct CodeOffsetsKeyComparator {
-    bool operator()(const CompiledMethod* lhs, const CompiledMethod* rhs) const {
-      // Code is deduplicated by CompilerDriver, compare only data pointers.
-      if (lhs->GetQuickCode().data() != rhs->GetQuickCode().data()) {
-        return lhs->GetQuickCode().data() < rhs->GetQuickCode().data();
-      }
-      // If the code is the same, all other fields are likely to be the same as well.
-      if (UNLIKELY(lhs->GetVmapTable().data() != rhs->GetVmapTable().data())) {
-        return lhs->GetVmapTable().data() < rhs->GetVmapTable().data();
-      }
-      if (UNLIKELY(lhs->GetMethodInfo().data() != rhs->GetMethodInfo().data())) {
-        return lhs->GetMethodInfo().data() < rhs->GetMethodInfo().data();
-      }
-      if (UNLIKELY(lhs->GetPatches().data() != rhs->GetPatches().data())) {
-        return lhs->GetPatches().data() < rhs->GetPatches().data();
-      }
-      return false;
-    }
-  };
-
-  uint32_t NewQuickCodeOffset(CompiledMethod* compiled_method,
-                              const ClassDataItemIterator& it,
-                              uint32_t thumb_offset) {
-    offset_ = relative_patcher_->ReserveSpace(
-        offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex()));
-    offset_ += CodeAlignmentSize(offset_, *compiled_method);
-    DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader),
-                         GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
-    return offset_ + sizeof(OatQuickMethodHeader) + thumb_offset;
-  }
-
-  // Deduplication is already done on a pointer basis by the compiler driver,
-  // so we can simply compare the pointers to find out if things are duplicated.
-  SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
-
-  // Cache writer_'s members and compiler options.
-  linker::MultiOatRelativePatcher* relative_patcher_;
-  uint32_t executable_offset_;
-  const bool debuggable_;
-  const bool native_debuggable_;
-  const bool generate_debug_info_;
-};
-
-class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor {
- public:
-  InitMapMethodVisitor(OatWriter* writer, size_t offset)
-      : OatDexMethodVisitor(writer, offset) {}
-
-  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED)
-      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
-    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
-    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
-
-    if (HasCompiledCode(compiled_method)) {
-      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
-      DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].GetVmapTableOffset(), 0u);
-
-      ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
-      uint32_t map_size = map.size() * sizeof(map[0]);
-      if (map_size != 0u) {
-        size_t offset = dedupe_map_.GetOrCreate(
-            map.data(),
-            [this, map_size]() {
-              uint32_t new_offset = offset_;
-              offset_ += map_size;
-              return new_offset;
-            });
-        // Code offset is not initialized yet, so set the map offset to 0u-offset.
-        DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
-        oat_class->method_headers_[method_offsets_index_].SetVmapTableOffset(0u - offset);
-      }
-      ++method_offsets_index_;
-    }
-
-    return true;
-  }
-
- private:
-  // Deduplication is already done on a pointer basis by the compiler driver,
-  // so we can simply compare the pointers to find out if things are duplicated.
-  SafeMap<const uint8_t*, uint32_t> dedupe_map_;
-};
-
-class OatWriter::InitMethodInfoVisitor : public OatDexMethodVisitor {
- public:
-  InitMethodInfoVisitor(OatWriter* writer, size_t offset) : OatDexMethodVisitor(writer, offset) {}
-
-  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED)
-      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
-    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
-    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
-
-    if (HasCompiledCode(compiled_method)) {
-      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
-      DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].GetMethodInfoOffset(), 0u);
-      ArrayRef<const uint8_t> map = compiled_method->GetMethodInfo();
-      const uint32_t map_size = map.size() * sizeof(map[0]);
-      if (map_size != 0u) {
-        size_t offset = dedupe_map_.GetOrCreate(
-            map.data(),
-            [this, map_size]() {
-              uint32_t new_offset = offset_;
-              offset_ += map_size;
-              return new_offset;
-            });
-        // Code offset is not initialized yet, so set the map offset to 0u-offset.
-        DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
-        oat_class->method_headers_[method_offsets_index_].SetMethodInfoOffset(0u - offset);
-      }
-      ++method_offsets_index_;
-    }
-
-    return true;
-  }
-
- private:
-  // Deduplication is already done on a pointer basis by the compiler driver,
-  // so we can simply compare the pointers to find out if things are duplicated.
-  SafeMap<const uint8_t*, uint32_t> dedupe_map_;
-};
-
-class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
- public:
-  InitImageMethodVisitor(OatWriter* writer,
-                         size_t offset,
-                         const std::vector<const DexFile*>* dex_files)
-      : OatDexMethodVisitor(writer, offset),
-        pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
-        class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
-        dex_files_(dex_files),
-        class_linker_(Runtime::Current()->GetClassLinker()) {}
-
-  // Handle copied methods here. Copy pointer to quick code from
-  // an origin method to a copied method only if they are
-  // in the same oat file. If the origin and the copied methods are
-  // in different oat files don't touch the copied method.
-  // References to other oat files are not supported yet.
-  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    OatDexMethodVisitor::StartClass(dex_file, class_def_index);
-    // Skip classes that are not in the image.
-    if (!IsImageClass()) {
-      return true;
-    }
-    ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(Thread::Current(), *dex_file);
-    const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
-    mirror::Class* klass = dex_cache->GetResolvedType(class_def.class_idx_);
-    if (klass != nullptr) {
-      for (ArtMethod& method : klass->GetCopiedMethods(pointer_size_)) {
-        // Find origin method. Declaring class and dex_method_idx
-        // in the copied method should be the same as in the origin
-        // method.
-        mirror::Class* declaring_class = method.GetDeclaringClass();
-        ArtMethod* origin = declaring_class->FindClassMethod(
-            declaring_class->GetDexCache(),
-            method.GetDexMethodIndex(),
-            pointer_size_);
-        CHECK(origin != nullptr);
-        CHECK(!origin->IsDirect());
-        CHECK(origin->GetDeclaringClass() == declaring_class);
-        if (IsInOatFile(&declaring_class->GetDexFile())) {
-          const void* code_ptr =
-              origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
-          if (code_ptr == nullptr) {
-            methods_to_process_.push_back(std::make_pair(&method, origin));
-          } else {
-            method.SetEntryPointFromQuickCompiledCodePtrSize(
-                code_ptr, pointer_size_);
-          }
-        }
-      }
-    }
-    return true;
-  }
-
-  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    // Skip methods that are not in the image.
-    if (!IsImageClass()) {
-      return true;
-    }
-
-    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
-    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
-
-    OatMethodOffsets offsets(0u);
-    if (HasCompiledCode(compiled_method)) {
-      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
-      offsets = oat_class->method_offsets_[method_offsets_index_];
-      ++method_offsets_index_;
-    }
-
-    Thread* self = Thread::Current();
-    ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(self, *dex_file_);
-    ArtMethod* method;
-    if (writer_->HasBootImage()) {
-      const InvokeType invoke_type = it.GetMethodInvokeType(
-          dex_file_->GetClassDef(class_def_index_));
-      // Unchecked as we hold mutator_lock_ on entry.
-      ScopedObjectAccessUnchecked soa(self);
-      StackHandleScope<1> hs(self);
-      method = class_linker_->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
-          *dex_file_,
-          it.GetMemberIndex(),
-          hs.NewHandle(dex_cache),
-          ScopedNullHandle<mirror::ClassLoader>(),
-          nullptr,
-          invoke_type);
-      if (method == nullptr) {
-        LOG(FATAL_WITHOUT_ABORT) << "Unexpected failure to resolve a method: "
-            << dex_file_->PrettyMethod(it.GetMemberIndex(), true);
-        self->AssertPendingException();
-        mirror::Throwable* exc = self->GetException();
-        std::string dump = exc->Dump();
-        LOG(FATAL) << dump;
-        UNREACHABLE();
-      }
-    } else {
-      // Should already have been resolved by the compiler.
-      // It may not be resolved if the class failed to verify, in this case, don't set the
-      // entrypoint. This is not fatal since we shall use a resolution method.
-      method = class_linker_->LookupResolvedMethod(it.GetMemberIndex(), dex_cache, class_loader_);
-    }
-    if (method != nullptr &&
-        compiled_method != nullptr &&
-        compiled_method->GetQuickCode().size() != 0) {
-      method->SetEntryPointFromQuickCompiledCodePtrSize(
-          reinterpret_cast<void*>(offsets.code_offset_), pointer_size_);
-    }
-
-    return true;
-  }
-
-  // Check whether current class is image class
-  bool IsImageClass() {
-    const DexFile::TypeId& type_id =
-        dex_file_->GetTypeId(dex_file_->GetClassDef(class_def_index_).class_idx_);
-    const char* class_descriptor = dex_file_->GetTypeDescriptor(type_id);
-    return writer_->GetCompilerDriver()->IsImageClass(class_descriptor);
-  }
-
-  // Check whether specified dex file is in the compiled oat file.
-  bool IsInOatFile(const DexFile* dex_file) {
-    return ContainsElement(*dex_files_, dex_file);
-  }
-
-  // Assign a pointer to quick code for copied methods
-  // not handled in the method StartClass
-  void Postprocess() {
-    for (std::pair<ArtMethod*, ArtMethod*>& p : methods_to_process_) {
-      ArtMethod* method = p.first;
-      ArtMethod* origin = p.second;
-      const void* code_ptr =
-          origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
-      if (code_ptr != nullptr) {
-        method->SetEntryPointFromQuickCompiledCodePtrSize(code_ptr, pointer_size_);
-      }
-    }
-  }
-
- private:
-  const PointerSize pointer_size_;
-  ObjPtr<mirror::ClassLoader> class_loader_;
-  const std::vector<const DexFile*>* dex_files_;
-  ClassLinker* const class_linker_;
-  std::vector<std::pair<ArtMethod*, ArtMethod*>> methods_to_process_;
-};
-
-class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
- public:
-  WriteCodeMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset,
-                         size_t relative_offset) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
-      : OatDexMethodVisitor(writer, relative_offset),
-        pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
-        class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
-        out_(out),
-        file_offset_(file_offset),
-        soa_(Thread::Current()),
-        no_thread_suspension_("OatWriter patching"),
-        class_linker_(Runtime::Current()->GetClassLinker()),
-        dex_cache_(nullptr) {
-    patched_code_.reserve(16 * KB);
-    if (writer_->HasBootImage()) {
-      // If we're creating the image, the address space must be ready so that we can apply patches.
-      CHECK(writer_->image_writer_->IsImageAddressSpaceReady());
-    }
-  }
-
-  ~WriteCodeMethodVisitor() UNLOCK_FUNCTION(Locks::mutator_lock_) {
-  }
-
-  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    OatDexMethodVisitor::StartClass(dex_file, class_def_index);
-    if (writer_->GetCompilerDriver()->GetCompilerOptions().IsAotCompilationEnabled()) {
-      // Only need to set the dex cache if we have compilation. Other modes might have unloaded it.
-      if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) {
-        dex_cache_ = class_linker_->FindDexCache(Thread::Current(), *dex_file);
-        DCHECK(dex_cache_ != nullptr);
-      }
-    }
-    return true;
-  }
-
-  bool EndClass() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
-    bool result = OatDexMethodVisitor::EndClass();
-    if (oat_class_index_ == writer_->oat_classes_.size()) {
-      DCHECK(result);  // OatDexMethodVisitor::EndClass() never fails.
-      offset_ = writer_->relative_patcher_->WriteThunks(out_, offset_);
-      if (UNLIKELY(offset_ == 0u)) {
-        PLOG(ERROR) << "Failed to write final relative call thunks";
-        result = false;
-      }
-    }
-    return result;
-  }
-
-  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
-    const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
-
-    // No thread suspension since dex_cache_ that may get invalidated if that occurs.
-    ScopedAssertNoThreadSuspension tsc(__FUNCTION__);
-    if (HasCompiledCode(compiled_method)) {
-      size_t file_offset = file_offset_;
-      OutputStream* out = out_;
-
-      ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
-      uint32_t code_size = quick_code.size() * sizeof(uint8_t);
-
-      // Deduplicate code arrays.
-      const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_];
-      if (method_offsets.code_offset_ > offset_) {
-        offset_ = writer_->relative_patcher_->WriteThunks(out, offset_);
-        if (offset_ == 0u) {
-          ReportWriteFailure("relative call thunk", it);
-          return false;
-        }
-        uint32_t alignment_size = CodeAlignmentSize(offset_, *compiled_method);
-        if (alignment_size != 0) {
-          if (!writer_->WriteCodeAlignment(out, alignment_size)) {
-            ReportWriteFailure("code alignment padding", it);
-            return false;
-          }
-          offset_ += alignment_size;
-          DCHECK_OFFSET_();
-        }
-        DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader),
-                             GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
-        DCHECK_EQ(method_offsets.code_offset_,
-                  offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta())
-            << dex_file_->PrettyMethod(it.GetMemberIndex());
-        const OatQuickMethodHeader& method_header =
-            oat_class->method_headers_[method_offsets_index_];
-        if (!out->WriteFully(&method_header, sizeof(method_header))) {
-          ReportWriteFailure("method header", it);
-          return false;
-        }
-        writer_->size_method_header_ += sizeof(method_header);
-        offset_ += sizeof(method_header);
-        DCHECK_OFFSET_();
-
-        if (!compiled_method->GetPatches().empty()) {
-          patched_code_.assign(quick_code.begin(), quick_code.end());
-          quick_code = ArrayRef<const uint8_t>(patched_code_);
-          for (const LinkerPatch& patch : compiled_method->GetPatches()) {
-            uint32_t literal_offset = patch.LiteralOffset();
-            switch (patch.GetType()) {
-              case LinkerPatch::Type::kMethodBssEntry: {
-                uint32_t target_offset =
-                    writer_->bss_start_ + writer_->bss_method_entries_.Get(patch.TargetMethod());
-                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
-                                                                     patch,
-                                                                     offset_ + literal_offset,
-                                                                     target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kCallRelative: {
-                // NOTE: Relative calls across oat files are not supported.
-                uint32_t target_offset = GetTargetOffset(patch);
-                writer_->relative_patcher_->PatchCall(&patched_code_,
-                                                      literal_offset,
-                                                      offset_ + literal_offset,
-                                                      target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kStringRelative: {
-                uint32_t target_offset = GetTargetObjectOffset(GetTargetString(patch));
-                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
-                                                                     patch,
-                                                                     offset_ + literal_offset,
-                                                                     target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kStringInternTable: {
-                uint32_t target_offset = GetInternTableEntryOffset(patch);
-                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
-                                                                     patch,
-                                                                     offset_ + literal_offset,
-                                                                     target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kStringBssEntry: {
-                StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
-                uint32_t target_offset =
-                    writer_->bss_start_ + writer_->bss_string_entries_.Get(ref);
-                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
-                                                                     patch,
-                                                                     offset_ + literal_offset,
-                                                                     target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kTypeRelative: {
-                uint32_t target_offset = GetTargetObjectOffset(GetTargetType(patch));
-                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
-                                                                     patch,
-                                                                     offset_ + literal_offset,
-                                                                     target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kTypeClassTable: {
-                uint32_t target_offset = GetClassTableEntryOffset(patch);
-                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
-                                                                     patch,
-                                                                     offset_ + literal_offset,
-                                                                     target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kTypeBssEntry: {
-                TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
-                uint32_t target_offset = writer_->bss_start_ + writer_->bss_type_entries_.Get(ref);
-                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
-                                                                     patch,
-                                                                     offset_ + literal_offset,
-                                                                     target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kCall: {
-                uint32_t target_offset = GetTargetOffset(patch);
-                PatchCodeAddress(&patched_code_, literal_offset, target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kMethodRelative: {
-                uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch));
-                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
-                                                                     patch,
-                                                                     offset_ + literal_offset,
-                                                                     target_offset);
-                break;
-              }
-              case LinkerPatch::Type::kBakerReadBarrierBranch: {
-                writer_->relative_patcher_->PatchBakerReadBarrierBranch(&patched_code_,
-                                                                        patch,
-                                                                        offset_ + literal_offset);
-                break;
-              }
-              default: {
-                DCHECK(false) << "Unexpected linker patch type: " << patch.GetType();
-                break;
-              }
-            }
-          }
-        }
-
-        if (!out->WriteFully(quick_code.data(), code_size)) {
-          ReportWriteFailure("method code", it);
-          return false;
-        }
-        writer_->size_code_ += code_size;
-        offset_ += code_size;
-      }
-      DCHECK_OFFSET_();
-      ++method_offsets_index_;
-    }
-
-    return true;
-  }
-
- private:
-  const PointerSize pointer_size_;
-  ObjPtr<mirror::ClassLoader> class_loader_;
-  OutputStream* const out_;
-  const size_t file_offset_;
-  const ScopedObjectAccess soa_;
-  const ScopedAssertNoThreadSuspension no_thread_suspension_;
-  ClassLinker* const class_linker_;
-  ObjPtr<mirror::DexCache> dex_cache_;
-  std::vector<uint8_t> patched_code_;
-
-  void ReportWriteFailure(const char* what, const ClassDataItemIterator& it) {
-    PLOG(ERROR) << "Failed to write " << what << " for "
-        << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation();
-  }
-
-  ArtMethod* GetTargetMethod(const LinkerPatch& patch)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    MethodReference ref = patch.TargetMethod();
-    ObjPtr<mirror::DexCache> dex_cache =
-        (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(
-            Thread::Current(), *ref.dex_file);
-    ArtMethod* method = class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_);
-    CHECK(method != nullptr);
-    return method;
-  }
-
-  uint32_t GetTargetOffset(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
-    uint32_t target_offset = writer_->relative_patcher_->GetOffset(patch.TargetMethod());
-    // If there's no new compiled code, either we're compiling an app and the target method
-    // is in the boot image, or we need to point to the correct trampoline.
-    if (UNLIKELY(target_offset == 0)) {
-      ArtMethod* target = GetTargetMethod(patch);
-      DCHECK(target != nullptr);
-      const void* oat_code_offset =
-          target->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
-      if (oat_code_offset != 0) {
-        DCHECK(!writer_->HasBootImage());
-        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickResolutionStub(oat_code_offset));
-        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(oat_code_offset));
-        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickGenericJniStub(oat_code_offset));
-        target_offset = PointerToLowMemUInt32(oat_code_offset);
-      } else {
-        target_offset = target->IsNative()
-            ? writer_->oat_header_->GetQuickGenericJniTrampolineOffset()
-            : writer_->oat_header_->GetQuickToInterpreterBridgeOffset();
-      }
-    }
-    return target_offset;
-  }
-
-  ObjPtr<mirror::DexCache> GetDexCache(const DexFile* target_dex_file)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    return (target_dex_file == dex_file_)
-        ? dex_cache_
-        : class_linker_->FindDexCache(Thread::Current(), *target_dex_file);
-  }
-
-  mirror::Class* GetTargetType(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(writer_->HasImage());
-    ObjPtr<mirror::DexCache> dex_cache = GetDexCache(patch.TargetTypeDexFile());
-    ObjPtr<mirror::Class> type =
-        ClassLinker::LookupResolvedType(patch.TargetTypeIndex(), dex_cache, class_loader_);
-    CHECK(type != nullptr);
-    return type.Ptr();
-  }
-
-  mirror::String* GetTargetString(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
-    ClassLinker* linker = Runtime::Current()->GetClassLinker();
-    mirror::String* string = linker->LookupString(*patch.TargetStringDexFile(),
-                                                  patch.TargetStringIndex(),
-                                                  GetDexCache(patch.TargetStringDexFile()));
-    DCHECK(string != nullptr);
-    DCHECK(writer_->HasBootImage() ||
-           Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(string));
-    return string;
-  }
-
-  uint32_t GetTargetMethodOffset(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(writer_->HasBootImage());
-    method = writer_->image_writer_->GetImageMethodAddress(method);
-    size_t oat_index = writer_->image_writer_->GetOatIndexForDexFile(dex_file_);
-    uintptr_t oat_data_begin = writer_->image_writer_->GetOatDataBegin(oat_index);
-    // TODO: Clean up offset types. The target offset must be treated as signed.
-    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method) - oat_data_begin);
-  }
-
-  uint32_t GetTargetObjectOffset(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(writer_->HasBootImage());
-    object = writer_->image_writer_->GetImageAddress(object);
-    size_t oat_index = writer_->image_writer_->GetOatIndexForDexFile(dex_file_);
-    uintptr_t oat_data_begin = writer_->image_writer_->GetOatDataBegin(oat_index);
-    // TODO: Clean up offset types. The target offset must be treated as signed.
-    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object) - oat_data_begin);
-  }
-
-  void PatchObjectAddress(std::vector<uint8_t>* code, uint32_t offset, mirror::Object* object)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (writer_->HasBootImage()) {
-      object = writer_->image_writer_->GetImageAddress(object);
-    } else {
-      // NOTE: We're using linker patches for app->boot references when the image can
-      // be relocated and therefore we need to emit .oat_patches. We're not using this
-      // for app->app references, so check that the object is in the image space.
-      DCHECK(Runtime::Current()->GetHeap()->FindSpaceFromObject(object, false)->IsImageSpace());
-    }
-    // Note: We only patch targeting Objects in image which is in the low 4gb.
-    uint32_t address = PointerToLowMemUInt32(object);
-    DCHECK_LE(offset + 4, code->size());
-    uint8_t* data = &(*code)[offset];
-    data[0] = address & 0xffu;
-    data[1] = (address >> 8) & 0xffu;
-    data[2] = (address >> 16) & 0xffu;
-    data[3] = (address >> 24) & 0xffu;
-  }
-
-  void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    uint32_t address = target_offset;
-    if (writer_->HasBootImage()) {
-      size_t oat_index = writer_->image_writer_->GetOatIndexForDexCache(dex_cache_);
-      // TODO: Clean up offset types.
-      // The target_offset must be treated as signed for cross-oat patching.
-      const void* target = reinterpret_cast<const void*>(
-          writer_->image_writer_->GetOatDataBegin(oat_index) +
-          static_cast<int32_t>(target_offset));
-      address = PointerToLowMemUInt32(target);
-    }
-    DCHECK_LE(offset + 4, code->size());
-    uint8_t* data = &(*code)[offset];
-    data[0] = address & 0xffu;
-    data[1] = (address >> 8) & 0xffu;
-    data[2] = (address >> 16) & 0xffu;
-    data[3] = (address >> 24) & 0xffu;
-  }
-
-  // Calculate the offset of the InternTable slot (GcRoot<String>) when mmapped to the .bss.
-  uint32_t GetInternTableEntryOffset(const LinkerPatch& patch)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(!writer_->HasBootImage());
-    const uint8_t* string_root = writer_->LookupBootImageInternTableSlot(
-        *patch.TargetStringDexFile(), patch.TargetStringIndex());
-    DCHECK(string_root != nullptr);
-    return GetBootImageTableEntryOffset(string_root);
-  }
-
-  // Calculate the offset of the ClassTable::TableSlot when mmapped to the .bss.
-  uint32_t GetClassTableEntryOffset(const LinkerPatch& patch)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(!writer_->HasBootImage());
-    const uint8_t* table_slot =
-        writer_->LookupBootImageClassTableSlot(*patch.TargetTypeDexFile(), patch.TargetTypeIndex());
-    DCHECK(table_slot != nullptr);
-    return GetBootImageTableEntryOffset(table_slot);
-  }
-
-  uint32_t GetBootImageTableEntryOffset(const uint8_t* raw_root) {
-    uint32_t base_offset = writer_->bss_start_;
-    for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
-      const uint8_t* const_tables_begin =
-          space->Begin() + space->GetImageHeader().GetBootImageConstantTablesOffset();
-      size_t offset = static_cast<size_t>(raw_root - const_tables_begin);
-      if (offset < space->GetImageHeader().GetBootImageConstantTablesSize()) {
-        DCHECK_LE(base_offset + offset, writer_->bss_start_ + writer_->bss_methods_offset_);
-        return base_offset + offset;
-      }
-      base_offset += space->GetImageHeader().GetBootImageConstantTablesSize();
-    }
-    LOG(FATAL) << "Didn't find boot image string in boot image intern tables!";
-    UNREACHABLE();
-  }
-};
-
-class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
- public:
-  WriteMapMethodVisitor(OatWriter* writer,
-                        OutputStream* out,
-                        const size_t file_offset,
-                        size_t relative_offset)
-      : OatDexMethodVisitor(writer, relative_offset),
-        out_(out),
-        file_offset_(file_offset) {}
-
-  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE {
-    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
-    const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
-
-    if (HasCompiledCode(compiled_method)) {
-      size_t file_offset = file_offset_;
-      OutputStream* out = out_;
-
-      uint32_t map_offset = oat_class->method_headers_[method_offsets_index_].GetVmapTableOffset();
-      uint32_t code_offset = oat_class->method_offsets_[method_offsets_index_].code_offset_;
-      ++method_offsets_index_;
-
-      DCHECK((compiled_method->GetVmapTable().size() == 0u && map_offset == 0u) ||
-             (compiled_method->GetVmapTable().size() != 0u && map_offset != 0u))
-          << compiled_method->GetVmapTable().size() << " " << map_offset << " "
-          << dex_file_->PrettyMethod(it.GetMemberIndex());
-
-      // If vdex is enabled, only emit the map for compiled code. The quickening info
-      // is emitted in the vdex already.
-      if (map_offset != 0u) {
-        // Transform map_offset to actual oat data offset.
-        map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset;
-        DCHECK_NE(map_offset, 0u);
-        DCHECK_LE(map_offset, offset_) << dex_file_->PrettyMethod(it.GetMemberIndex());
-
-        ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
-        size_t map_size = map.size() * sizeof(map[0]);
-        if (map_offset == offset_) {
-          // Write deduplicated map (code info for Optimizing or transformation info for dex2dex).
-          if (UNLIKELY(!out->WriteFully(map.data(), map_size))) {
-            ReportWriteFailure(it);
-            return false;
-          }
-          offset_ += map_size;
-        }
-      }
-      DCHECK_OFFSET_();
-    }
-
-    return true;
-  }
-
- private:
-  OutputStream* const out_;
-  size_t const file_offset_;
-
-  void ReportWriteFailure(const ClassDataItemIterator& it) {
-    PLOG(ERROR) << "Failed to write map for "
-        << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation();
-  }
-};
-
-class OatWriter::WriteMethodInfoVisitor : public OatDexMethodVisitor {
- public:
-  WriteMethodInfoVisitor(OatWriter* writer,
-                         OutputStream* out,
-                         const size_t file_offset,
-                         size_t relative_offset)
-      : OatDexMethodVisitor(writer, relative_offset),
-        out_(out),
-        file_offset_(file_offset) {}
-
-  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE {
-    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
-    const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
-
-    if (HasCompiledCode(compiled_method)) {
-      size_t file_offset = file_offset_;
-      OutputStream* out = out_;
-      uint32_t map_offset = oat_class->method_headers_[method_offsets_index_].GetMethodInfoOffset();
-      uint32_t code_offset = oat_class->method_offsets_[method_offsets_index_].code_offset_;
-      ++method_offsets_index_;
-      DCHECK((compiled_method->GetMethodInfo().size() == 0u && map_offset == 0u) ||
-             (compiled_method->GetMethodInfo().size() != 0u && map_offset != 0u))
-          << compiled_method->GetMethodInfo().size() << " " << map_offset << " "
-          << dex_file_->PrettyMethod(it.GetMemberIndex());
-      if (map_offset != 0u) {
-        // Transform map_offset to actual oat data offset.
-        map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset;
-        DCHECK_NE(map_offset, 0u);
-        DCHECK_LE(map_offset, offset_) << dex_file_->PrettyMethod(it.GetMemberIndex());
-
-        ArrayRef<const uint8_t> map = compiled_method->GetMethodInfo();
-        size_t map_size = map.size() * sizeof(map[0]);
-        if (map_offset == offset_) {
-          // Write deduplicated map (code info for Optimizing or transformation info for dex2dex).
-          if (UNLIKELY(!out->WriteFully(map.data(), map_size))) {
-            ReportWriteFailure(it);
-            return false;
-          }
-          offset_ += map_size;
-        }
-      }
-      DCHECK_OFFSET_();
-    }
-
-    return true;
-  }
-
- private:
-  OutputStream* const out_;
-  size_t const file_offset_;
-
-  void ReportWriteFailure(const ClassDataItemIterator& it) {
-    PLOG(ERROR) << "Failed to write map for "
-        << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation();
-  }
-};
-
-// Visit all methods from all classes in all dex files with the specified visitor.
-bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) {
-  for (const DexFile* dex_file : *dex_files_) {
-    const size_t class_def_count = dex_file->NumClassDefs();
-    for (size_t class_def_index = 0; class_def_index != class_def_count; ++class_def_index) {
-      if (UNLIKELY(!visitor->StartClass(dex_file, class_def_index))) {
-        return false;
-      }
-      if (MayHaveCompiledMethods()) {
-        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
-        const uint8_t* class_data = dex_file->GetClassData(class_def);
-        if (class_data != nullptr) {  // ie not an empty class, such as a marker interface
-          ClassDataItemIterator it(*dex_file, class_data);
-          it.SkipAllFields();
-          size_t class_def_method_index = 0u;
-          while (it.HasNextDirectMethod()) {
-            if (!visitor->VisitMethod(class_def_method_index, it)) {
-              return false;
-            }
-            ++class_def_method_index;
-            it.Next();
-          }
-          while (it.HasNextVirtualMethod()) {
-            if (UNLIKELY(!visitor->VisitMethod(class_def_method_index, it))) {
-              return false;
-            }
-            ++class_def_method_index;
-            it.Next();
-          }
-        }
-      }
-      if (UNLIKELY(!visitor->EndClass())) {
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-size_t OatWriter::InitOatHeader(InstructionSet instruction_set,
-                                const InstructionSetFeatures* instruction_set_features,
-                                uint32_t num_dex_files,
-                                SafeMap<std::string, std::string>* key_value_store) {
-  TimingLogger::ScopedTiming split("InitOatHeader", timings_);
-  oat_header_.reset(OatHeader::Create(instruction_set,
-                                      instruction_set_features,
-                                      num_dex_files,
-                                      key_value_store));
-  size_oat_header_ += sizeof(OatHeader);
-  size_oat_header_key_value_store_ += oat_header_->GetHeaderSize() - sizeof(OatHeader);
-  return oat_header_->GetHeaderSize();
-}
-
-size_t OatWriter::InitClassOffsets(size_t offset) {
-  // Reserve space for class offsets in OAT and update class_offsets_offset_.
-  for (OatDexFile& oat_dex_file : oat_dex_files_) {
-    DCHECK_EQ(oat_dex_file.class_offsets_offset_, 0u);
-    if (!oat_dex_file.class_offsets_.empty()) {
-      // Class offsets are required to be 4 byte aligned.
-      offset = RoundUp(offset, 4u);
-      oat_dex_file.class_offsets_offset_ = offset;
-      offset += oat_dex_file.GetClassOffsetsRawSize();
-      DCHECK_ALIGNED(offset, 4u);
-    }
-  }
-  return offset;
-}
-
-size_t OatWriter::InitOatClasses(size_t offset) {
-  // calculate the offsets within OatDexFiles to OatClasses
-  InitOatClassesMethodVisitor visitor(this, offset);
-  bool success = VisitDexMethods(&visitor);
-  CHECK(success);
-  offset = visitor.GetOffset();
-
-  // Update oat_dex_files_.
-  auto oat_class_it = oat_class_headers_.begin();
-  for (OatDexFile& oat_dex_file : oat_dex_files_) {
-    for (uint32_t& class_offset : oat_dex_file.class_offsets_) {
-      DCHECK(oat_class_it != oat_class_headers_.end());
-      class_offset = oat_class_it->offset_;
-      ++oat_class_it;
-    }
-  }
-  CHECK(oat_class_it == oat_class_headers_.end());
-
-  return offset;
-}
-
-size_t OatWriter::InitOatMaps(size_t offset) {
-  if (!MayHaveCompiledMethods()) {
-    return offset;
-  }
-  {
-    InitMapMethodVisitor visitor(this, offset);
-    bool success = VisitDexMethods(&visitor);
-    DCHECK(success);
-    offset = visitor.GetOffset();
-  }
-  {
-    InitMethodInfoVisitor visitor(this, offset);
-    bool success = VisitDexMethods(&visitor);
-    DCHECK(success);
-    offset = visitor.GetOffset();
-  }
-  return offset;
-}
-
-size_t OatWriter::InitMethodBssMappings(size_t offset) {
-  size_t number_of_dex_files = 0u;
-  for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
-    const DexFile* dex_file = (*dex_files_)[i];
-    auto it = bss_method_entry_references_.find(dex_file);
-    if (it != bss_method_entry_references_.end()) {
-      const BitVector& method_indexes = it->second;
-      ++number_of_dex_files;
-      // If there are any classes, the class offsets allocation aligns the offset
-      // and we cannot have method bss mappings without class offsets.
-      static_assert(alignof(MethodBssMapping) == 4u, "MethodBssMapping alignment check.");
-      DCHECK_ALIGNED(offset, 4u);
-      oat_dex_files_[i].method_bss_mapping_offset_ = offset;
-
-      linker::MethodBssMappingEncoder encoder(
-          GetInstructionSetPointerSize(oat_header_->GetInstructionSet()));
-      size_t number_of_entries = 0u;
-      bool first_index = true;
-      for (uint32_t method_index : method_indexes.Indexes()) {
-        uint32_t bss_offset = bss_method_entries_.Get(MethodReference(dex_file, method_index));
-        if (first_index || !encoder.TryMerge(method_index, bss_offset)) {
-          encoder.Reset(method_index, bss_offset);
-          ++number_of_entries;
-          first_index = false;
-        }
-      }
-      DCHECK_NE(number_of_entries, 0u);
-      offset += MethodBssMapping::ComputeSize(number_of_entries);
-    }
-  }
-  // Check that all dex files targeted by method bss entries are in `*dex_files_`.
-  CHECK_EQ(number_of_dex_files, bss_method_entry_references_.size());
-  return offset;
-}
-
-size_t OatWriter::InitOatDexFiles(size_t offset) {
-  // Initialize offsets of oat dex files.
-  for (OatDexFile& oat_dex_file : oat_dex_files_) {
-    oat_dex_file.offset_ = offset;
-    offset += oat_dex_file.SizeOf();
-  }
-  return offset;
-}
-
-size_t OatWriter::InitOatCode(size_t offset) {
-  // calculate the offsets within OatHeader to executable code
-  size_t old_offset = offset;
-  // required to be on a new page boundary
-  offset = RoundUp(offset, kPageSize);
-  oat_header_->SetExecutableOffset(offset);
-  size_executable_offset_alignment_ = offset - old_offset;
-  // TODO: Remove unused trampoline offsets from the OatHeader (requires oat version change).
-  oat_header_->SetInterpreterToInterpreterBridgeOffset(0);
-  oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0);
-  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
-    InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
-    const bool generate_debug_info = compiler_driver_->GetCompilerOptions().GenerateAnyDebugInfo();
-    size_t adjusted_offset = offset;
-
-    #define DO_TRAMPOLINE(field, fn_name)                                   \
-      offset = CompiledCode::AlignCode(offset, instruction_set);            \
-      adjusted_offset = offset + CompiledCode::CodeDelta(instruction_set);  \
-      oat_header_->Set ## fn_name ## Offset(adjusted_offset);               \
-      (field) = compiler_driver_->Create ## fn_name();                      \
-      if (generate_debug_info) {                                            \
-        debug::MethodDebugInfo info = {};                                   \
-        info.trampoline_name = #fn_name;                                    \
-        info.isa = instruction_set;                                         \
-        info.is_code_address_text_relative = true;                          \
-        /* Use the code offset rather than the `adjusted_offset`. */        \
-        info.code_address = offset - oat_header_->GetExecutableOffset();    \
-        info.code_size = (field)->size();                                   \
-        method_info_.push_back(std::move(info));                            \
-      }                                                                     \
-      offset += (field)->size();
-
-    DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup);
-    DO_TRAMPOLINE(quick_generic_jni_trampoline_, QuickGenericJniTrampoline);
-    DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline);
-    DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline);
-    DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge);
-
-    #undef DO_TRAMPOLINE
-  } else {
-    oat_header_->SetJniDlsymLookupOffset(0);
-    oat_header_->SetQuickGenericJniTrampolineOffset(0);
-    oat_header_->SetQuickImtConflictTrampolineOffset(0);
-    oat_header_->SetQuickResolutionTrampolineOffset(0);
-    oat_header_->SetQuickToInterpreterBridgeOffset(0);
-  }
-  return offset;
-}
-
-size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
-  if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) {
-    return offset;
-  }
-  InitCodeMethodVisitor code_visitor(this, offset);
-  bool success = VisitDexMethods(&code_visitor);
-  DCHECK(success);
-  offset = code_visitor.GetOffset();
-
-  if (HasImage()) {
-    InitImageMethodVisitor image_visitor(this, offset, dex_files_);
-    success = VisitDexMethods(&image_visitor);
-    image_visitor.Postprocess();
-    DCHECK(success);
-    offset = image_visitor.GetOffset();
-  }
-
-  return offset;
-}
-
-void OatWriter::InitBssLayout(InstructionSet instruction_set) {
-  {
-    InitBssLayoutMethodVisitor visitor(this);
-    bool success = VisitDexMethods(&visitor);
-    DCHECK(success);
-  }
-
-  DCHECK_EQ(bss_size_, 0u);
-  if (HasBootImage()) {
-    DCHECK(!map_boot_image_tables_to_bss_);
-    DCHECK(bss_string_entries_.empty());
-  }
-  if (!map_boot_image_tables_to_bss_ &&
-      bss_method_entries_.empty() &&
-      bss_type_entries_.empty() &&
-      bss_string_entries_.empty()) {
-    // Nothing to put to the .bss section.
-    return;
-  }
-
-  // Allocate space for boot image tables in the .bss section.
-  PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set);
-  if (map_boot_image_tables_to_bss_) {
-    for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
-      bss_size_ += space->GetImageHeader().GetBootImageConstantTablesSize();
-    }
-  }
-
-  bss_methods_offset_ = bss_size_;
-
-  // Prepare offsets for .bss ArtMethod entries.
-  for (auto& entry : bss_method_entries_) {
-    DCHECK_EQ(entry.second, 0u);
-    entry.second = bss_size_;
-    bss_size_ += static_cast<size_t>(pointer_size);
-  }
-
-  bss_roots_offset_ = bss_size_;
-
-  // Prepare offsets for .bss Class entries.
-  for (auto& entry : bss_type_entries_) {
-    DCHECK_EQ(entry.second, 0u);
-    entry.second = bss_size_;
-    bss_size_ += sizeof(GcRoot<mirror::Class>);
-  }
-  // Prepare offsets for .bss String entries.
-  for (auto& entry : bss_string_entries_) {
-    DCHECK_EQ(entry.second, 0u);
-    entry.second = bss_size_;
-    bss_size_ += sizeof(GcRoot<mirror::String>);
-  }
-}
-
-bool OatWriter::WriteRodata(OutputStream* out) {
-  CHECK(write_state_ == WriteState::kWriteRoData);
-
-  size_t file_offset = oat_data_offset_;
-  off_t current_offset = out->Seek(0, kSeekCurrent);
-  if (current_offset == static_cast<off_t>(-1)) {
-    PLOG(ERROR) << "Failed to retrieve current position in " << out->GetLocation();
-  }
-  DCHECK_GE(static_cast<size_t>(current_offset), file_offset + oat_header_->GetHeaderSize());
-  size_t relative_offset = current_offset - file_offset;
-
-  // Wrap out to update checksum with each write.
-  ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get());
-  out = &checksum_updating_out;
-
-  relative_offset = WriteClassOffsets(out, file_offset, relative_offset);
-  if (relative_offset == 0) {
-    PLOG(ERROR) << "Failed to write class offsets to " << out->GetLocation();
-    return false;
-  }
-
-  relative_offset = WriteClasses(out, file_offset, relative_offset);
-  if (relative_offset == 0) {
-    PLOG(ERROR) << "Failed to write classes to " << out->GetLocation();
-    return false;
-  }
-
-  relative_offset = WriteMethodBssMappings(out, file_offset, relative_offset);
-  if (relative_offset == 0) {
-    PLOG(ERROR) << "Failed to write method bss mappings to " << out->GetLocation();
-    return false;
-  }
-
-  relative_offset = WriteMaps(out, file_offset, relative_offset);
-  if (relative_offset == 0) {
-    PLOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
-    return false;
-  }
-
-  relative_offset = WriteOatDexFiles(out, file_offset, relative_offset);
-  if (relative_offset == 0) {
-    PLOG(ERROR) << "Failed to write oat dex information to " << out->GetLocation();
-    return false;
-  }
-
-  // Write padding.
-  off_t new_offset = out->Seek(size_executable_offset_alignment_, kSeekCurrent);
-  relative_offset += size_executable_offset_alignment_;
-  DCHECK_EQ(relative_offset, oat_header_->GetExecutableOffset());
-  size_t expected_file_offset = file_offset + relative_offset;
-  if (static_cast<uint32_t>(new_offset) != expected_file_offset) {
-    PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset
-                << " Expected: " << expected_file_offset << " File: " << out->GetLocation();
-    return 0;
-  }
-  DCHECK_OFFSET();
-
-  write_state_ = WriteState::kWriteText;
-  return true;
-}
-
-class OatWriter::WriteQuickeningInfoMethodVisitor : public DexMethodVisitor {
- public:
-  WriteQuickeningInfoMethodVisitor(OatWriter* writer,
-                                   OutputStream* out,
-                                   uint32_t offset,
-                                   SafeMap<const uint8_t*, uint32_t>* offset_map)
-      : DexMethodVisitor(writer, offset),
-        out_(out),
-        written_bytes_(0u),
-        offset_map_(offset_map) {}
-
-  bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED, const ClassDataItemIterator& it)
-      OVERRIDE {
-    uint32_t method_idx = it.GetMemberIndex();
-    CompiledMethod* compiled_method =
-        writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx));
-
-    if (HasQuickeningInfo(compiled_method)) {
-      ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
-      // Deduplication is already done on a pointer basis by the compiler driver,
-      // so we can simply compare the pointers to find out if things are duplicated.
-      if (offset_map_->find(map.data()) == offset_map_->end()) {
-        uint32_t length = map.size() * sizeof(map.front());
-        offset_map_->Put(map.data(), written_bytes_);
-        if (!out_->WriteFully(&length, sizeof(length)) ||
-            !out_->WriteFully(map.data(), length)) {
-          PLOG(ERROR) << "Failed to write quickening info for "
-                      << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to "
-                      << out_->GetLocation();
-          return false;
-        }
-        written_bytes_ += sizeof(length) + length;
-        offset_ += sizeof(length) + length;
-      }
-    }
-
-    return true;
-  }
-
-  size_t GetNumberOfWrittenBytes() const {
-    return written_bytes_;
-  }
-
- private:
-  OutputStream* const out_;
-  size_t written_bytes_;
-  // Maps quickening map to its offset in the file.
-  SafeMap<const uint8_t*, uint32_t>* offset_map_;
-};
-
-class OatWriter::WriteQuickeningIndicesMethodVisitor {
- public:
-  WriteQuickeningIndicesMethodVisitor(OutputStream* out,
-                                      uint32_t indices_offset,
-                                      const SafeMap<const uint8_t*, uint32_t>& offset_map,
-                                      std::vector<uint32_t>* dex_files_offset)
-      : out_(out),
-        indices_offset_(indices_offset),
-        written_bytes_(0u),
-        dex_files_offset_(dex_files_offset),
-        offset_map_(offset_map) {}
-
-  bool VisitDexMethods(const std::vector<const DexFile*>& dex_files, const CompilerDriver& driver) {
-    for (const DexFile* dex_file : dex_files) {
-      // Record the offset for this current dex file. It will be written in the vdex file
-      // later.
-      dex_files_offset_->push_back(indices_offset_ + GetNumberOfWrittenBytes());
-      const size_t class_def_count = dex_file->NumClassDefs();
-      for (size_t class_def_index = 0; class_def_index != class_def_count; ++class_def_index) {
-        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
-        const uint8_t* class_data = dex_file->GetClassData(class_def);
-        if (class_data == nullptr) {
-          continue;
-        }
-        for (ClassDataItemIterator class_it(*dex_file, class_data);
-             class_it.HasNext();
-             class_it.Next()) {
-          if (!class_it.IsAtMethod()) {
-            continue;
-          }
-          uint32_t method_idx = class_it.GetMemberIndex();
-          CompiledMethod* compiled_method =
-              driver.GetCompiledMethod(MethodReference(dex_file, method_idx));
-          if (HasQuickeningInfo(compiled_method)) {
-            uint32_t code_item_offset = class_it.GetMethodCodeItemOffset();
-            uint32_t offset = offset_map_.Get(compiled_method->GetVmapTable().data());
-            if (!out_->WriteFully(&code_item_offset, sizeof(code_item_offset)) ||
-                !out_->WriteFully(&offset, sizeof(offset))) {
-              PLOG(ERROR) << "Failed to write quickening info for "
-                          << dex_file->PrettyMethod(method_idx) << " to "
-                          << out_->GetLocation();
-              return false;
-            }
-            written_bytes_ += sizeof(code_item_offset) + sizeof(offset);
-          }
-        }
-      }
-    }
-    return true;
-  }
-
-  size_t GetNumberOfWrittenBytes() const {
-    return written_bytes_;
-  }
-
- private:
-  OutputStream* const out_;
-  const uint32_t indices_offset_;
-  size_t written_bytes_;
-  std::vector<uint32_t>* dex_files_offset_;
-  // Maps quickening map to its offset in the file.
-  const SafeMap<const uint8_t*, uint32_t>& offset_map_;
-};
-
-bool OatWriter::WriteQuickeningInfo(OutputStream* vdex_out) {
-  if (!kIsVdexEnabled) {
-    return true;
-  }
-
-  size_t initial_offset = vdex_size_;
-  size_t start_offset = RoundUp(initial_offset, 4u);
-
-  vdex_size_ = start_offset;
-  vdex_quickening_info_offset_ = vdex_size_;
-  size_quickening_info_alignment_ = start_offset - initial_offset;
-
-  off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(start_offset)) {
-    PLOG(ERROR) << "Failed to seek to quickening info section. Actual: " << actual_offset
-                << " Expected: " << start_offset
-                << " Output: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  if (compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) {
-    std::vector<uint32_t> dex_files_indices;
-    SafeMap<const uint8_t*, uint32_t> offset_map;
-    WriteQuickeningInfoMethodVisitor visitor1(this, vdex_out, start_offset, &offset_map);
-    if (!VisitDexMethods(&visitor1)) {
-      PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation();
-      return false;
-    }
-
-    WriteQuickeningIndicesMethodVisitor visitor2(vdex_out,
-                                                 visitor1.GetNumberOfWrittenBytes(),
-                                                 offset_map,
-                                                 &dex_files_indices);
-    if (!visitor2.VisitDexMethods(*dex_files_, *compiler_driver_)) {
-      PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation();
-      return false;
-    }
-
-    DCHECK_EQ(dex_files_->size(), dex_files_indices.size());
-    if (!vdex_out->WriteFully(
-            dex_files_indices.data(), sizeof(dex_files_indices[0]) * dex_files_indices.size())) {
-      PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation();
-      return false;
-    }
-
-    if (!vdex_out->Flush()) {
-      PLOG(ERROR) << "Failed to flush stream after writing quickening info."
-                  << " File: " << vdex_out->GetLocation();
-      return false;
-    }
-    size_quickening_info_ = visitor1.GetNumberOfWrittenBytes() +
-                            visitor2.GetNumberOfWrittenBytes() +
-                            dex_files_->size() * sizeof(uint32_t);
-  } else {
-    // We know we did not quicken.
-    size_quickening_info_ = 0;
-  }
-
-  vdex_size_ += size_quickening_info_;
-  return true;
-}
-
-bool OatWriter::WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps) {
-  if (!kIsVdexEnabled) {
-    return true;
-  }
-
-  if (verifier_deps == nullptr) {
-    // Nothing to write. Record the offset, but no need
-    // for alignment.
-    vdex_verifier_deps_offset_ = vdex_size_;
-    return true;
-  }
-
-  size_t initial_offset = vdex_size_;
-  size_t start_offset = RoundUp(initial_offset, 4u);
-
-  vdex_size_ = start_offset;
-  vdex_verifier_deps_offset_ = vdex_size_;
-  size_verifier_deps_alignment_ = start_offset - initial_offset;
-
-  off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(start_offset)) {
-    PLOG(ERROR) << "Failed to seek to verifier deps section. Actual: " << actual_offset
-                << " Expected: " << start_offset
-                << " Output: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  std::vector<uint8_t> buffer;
-  verifier_deps->Encode(*dex_files_, &buffer);
-
-  if (!vdex_out->WriteFully(buffer.data(), buffer.size())) {
-    PLOG(ERROR) << "Failed to write verifier deps."
-                << " File: " << vdex_out->GetLocation();
-    return false;
-  }
-  if (!vdex_out->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after writing verifier deps."
-                << " File: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  size_verifier_deps_ = buffer.size();
-  vdex_size_ += size_verifier_deps_;
-  return true;
-}
-
-bool OatWriter::WriteCode(OutputStream* out) {
-  CHECK(write_state_ == WriteState::kWriteText);
-
-  // Wrap out to update checksum with each write.
-  ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get());
-  out = &checksum_updating_out;
-
-  SetMultiOatRelativePatcherAdjustment();
-
-  const size_t file_offset = oat_data_offset_;
-  size_t relative_offset = oat_header_->GetExecutableOffset();
-  DCHECK_OFFSET();
-
-  relative_offset = WriteCode(out, file_offset, relative_offset);
-  if (relative_offset == 0) {
-    LOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
-    return false;
-  }
-
-  relative_offset = WriteCodeDexFiles(out, file_offset, relative_offset);
-  if (relative_offset == 0) {
-    LOG(ERROR) << "Failed to write oat code for dex files to " << out->GetLocation();
-    return false;
-  }
-
-  const off_t oat_end_file_offset = out->Seek(0, kSeekCurrent);
-  if (oat_end_file_offset == static_cast<off_t>(-1)) {
-    LOG(ERROR) << "Failed to get oat end file offset in " << out->GetLocation();
-    return false;
-  }
-
-  if (kIsDebugBuild) {
-    uint32_t size_total = 0;
-    #define DO_STAT(x) \
-      VLOG(compiler) << #x "=" << PrettySize(x) << " (" << (x) << "B)"; \
-      size_total += (x);
-
-    DO_STAT(size_vdex_header_);
-    DO_STAT(size_vdex_checksums_);
-    DO_STAT(size_dex_file_alignment_);
-    DO_STAT(size_executable_offset_alignment_);
-    DO_STAT(size_oat_header_);
-    DO_STAT(size_oat_header_key_value_store_);
-    DO_STAT(size_dex_file_);
-    DO_STAT(size_verifier_deps_);
-    DO_STAT(size_verifier_deps_alignment_);
-    DO_STAT(size_quickening_info_);
-    DO_STAT(size_quickening_info_alignment_);
-    DO_STAT(size_interpreter_to_interpreter_bridge_);
-    DO_STAT(size_interpreter_to_compiled_code_bridge_);
-    DO_STAT(size_jni_dlsym_lookup_);
-    DO_STAT(size_quick_generic_jni_trampoline_);
-    DO_STAT(size_quick_imt_conflict_trampoline_);
-    DO_STAT(size_quick_resolution_trampoline_);
-    DO_STAT(size_quick_to_interpreter_bridge_);
-    DO_STAT(size_trampoline_alignment_);
-    DO_STAT(size_method_header_);
-    DO_STAT(size_code_);
-    DO_STAT(size_code_alignment_);
-    DO_STAT(size_relative_call_thunks_);
-    DO_STAT(size_misc_thunks_);
-    DO_STAT(size_vmap_table_);
-    DO_STAT(size_method_info_);
-    DO_STAT(size_oat_dex_file_location_size_);
-    DO_STAT(size_oat_dex_file_location_data_);
-    DO_STAT(size_oat_dex_file_location_checksum_);
-    DO_STAT(size_oat_dex_file_offset_);
-    DO_STAT(size_oat_dex_file_class_offsets_offset_);
-    DO_STAT(size_oat_dex_file_lookup_table_offset_);
-    DO_STAT(size_oat_dex_file_dex_layout_sections_offset_);
-    DO_STAT(size_oat_dex_file_dex_layout_sections_);
-    DO_STAT(size_oat_dex_file_dex_layout_sections_alignment_);
-    DO_STAT(size_oat_dex_file_method_bss_mapping_offset_);
-    DO_STAT(size_oat_lookup_table_alignment_);
-    DO_STAT(size_oat_lookup_table_);
-    DO_STAT(size_oat_class_offsets_alignment_);
-    DO_STAT(size_oat_class_offsets_);
-    DO_STAT(size_oat_class_type_);
-    DO_STAT(size_oat_class_status_);
-    DO_STAT(size_oat_class_method_bitmaps_);
-    DO_STAT(size_oat_class_method_offsets_);
-    DO_STAT(size_method_bss_mappings_);
-    #undef DO_STAT
-
-    VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)";
-
-    CHECK_EQ(vdex_size_ + oat_size_, size_total);
-    CHECK_EQ(file_offset + size_total - vdex_size_, static_cast<size_t>(oat_end_file_offset));
-  }
-
-  CHECK_EQ(file_offset + oat_size_, static_cast<size_t>(oat_end_file_offset));
-  CHECK_EQ(oat_size_, relative_offset);
-
-  write_state_ = WriteState::kWriteHeader;
-  return true;
-}
-
-bool OatWriter::WriteHeader(OutputStream* out,
-                            uint32_t image_file_location_oat_checksum,
-                            uintptr_t image_file_location_oat_begin,
-                            int32_t image_patch_delta) {
-  CHECK(write_state_ == WriteState::kWriteHeader);
-
-  oat_header_->SetImageFileLocationOatChecksum(image_file_location_oat_checksum);
-  oat_header_->SetImageFileLocationOatDataBegin(image_file_location_oat_begin);
-  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
-    CHECK_EQ(image_patch_delta, 0);
-    CHECK_EQ(oat_header_->GetImagePatchDelta(), 0);
-  } else {
-    CHECK_ALIGNED(image_patch_delta, kPageSize);
-    oat_header_->SetImagePatchDelta(image_patch_delta);
-  }
-  oat_header_->UpdateChecksumWithHeaderData();
-
-  const size_t file_offset = oat_data_offset_;
-
-  off_t current_offset = out->Seek(0, kSeekCurrent);
-  if (current_offset == static_cast<off_t>(-1)) {
-    PLOG(ERROR) << "Failed to get current offset from " << out->GetLocation();
-    return false;
-  }
-  if (out->Seek(file_offset, kSeekSet) == static_cast<off_t>(-1)) {
-    PLOG(ERROR) << "Failed to seek to oat header position in " << out->GetLocation();
-    return false;
-  }
-  DCHECK_EQ(file_offset, static_cast<size_t>(out->Seek(0, kSeekCurrent)));
-
-  // Flush all other data before writing the header.
-  if (!out->Flush()) {
-    PLOG(ERROR) << "Failed to flush before writing oat header to " << out->GetLocation();
-    return false;
-  }
-  // Write the header.
-  size_t header_size = oat_header_->GetHeaderSize();
-  if (!out->WriteFully(oat_header_.get(), header_size)) {
-    PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation();
-    return false;
-  }
-  // Flush the header data.
-  if (!out->Flush()) {
-    PLOG(ERROR) << "Failed to flush after writing oat header to " << out->GetLocation();
-    return false;
-  }
-
-  if (out->Seek(current_offset, kSeekSet) == static_cast<off_t>(-1)) {
-    PLOG(ERROR) << "Failed to seek back after writing oat header to " << out->GetLocation();
-    return false;
-  }
-  DCHECK_EQ(current_offset, out->Seek(0, kSeekCurrent));
-
-  write_state_ = WriteState::kDone;
-  return true;
-}
-
-size_t OatWriter::WriteClassOffsets(OutputStream* out, size_t file_offset, size_t relative_offset) {
-  for (OatDexFile& oat_dex_file : oat_dex_files_) {
-    if (oat_dex_file.class_offsets_offset_ != 0u) {
-      // Class offsets are required to be 4 byte aligned.
-      if (UNLIKELY(!IsAligned<4u>(relative_offset))) {
-        size_t padding_size =  RoundUp(relative_offset, 4u) - relative_offset;
-        if (!WriteUpTo16BytesAlignment(out, padding_size, &size_oat_class_offsets_alignment_)) {
-          return 0u;
-        }
-        relative_offset += padding_size;
-      }
-      DCHECK_OFFSET();
-      if (!oat_dex_file.WriteClassOffsets(this, out)) {
-        return 0u;
-      }
-      relative_offset += oat_dex_file.GetClassOffsetsRawSize();
-    }
-  }
-  return relative_offset;
-}
-
-size_t OatWriter::WriteClasses(OutputStream* out, size_t file_offset, size_t relative_offset) {
-  const bool may_have_compiled = MayHaveCompiledMethods();
-  if (may_have_compiled) {
-    CHECK_EQ(oat_class_headers_.size(), oat_classes_.size());
-  }
-  for (size_t i = 0; i < oat_class_headers_.size(); ++i) {
-    // If there are any classes, the class offsets allocation aligns the offset.
-    DCHECK_ALIGNED(relative_offset, 4u);
-    DCHECK_OFFSET();
-    if (!oat_class_headers_[i].Write(this, out, oat_data_offset_)) {
-      return 0u;
-    }
-    relative_offset += oat_class_headers_[i].SizeOf();
-    if (may_have_compiled) {
-      if (!oat_classes_[i].Write(this, out)) {
-        return 0u;
-      }
-      relative_offset += oat_classes_[i].SizeOf();
-    }
-  }
-  return relative_offset;
-}
-
-size_t OatWriter::WriteMaps(OutputStream* out, size_t file_offset, size_t relative_offset) {
-  {
-    size_t vmap_tables_offset = relative_offset;
-    WriteMapMethodVisitor visitor(this, out, file_offset, relative_offset);
-    if (UNLIKELY(!VisitDexMethods(&visitor))) {
-      return 0;
-    }
-    relative_offset = visitor.GetOffset();
-    size_vmap_table_ = relative_offset - vmap_tables_offset;
-  }
-  {
-    size_t method_infos_offset = relative_offset;
-    WriteMethodInfoVisitor visitor(this, out, file_offset, relative_offset);
-    if (UNLIKELY(!VisitDexMethods(&visitor))) {
-      return 0;
-    }
-    relative_offset = visitor.GetOffset();
-    size_method_info_ = relative_offset - method_infos_offset;
-  }
-
-  return relative_offset;
-}
-
-size_t OatWriter::WriteMethodBssMappings(OutputStream* out,
-                                         size_t file_offset,
-                                         size_t relative_offset) {
-  TimingLogger::ScopedTiming split("WriteMethodBssMappings", timings_);
-
-  for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
-    const DexFile* dex_file = (*dex_files_)[i];
-    OatDexFile* oat_dex_file = &oat_dex_files_[i];
-    auto it = bss_method_entry_references_.find(dex_file);
-    if (it != bss_method_entry_references_.end()) {
-      const BitVector& method_indexes = it->second;
-      // If there are any classes, the class offsets allocation aligns the offset
-      // and we cannot have method bss mappings without class offsets.
-      static_assert(alignof(MethodBssMapping) == sizeof(uint32_t),
-                    "MethodBssMapping alignment check.");
-      DCHECK_ALIGNED(relative_offset, sizeof(uint32_t));
-
-      linker::MethodBssMappingEncoder encoder(
-          GetInstructionSetPointerSize(oat_header_->GetInstructionSet()));
-      // Allocate a sufficiently large MethodBssMapping.
-      size_t number_of_method_indexes = method_indexes.NumSetBits();
-      DCHECK_NE(number_of_method_indexes, 0u);
-      size_t max_mappings_size = MethodBssMapping::ComputeSize(number_of_method_indexes);
-      DCHECK_ALIGNED(max_mappings_size, sizeof(uint32_t));
-      std::unique_ptr<uint32_t[]> storage(new uint32_t[max_mappings_size / sizeof(uint32_t)]);
-      MethodBssMapping* mappings = new(storage.get()) MethodBssMapping(number_of_method_indexes);
-      mappings->ClearPadding();
-      // Encode the MethodBssMapping.
-      auto init_it = mappings->begin();
-      bool first_index = true;
-      for (uint32_t method_index : method_indexes.Indexes()) {
-        size_t bss_offset = bss_method_entries_.Get(MethodReference(dex_file, method_index));
-        if (first_index) {
-          first_index = false;
-          encoder.Reset(method_index, bss_offset);
-        } else if (!encoder.TryMerge(method_index, bss_offset)) {
-          *init_it = encoder.GetEntry();
-          ++init_it;
-          encoder.Reset(method_index, bss_offset);
-        }
-      }
-      // Store the last entry and shrink the mapping to the actual size.
-      *init_it = encoder.GetEntry();
-      ++init_it;
-      DCHECK(init_it <= mappings->end());
-      mappings->SetSize(std::distance(mappings->begin(), init_it));
-      size_t mappings_size = MethodBssMapping::ComputeSize(mappings->size());
-
-      DCHECK_EQ(relative_offset, oat_dex_file->method_bss_mapping_offset_);
-      DCHECK_OFFSET();
-      if (!out->WriteFully(storage.get(), mappings_size)) {
-        return 0u;
-      }
-      size_method_bss_mappings_ += mappings_size;
-      relative_offset += mappings_size;
-    } else {
-      DCHECK_EQ(0u, oat_dex_file->method_bss_mapping_offset_);
-    }
-  }
-  return relative_offset;
-}
-
-size_t OatWriter::WriteOatDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset) {
-  TimingLogger::ScopedTiming split("WriteOatDexFiles", timings_);
-
-  for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
-    OatDexFile* oat_dex_file = &oat_dex_files_[i];
-    DCHECK_EQ(relative_offset, oat_dex_file->offset_);
-    DCHECK_OFFSET();
-
-    // Write OatDexFile.
-    if (!oat_dex_file->Write(this, out)) {
-      return 0u;
-    }
-    relative_offset += oat_dex_file->SizeOf();
-  }
-
-  return relative_offset;
-}
-
-size_t OatWriter::WriteCode(OutputStream* out, size_t file_offset, size_t relative_offset) {
-  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
-    InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
-
-    #define DO_TRAMPOLINE(field) \
-      do { \
-        uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); \
-        uint32_t alignment_padding = aligned_offset - relative_offset; \
-        out->Seek(alignment_padding, kSeekCurrent); \
-        size_trampoline_alignment_ += alignment_padding; \
-        if (!out->WriteFully((field)->data(), (field)->size())) { \
-          PLOG(ERROR) << "Failed to write " # field " to " << out->GetLocation(); \
-          return false; \
-        } \
-        size_ ## field += (field)->size(); \
-        relative_offset += alignment_padding + (field)->size(); \
-        DCHECK_OFFSET(); \
-      } while (false)
-
-    DO_TRAMPOLINE(jni_dlsym_lookup_);
-    DO_TRAMPOLINE(quick_generic_jni_trampoline_);
-    DO_TRAMPOLINE(quick_imt_conflict_trampoline_);
-    DO_TRAMPOLINE(quick_resolution_trampoline_);
-    DO_TRAMPOLINE(quick_to_interpreter_bridge_);
-    #undef DO_TRAMPOLINE
-  }
-  return relative_offset;
-}
-
-size_t OatWriter::WriteCodeDexFiles(OutputStream* out,
-                                    size_t file_offset,
-                                    size_t relative_offset) {
-  #define VISIT(VisitorType)                                              \
-    do {                                                                  \
-      VisitorType visitor(this, out, file_offset, relative_offset);       \
-      if (UNLIKELY(!VisitDexMethods(&visitor))) {                         \
-        return 0;                                                         \
-      }                                                                   \
-      relative_offset = visitor.GetOffset();                              \
-    } while (false)
-
-  VISIT(WriteCodeMethodVisitor);
-
-  #undef VISIT
-
-  size_code_alignment_ += relative_patcher_->CodeAlignmentSize();
-  size_relative_call_thunks_ += relative_patcher_->RelativeCallThunksSize();
-  size_misc_thunks_ += relative_patcher_->MiscThunksSize();
-
-  return relative_offset;
-}
-
-bool OatWriter::RecordOatDataOffset(OutputStream* out) {
-  // Get the elf file offset of the oat file.
-  const off_t raw_file_offset = out->Seek(0, kSeekCurrent);
-  if (raw_file_offset == static_cast<off_t>(-1)) {
-    LOG(ERROR) << "Failed to get file offset in " << out->GetLocation();
-    return false;
-  }
-  oat_data_offset_ = static_cast<size_t>(raw_file_offset);
-  return true;
-}
-
-bool OatWriter::ReadDexFileHeader(File* file, OatDexFile* oat_dex_file) {
-  // Read the dex file header and perform minimal verification.
-  uint8_t raw_header[sizeof(DexFile::Header)];
-  if (!file->ReadFully(&raw_header, sizeof(DexFile::Header))) {
-    PLOG(ERROR) << "Failed to read dex file header. Actual: "
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (!ValidateDexFileHeader(raw_header, oat_dex_file->GetLocation())) {
-    return false;
-  }
-
-  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_header);
-  oat_dex_file->dex_file_size_ = header->file_size_;
-  oat_dex_file->dex_file_location_checksum_ = header->checksum_;
-  oat_dex_file->class_offsets_.resize(header->class_defs_size_);
-  return true;
-}
-
-bool OatWriter::ValidateDexFileHeader(const uint8_t* raw_header, const char* location) {
-  if (!DexFile::IsMagicValid(raw_header)) {
-    LOG(ERROR) << "Invalid magic number in dex file header. " << " File: " << location;
-    return false;
-  }
-  if (!DexFile::IsVersionValid(raw_header)) {
-    LOG(ERROR) << "Invalid version number in dex file header. " << " File: " << location;
-    return false;
-  }
-  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_header);
-  if (header->file_size_ < sizeof(DexFile::Header)) {
-    LOG(ERROR) << "Dex file header specifies file size insufficient to contain the header."
-               << " File: " << location;
-    return false;
-  }
-  return true;
-}
-
-bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_vdex) {
-  TimingLogger::ScopedTiming split("Write Dex files", timings_);
-
-  vdex_dex_files_offset_ = vdex_size_;
-
-  // Write dex files.
-  for (OatDexFile& oat_dex_file : oat_dex_files_) {
-    if (!WriteDexFile(out, file, &oat_dex_file, update_input_vdex)) {
-      return false;
-    }
-  }
-
-  CloseSources();
-  return true;
-}
-
-void OatWriter::CloseSources() {
-  for (OatDexFile& oat_dex_file : oat_dex_files_) {
-    oat_dex_file.source_.Clear();  // Get rid of the reference, it's about to be invalidated.
-  }
-  zipped_dex_files_.clear();
-  zip_archives_.clear();
-  raw_dex_files_.clear();
-}
-
-bool OatWriter::WriteDexFile(OutputStream* out,
-                             File* file,
-                             OatDexFile* oat_dex_file,
-                             bool update_input_vdex) {
-  if (!SeekToDexFile(out, file, oat_dex_file)) {
-    return false;
-  }
-  if (profile_compilation_info_ != nullptr) {
-    CHECK(!update_input_vdex) << "We should never update the input vdex when doing dexlayout";
-    if (!LayoutAndWriteDexFile(out, oat_dex_file)) {
-      return false;
-    }
-  } else if (oat_dex_file->source_.IsZipEntry()) {
-    DCHECK(!update_input_vdex);
-    if (!WriteDexFile(out, file, oat_dex_file, oat_dex_file->source_.GetZipEntry())) {
-      return false;
-    }
-  } else if (oat_dex_file->source_.IsRawFile()) {
-    DCHECK(!update_input_vdex);
-    if (!WriteDexFile(out, file, oat_dex_file, oat_dex_file->source_.GetRawFile())) {
-      return false;
-    }
-  } else {
-    DCHECK(oat_dex_file->source_.IsRawData());
-    if (!WriteDexFile(out, oat_dex_file, oat_dex_file->source_.GetRawData(), update_input_vdex)) {
-      return false;
-    }
-  }
-
-  // Update current size and account for the written data.
-  if (kIsVdexEnabled) {
-    DCHECK_EQ(vdex_size_, oat_dex_file->dex_file_offset_);
-    vdex_size_ += oat_dex_file->dex_file_size_;
-  } else {
-    DCHECK(!update_input_vdex);
-    DCHECK_EQ(oat_size_, oat_dex_file->dex_file_offset_);
-    oat_size_ += oat_dex_file->dex_file_size_;
-  }
-  size_dex_file_ += oat_dex_file->dex_file_size_;
-  return true;
-}
-
-bool OatWriter::SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file) {
-  // Dex files are required to be 4 byte aligned.
-  size_t initial_offset = kIsVdexEnabled ? vdex_size_ : oat_size_;
-  size_t start_offset = RoundUp(initial_offset, 4);
-  size_t file_offset = kIsVdexEnabled ? start_offset : (oat_data_offset_ + start_offset);
-  size_dex_file_alignment_ += start_offset - initial_offset;
-
-  // Seek to the start of the dex file and flush any pending operations in the stream.
-  // Verify that, after flushing the stream, the file is at the same offset as the stream.
-  off_t actual_offset = out->Seek(file_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(file_offset)) {
-    PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset
-                << " Expected: " << file_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (!out->Flush()) {
-    PLOG(ERROR) << "Failed to flush before writing dex file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  actual_offset = lseek(file->Fd(), 0, SEEK_CUR);
-  if (actual_offset != static_cast<off_t>(file_offset)) {
-    PLOG(ERROR) << "Stream/file position mismatch! Actual: " << actual_offset
-                << " Expected: " << file_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-
-  if (kIsVdexEnabled) {
-    vdex_size_ = start_offset;
-  } else {
-    oat_size_ = start_offset;
-  }
-  oat_dex_file->dex_file_offset_ = start_offset;
-  return true;
-}
-
-bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_file) {
-  TimingLogger::ScopedTiming split("Dex Layout", timings_);
-  std::string error_msg;
-  std::string location(oat_dex_file->GetLocation());
-  std::unique_ptr<const DexFile> dex_file;
-  if (oat_dex_file->source_.IsZipEntry()) {
-    ZipEntry* zip_entry = oat_dex_file->source_.GetZipEntry();
-    std::unique_ptr<MemMap> mem_map(
-        zip_entry->ExtractToMemMap(location.c_str(), "classes.dex", &error_msg));
-    if (mem_map == nullptr) {
-      LOG(ERROR) << "Failed to extract dex file to mem map for layout: " << error_msg;
-      return false;
-    }
-    dex_file = DexFile::Open(location,
-                             zip_entry->GetCrc32(),
-                             std::move(mem_map),
-                             /* verify */ true,
-                             /* verify_checksum */ true,
-                             &error_msg);
-  } else if (oat_dex_file->source_.IsRawFile()) {
-    File* raw_file = oat_dex_file->source_.GetRawFile();
-    int dup_fd = dup(raw_file->Fd());
-    if (dup_fd < 0) {
-      PLOG(ERROR) << "Failed to dup dex file descriptor (" << raw_file->Fd() << ") at " << location;
-      return false;
-    }
-    dex_file = DexFile::OpenDex(dup_fd, location, /* verify_checksum */ true, &error_msg);
-  } else {
-    // The source data is a vdex file.
-    CHECK(oat_dex_file->source_.IsRawData())
-        << static_cast<size_t>(oat_dex_file->source_.GetType());
-    const uint8_t* raw_dex_file = oat_dex_file->source_.GetRawData();
-    // Note: The raw data has already been checked to contain the header
-    // and all the data that the header specifies as the file size.
-    DCHECK(raw_dex_file != nullptr);
-    DCHECK(ValidateDexFileHeader(raw_dex_file, oat_dex_file->GetLocation()));
-    const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file);
-    // Since the source may have had its layout changed, or may be quickened, don't verify it.
-    dex_file = DexFile::Open(raw_dex_file,
-                             header->file_size_,
-                             location,
-                             oat_dex_file->dex_file_location_checksum_,
-                             nullptr,
-                             /* verify */ false,
-                             /* verify_checksum */ false,
-                             &error_msg);
-  }
-  if (dex_file == nullptr) {
-    LOG(ERROR) << "Failed to open dex file for layout: " << error_msg;
-    return false;
-  }
-  Options options;
-  options.output_to_memmap_ = true;
-  DexLayout dex_layout(options, profile_compilation_info_, nullptr);
-  dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0);
-  std::unique_ptr<MemMap> mem_map(dex_layout.GetAndReleaseMemMap());
-  if (!WriteDexFile(out, oat_dex_file, mem_map->Begin(), /* update_input_vdex */ false)) {
-    return false;
-  }
-  oat_dex_file->dex_sections_layout_ = dex_layout.GetSections();
-  // Set the checksum of the new oat dex file to be the original file's checksum.
-  oat_dex_file->dex_file_location_checksum_ = dex_file->GetLocationChecksum();
-  return true;
-}
-
-bool OatWriter::WriteDexFile(OutputStream* out,
-                             File* file,
-                             OatDexFile* oat_dex_file,
-                             ZipEntry* dex_file) {
-  size_t start_offset = kIsVdexEnabled ? vdex_size_ : oat_data_offset_ + oat_size_;
-  DCHECK_EQ(static_cast<off_t>(start_offset), out->Seek(0, kSeekCurrent));
-
-  // Extract the dex file and get the extracted size.
-  std::string error_msg;
-  if (!dex_file->ExtractToFile(*file, &error_msg)) {
-    LOG(ERROR) << "Failed to extract dex file from ZIP entry: " << error_msg
-               << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (file->Flush() != 0) {
-    PLOG(ERROR) << "Failed to flush dex file from ZIP entry."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  off_t extracted_end = lseek(file->Fd(), 0, SEEK_CUR);
-  if (extracted_end == static_cast<off_t>(-1)) {
-    PLOG(ERROR) << "Failed get end offset after writing dex file from ZIP entry."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (extracted_end < static_cast<off_t>(start_offset)) {
-    LOG(ERROR) << "Dex file end position is before start position! End: " << extracted_end
-               << " Start: " << start_offset
-               << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  uint64_t extracted_size = static_cast<uint64_t>(extracted_end - start_offset);
-  if (extracted_size < sizeof(DexFile::Header)) {
-    LOG(ERROR) << "Extracted dex file is shorter than dex file header. size: "
-               << extracted_size << " File: " << oat_dex_file->GetLocation();
-    return false;
-  }
-
-  // Read the dex file header and extract required data to OatDexFile.
-  off_t actual_offset = lseek(file->Fd(), start_offset, SEEK_SET);
-  if (actual_offset != static_cast<off_t>(start_offset)) {
-    PLOG(ERROR) << "Failed to seek back to dex file header. Actual: " << actual_offset
-                << " Expected: " << start_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (!ReadDexFileHeader(file, oat_dex_file)) {
-    return false;
-  }
-  if (extracted_size < oat_dex_file->dex_file_size_) {
-    LOG(ERROR) << "Extracted truncated dex file. Extracted size: " << extracted_size
-               << " file size from header: " << oat_dex_file->dex_file_size_
-               << " File: " << oat_dex_file->GetLocation();
-    return false;
-  }
-
-  // Override the checksum from header with the CRC from ZIP entry.
-  oat_dex_file->dex_file_location_checksum_ = dex_file->GetCrc32();
-
-  // Seek both file and stream to the end offset.
-  size_t end_offset = start_offset + oat_dex_file->dex_file_size_;
-  actual_offset = lseek(file->Fd(), end_offset, SEEK_SET);
-  if (actual_offset != static_cast<off_t>(end_offset)) {
-    PLOG(ERROR) << "Failed to seek to end of dex file. Actual: " << actual_offset
-                << " Expected: " << end_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  actual_offset = out->Seek(end_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(end_offset)) {
-    PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset
-                << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation();
-    return false;
-  }
-  if (!out->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after seeking over dex file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-
-  // If we extracted more than the size specified in the header, truncate the file.
-  if (extracted_size > oat_dex_file->dex_file_size_) {
-    if (file->SetLength(end_offset) != 0) {
-      PLOG(ERROR) << "Failed to truncate excessive dex file length."
-                  << " File: " << oat_dex_file->GetLocation()
-                  << " Output: " << file->GetPath();
-      return false;
-    }
-  }
-
-  return true;
-}
-
-bool OatWriter::WriteDexFile(OutputStream* out,
-                             File* file,
-                             OatDexFile* oat_dex_file,
-                             File* dex_file) {
-  size_t start_offset = kIsVdexEnabled ? vdex_size_ : oat_data_offset_ + oat_size_;
-  DCHECK_EQ(static_cast<off_t>(start_offset), out->Seek(0, kSeekCurrent));
-
-  off_t input_offset = lseek(dex_file->Fd(), 0, SEEK_SET);
-  if (input_offset != static_cast<off_t>(0)) {
-    PLOG(ERROR) << "Failed to seek to dex file header. Actual: " << input_offset
-                << " Expected: 0"
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (!ReadDexFileHeader(dex_file, oat_dex_file)) {
-    return false;
-  }
-
-  // Copy the input dex file using sendfile().
-  if (!file->Copy(dex_file, 0, oat_dex_file->dex_file_size_)) {
-    PLOG(ERROR) << "Failed to copy dex file to oat file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (file->Flush() != 0) {
-    PLOG(ERROR) << "Failed to flush dex file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-
-  // Check file position and seek the stream to the end offset.
-  size_t end_offset = start_offset + oat_dex_file->dex_file_size_;
-  off_t actual_offset = lseek(file->Fd(), 0, SEEK_CUR);
-  if (actual_offset != static_cast<off_t>(end_offset)) {
-    PLOG(ERROR) << "Unexpected file position after copying dex file. Actual: " << actual_offset
-                << " Expected: " << end_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  actual_offset = out->Seek(end_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(end_offset)) {
-    PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset
-                << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation();
-    return false;
-  }
-  if (!out->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after seeking over dex file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-
-  return true;
-}
-
-bool OatWriter::WriteDexFile(OutputStream* out,
-                             OatDexFile* oat_dex_file,
-                             const uint8_t* dex_file,
-                             bool update_input_vdex) {
-  // Note: The raw data has already been checked to contain the header
-  // and all the data that the header specifies as the file size.
-  DCHECK(dex_file != nullptr);
-  DCHECK(ValidateDexFileHeader(dex_file, oat_dex_file->GetLocation()));
-  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(dex_file);
-
-  if (update_input_vdex) {
-    // The vdex already contains the dex code, no need to write it again.
-  } else {
-    if (!out->WriteFully(dex_file, header->file_size_)) {
-      PLOG(ERROR) << "Failed to write dex file " << oat_dex_file->GetLocation()
-                  << " to " << out->GetLocation();
-      return false;
-    }
-    if (!out->Flush()) {
-      PLOG(ERROR) << "Failed to flush stream after writing dex file."
-                  << " File: " << oat_dex_file->GetLocation();
-      return false;
-    }
-  }
-
-  // Update dex file size and resize class offsets in the OatDexFile.
-  // Note: For raw data, the checksum is passed directly to AddRawDexFileSource().
-  // Note: For vdex, the checksum is copied from the existing vdex file.
-  oat_dex_file->dex_file_size_ = header->file_size_;
-  oat_dex_file->class_offsets_.resize(header->class_defs_size_);
-  return true;
-}
-
-bool OatWriter::OpenDexFiles(
-    File* file,
-    bool verify,
-    /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
-    /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
-  TimingLogger::ScopedTiming split("OpenDexFiles", timings_);
-
-  if (oat_dex_files_.empty()) {
-    // Nothing to do.
-    return true;
-  }
-
-  size_t map_offset = oat_dex_files_[0].dex_file_offset_;
-  size_t length = kIsVdexEnabled ? (vdex_size_ - map_offset) : (oat_size_ - map_offset);
-
-  std::string error_msg;
-  std::unique_ptr<MemMap> dex_files_map(MemMap::MapFile(
-      length,
-      PROT_READ | PROT_WRITE,
-      MAP_SHARED,
-      file->Fd(),
-      kIsVdexEnabled ? map_offset : (oat_data_offset_ + map_offset),
-      /* low_4gb */ false,
-      file->GetPath().c_str(),
-      &error_msg));
-  if (dex_files_map == nullptr) {
-    LOG(ERROR) << "Failed to mmap() dex files from oat file. File: " << file->GetPath()
-               << " error: " << error_msg;
-    return false;
-  }
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  for (OatDexFile& oat_dex_file : oat_dex_files_) {
-    // Make sure no one messed with input files while we were copying data.
-    // At the very least we need consistent file size and number of class definitions.
-    const uint8_t* raw_dex_file =
-        dex_files_map->Begin() + oat_dex_file.dex_file_offset_ - map_offset;
-    if (!ValidateDexFileHeader(raw_dex_file, oat_dex_file.GetLocation())) {
-      // Note: ValidateDexFileHeader() already logged an error message.
-      LOG(ERROR) << "Failed to verify written dex file header!"
-          << " Output: " << file->GetPath() << " ~ " << std::hex << map_offset
-          << " ~ " << static_cast<const void*>(raw_dex_file);
-      return false;
-    }
-    const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file);
-    if (header->file_size_ != oat_dex_file.dex_file_size_) {
-      LOG(ERROR) << "File size mismatch in written dex file header! Expected: "
-          << oat_dex_file.dex_file_size_ << " Actual: " << header->file_size_
-          << " Output: " << file->GetPath();
-      return false;
-    }
-    if (header->class_defs_size_ != oat_dex_file.class_offsets_.size()) {
-      LOG(ERROR) << "Class defs size mismatch in written dex file header! Expected: "
-          << oat_dex_file.class_offsets_.size() << " Actual: " << header->class_defs_size_
-          << " Output: " << file->GetPath();
-      return false;
-    }
-
-    // Now, open the dex file.
-    dex_files.emplace_back(DexFile::Open(raw_dex_file,
-                                         oat_dex_file.dex_file_size_,
-                                         oat_dex_file.GetLocation(),
-                                         oat_dex_file.dex_file_location_checksum_,
-                                         /* oat_dex_file */ nullptr,
-                                         verify,
-                                         verify,
-                                         &error_msg));
-    if (dex_files.back() == nullptr) {
-      LOG(ERROR) << "Failed to open dex file from oat file. File: " << oat_dex_file.GetLocation()
-                 << " Error: " << error_msg;
-      return false;
-    }
-  }
-
-  *opened_dex_files_map = std::move(dex_files_map);
-  *opened_dex_files = std::move(dex_files);
-  return true;
-}
-
-bool OatWriter::WriteTypeLookupTables(
-    OutputStream* oat_rodata,
-    const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files) {
-  TimingLogger::ScopedTiming split("WriteTypeLookupTables", timings_);
-
-  uint32_t expected_offset = oat_data_offset_ + oat_size_;
-  off_t actual_offset = oat_rodata->Seek(expected_offset, kSeekSet);
-  if (static_cast<uint32_t>(actual_offset) != expected_offset) {
-    PLOG(ERROR) << "Failed to seek to TypeLookupTable section. Actual: " << actual_offset
-                << " Expected: " << expected_offset << " File: " << oat_rodata->GetLocation();
-    return false;
-  }
-
-  DCHECK_EQ(opened_dex_files.size(), oat_dex_files_.size());
-  for (size_t i = 0, size = opened_dex_files.size(); i != size; ++i) {
-    OatDexFile* oat_dex_file = &oat_dex_files_[i];
-    DCHECK_EQ(oat_dex_file->lookup_table_offset_, 0u);
-
-    if (oat_dex_file->create_type_lookup_table_ != CreateTypeLookupTable::kCreate ||
-        oat_dex_file->class_offsets_.empty()) {
-      continue;
-    }
-
-    size_t table_size = TypeLookupTable::RawDataLength(oat_dex_file->class_offsets_.size());
-    if (table_size == 0u) {
-      continue;
-    }
-
-    // Create the lookup table. When `nullptr` is given as the storage buffer,
-    // TypeLookupTable allocates its own and OatDexFile takes ownership.
-    const DexFile& dex_file = *opened_dex_files[i];
-    {
-      std::unique_ptr<TypeLookupTable> type_lookup_table =
-          TypeLookupTable::Create(dex_file, /* storage */ nullptr);
-      type_lookup_table_oat_dex_files_.push_back(
-          std::make_unique<art::OatDexFile>(std::move(type_lookup_table)));
-      dex_file.SetOatDexFile(type_lookup_table_oat_dex_files_.back().get());
-    }
-    TypeLookupTable* const table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable();
-
-    // Type tables are required to be 4 byte aligned.
-    size_t initial_offset = oat_size_;
-    size_t rodata_offset = RoundUp(initial_offset, 4);
-    size_t padding_size = rodata_offset - initial_offset;
-
-    if (padding_size != 0u) {
-      std::vector<uint8_t> buffer(padding_size, 0u);
-      if (!oat_rodata->WriteFully(buffer.data(), padding_size)) {
-        PLOG(ERROR) << "Failed to write lookup table alignment padding."
-                    << " File: " << oat_dex_file->GetLocation()
-                    << " Output: " << oat_rodata->GetLocation();
-        return false;
-      }
-    }
-
-    DCHECK_EQ(oat_data_offset_ + rodata_offset,
-              static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent)));
-    DCHECK_EQ(table_size, table->RawDataLength());
-
-    if (!oat_rodata->WriteFully(table->RawData(), table_size)) {
-      PLOG(ERROR) << "Failed to write lookup table."
-                  << " File: " << oat_dex_file->GetLocation()
-                  << " Output: " << oat_rodata->GetLocation();
-      return false;
-    }
-
-    oat_dex_file->lookup_table_offset_ = rodata_offset;
-
-    oat_size_ += padding_size + table_size;
-    size_oat_lookup_table_ += table_size;
-    size_oat_lookup_table_alignment_ += padding_size;
-  }
-
-  if (!oat_rodata->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after writing type lookup tables."
-                << " File: " << oat_rodata->GetLocation();
-    return false;
-  }
-
-  return true;
-}
-
-bool OatWriter::WriteDexLayoutSections(
-    OutputStream* oat_rodata,
-    const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files) {
-  TimingLogger::ScopedTiming split(__FUNCTION__, timings_);
-
-  if (!kWriteDexLayoutInfo) {
-    return true;;
-  }
-
-  uint32_t expected_offset = oat_data_offset_ + oat_size_;
-  off_t actual_offset = oat_rodata->Seek(expected_offset, kSeekSet);
-  if (static_cast<uint32_t>(actual_offset) != expected_offset) {
-    PLOG(ERROR) << "Failed to seek to dex layout section offset section. Actual: " << actual_offset
-                << " Expected: " << expected_offset << " File: " << oat_rodata->GetLocation();
-    return false;
-  }
-
-  DCHECK_EQ(opened_dex_files.size(), oat_dex_files_.size());
-  size_t rodata_offset = oat_size_;
-  for (size_t i = 0, size = opened_dex_files.size(); i != size; ++i) {
-    OatDexFile* oat_dex_file = &oat_dex_files_[i];
-    DCHECK_EQ(oat_dex_file->dex_sections_layout_offset_, 0u);
-
-    // Write dex layout section alignment bytes.
-    const size_t padding_size =
-        RoundUp(rodata_offset, alignof(DexLayoutSections)) - rodata_offset;
-    if (padding_size != 0u) {
-      std::vector<uint8_t> buffer(padding_size, 0u);
-      if (!oat_rodata->WriteFully(buffer.data(), padding_size)) {
-        PLOG(ERROR) << "Failed to write lookup table alignment padding."
-                    << " File: " << oat_dex_file->GetLocation()
-                    << " Output: " << oat_rodata->GetLocation();
-        return false;
-      }
-      size_oat_dex_file_dex_layout_sections_alignment_ += padding_size;
-      rodata_offset += padding_size;
-    }
-
-    DCHECK_ALIGNED(rodata_offset, alignof(DexLayoutSections));
-    DCHECK_EQ(oat_data_offset_ + rodata_offset,
-              static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent)));
-    DCHECK(oat_dex_file != nullptr);
-    if (!oat_rodata->WriteFully(&oat_dex_file->dex_sections_layout_,
-                                sizeof(oat_dex_file->dex_sections_layout_))) {
-      PLOG(ERROR) << "Failed to write dex layout sections."
-                  << " File: " << oat_dex_file->GetLocation()
-                  << " Output: " << oat_rodata->GetLocation();
-      return false;
-    }
-    oat_dex_file->dex_sections_layout_offset_ = rodata_offset;
-    size_oat_dex_file_dex_layout_sections_ += sizeof(oat_dex_file->dex_sections_layout_);
-    rodata_offset += sizeof(oat_dex_file->dex_sections_layout_);
-  }
-  oat_size_ = rodata_offset;
-
-  if (!oat_rodata->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after writing type dex layout sections."
-                << " File: " << oat_rodata->GetLocation();
-    return false;
-  }
-
-  return true;
-}
-
-bool OatWriter::WriteChecksumsAndVdexHeader(OutputStream* vdex_out) {
-  if (!kIsVdexEnabled) {
-    return true;
-  }
-  // Write checksums
-  off_t actual_offset = vdex_out->Seek(sizeof(VdexFile::Header), kSeekSet);
-  if (actual_offset != sizeof(VdexFile::Header)) {
-    PLOG(ERROR) << "Failed to seek to the checksum location of vdex file. Actual: " << actual_offset
-                << " File: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
-    OatDexFile* oat_dex_file = &oat_dex_files_[i];
-    if (!vdex_out->WriteFully(
-            &oat_dex_file->dex_file_location_checksum_, sizeof(VdexFile::VdexChecksum))) {
-      PLOG(ERROR) << "Failed to write dex file location checksum. File: "
-                  << vdex_out->GetLocation();
-      return false;
-    }
-    size_vdex_checksums_ += sizeof(VdexFile::VdexChecksum);
-  }
-
-  // Write header.
-  actual_offset = vdex_out->Seek(0, kSeekSet);
-  if (actual_offset != 0) {
-    PLOG(ERROR) << "Failed to seek to the beginning of vdex file. Actual: " << actual_offset
-                << " File: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  DCHECK_NE(vdex_dex_files_offset_, 0u);
-  DCHECK_NE(vdex_verifier_deps_offset_, 0u);
-
-  size_t dex_section_size = vdex_verifier_deps_offset_ - vdex_dex_files_offset_;
-  size_t verifier_deps_section_size = vdex_quickening_info_offset_ - vdex_verifier_deps_offset_;
-  size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_;
-
-  VdexFile::Header vdex_header(oat_dex_files_.size(),
-                               dex_section_size,
-                               verifier_deps_section_size,
-                               quickening_info_section_size);
-  if (!vdex_out->WriteFully(&vdex_header, sizeof(VdexFile::Header))) {
-    PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
-    return false;
-  }
-  size_vdex_header_ = sizeof(VdexFile::Header);
-
-  if (!vdex_out->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after writing to vdex file."
-                << " File: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  return true;
-}
-
-bool OatWriter::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) {
-  return WriteUpTo16BytesAlignment(out, aligned_code_delta, &size_code_alignment_);
-}
-
-bool OatWriter::WriteUpTo16BytesAlignment(OutputStream* out, uint32_t size, uint32_t* stat) {
-  static const uint8_t kPadding[] = {
-      0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u
-  };
-  DCHECK_LE(size, sizeof(kPadding));
-  if (UNLIKELY(!out->WriteFully(kPadding, size))) {
-    return false;
-  }
-  *stat += size;
-  return true;
-}
-
-void OatWriter::SetMultiOatRelativePatcherAdjustment() {
-  DCHECK(dex_files_ != nullptr);
-  DCHECK(relative_patcher_ != nullptr);
-  DCHECK_NE(oat_data_offset_, 0u);
-  if (image_writer_ != nullptr && !dex_files_->empty()) {
-    // The oat data begin may not be initialized yet but the oat file offset is ready.
-    size_t oat_index = image_writer_->GetOatIndexForDexFile(dex_files_->front());
-    size_t elf_file_offset = image_writer_->GetOatFileOffset(oat_index);
-    relative_patcher_->StartOatFile(elf_file_offset + oat_data_offset_);
-  }
-}
-
-OatWriter::OatDexFile::OatDexFile(const char* dex_file_location,
-                                  DexFileSource source,
-                                  CreateTypeLookupTable create_type_lookup_table)
-    : source_(source),
-      create_type_lookup_table_(create_type_lookup_table),
-      dex_file_size_(0),
-      offset_(0),
-      dex_file_location_size_(strlen(dex_file_location)),
-      dex_file_location_data_(dex_file_location),
-      dex_file_location_checksum_(0u),
-      dex_file_offset_(0u),
-      class_offsets_offset_(0u),
-      lookup_table_offset_(0u),
-      method_bss_mapping_offset_(0u),
-      dex_sections_layout_offset_(0u),
-      class_offsets_() {
-}
-
-size_t OatWriter::OatDexFile::SizeOf() const {
-  return sizeof(dex_file_location_size_)
-          + dex_file_location_size_
-          + sizeof(dex_file_location_checksum_)
-          + sizeof(dex_file_offset_)
-          + sizeof(class_offsets_offset_)
-          + sizeof(lookup_table_offset_)
-          + sizeof(method_bss_mapping_offset_)
-          + sizeof(dex_sections_layout_offset_);
-}
-
-bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream* out) const {
-  const size_t file_offset = oat_writer->oat_data_offset_;
-  DCHECK_OFFSET_();
-
-  if (!out->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) {
-    PLOG(ERROR) << "Failed to write dex file location length to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_dex_file_location_size_ += sizeof(dex_file_location_size_);
-
-  if (!out->WriteFully(dex_file_location_data_, dex_file_location_size_)) {
-    PLOG(ERROR) << "Failed to write dex file location data to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_dex_file_location_data_ += dex_file_location_size_;
-
-  if (!out->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) {
-    PLOG(ERROR) << "Failed to write dex file location checksum to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_dex_file_location_checksum_ += sizeof(dex_file_location_checksum_);
-
-  if (!out->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) {
-    PLOG(ERROR) << "Failed to write dex file offset to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_dex_file_offset_ += sizeof(dex_file_offset_);
-
-  if (!out->WriteFully(&class_offsets_offset_, sizeof(class_offsets_offset_))) {
-    PLOG(ERROR) << "Failed to write class offsets offset to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_dex_file_class_offsets_offset_ += sizeof(class_offsets_offset_);
-
-  if (!out->WriteFully(&lookup_table_offset_, sizeof(lookup_table_offset_))) {
-    PLOG(ERROR) << "Failed to write lookup table offset to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_dex_file_lookup_table_offset_ += sizeof(lookup_table_offset_);
-
-  if (!out->WriteFully(&dex_sections_layout_offset_, sizeof(dex_sections_layout_offset_))) {
-    PLOG(ERROR) << "Failed to write dex section layout info to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_dex_file_dex_layout_sections_offset_ += sizeof(dex_sections_layout_offset_);
-
-  if (!out->WriteFully(&method_bss_mapping_offset_, sizeof(method_bss_mapping_offset_))) {
-    PLOG(ERROR) << "Failed to write method bss mapping offset to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_dex_file_method_bss_mapping_offset_ += sizeof(method_bss_mapping_offset_);
-
-  return true;
-}
-
-bool OatWriter::OatDexFile::WriteClassOffsets(OatWriter* oat_writer, OutputStream* out) {
-  if (!out->WriteFully(class_offsets_.data(), GetClassOffsetsRawSize())) {
-    PLOG(ERROR) << "Failed to write oat class offsets for " << GetLocation()
-                << " to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_class_offsets_ += GetClassOffsetsRawSize();
-  return true;
-}
-
-OatWriter::OatClass::OatClass(const dchecked_vector<CompiledMethod*>& compiled_methods,
-                              uint32_t compiled_methods_with_code,
-                              uint16_t oat_class_type)
-    : compiled_methods_(compiled_methods) {
-  const uint32_t num_methods = compiled_methods.size();
-  CHECK_LE(compiled_methods_with_code, num_methods);
-
-  oat_method_offsets_offsets_from_oat_class_.resize(num_methods);
-
-  method_offsets_.resize(compiled_methods_with_code);
-  method_headers_.resize(compiled_methods_with_code);
-
-  uint32_t oat_method_offsets_offset_from_oat_class = OatClassHeader::SizeOf();
-  // We only create this instance if there are at least some compiled.
-  if (oat_class_type == kOatClassSomeCompiled) {
-    method_bitmap_.reset(new BitVector(num_methods, false, Allocator::GetMallocAllocator()));
-    method_bitmap_size_ = method_bitmap_->GetSizeOf();
-    oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_);
-    oat_method_offsets_offset_from_oat_class += method_bitmap_size_;
-  } else {
-    method_bitmap_ = nullptr;
-    method_bitmap_size_ = 0;
-  }
-
-  for (size_t i = 0; i < num_methods; i++) {
-    CompiledMethod* compiled_method = compiled_methods_[i];
-    if (HasCompiledCode(compiled_method)) {
-      oat_method_offsets_offsets_from_oat_class_[i] = oat_method_offsets_offset_from_oat_class;
-      oat_method_offsets_offset_from_oat_class += sizeof(OatMethodOffsets);
-      if (oat_class_type == kOatClassSomeCompiled) {
-        method_bitmap_->SetBit(i);
-      }
-    } else {
-      oat_method_offsets_offsets_from_oat_class_[i] = 0;
-    }
-  }
-}
-
-size_t OatWriter::OatClass::SizeOf() const {
-  return ((method_bitmap_size_ == 0) ? 0 : sizeof(method_bitmap_size_))
-          + method_bitmap_size_
-          + (sizeof(method_offsets_[0]) * method_offsets_.size());
-}
-
-bool OatWriter::OatClassHeader::Write(OatWriter* oat_writer,
-                                      OutputStream* out,
-                                      const size_t file_offset) const {
-  DCHECK_OFFSET_();
-  if (!out->WriteFully(&status_, sizeof(status_))) {
-    PLOG(ERROR) << "Failed to write class status to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_class_status_ += sizeof(status_);
-
-  if (!out->WriteFully(&type_, sizeof(type_))) {
-    PLOG(ERROR) << "Failed to write oat class type to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_class_type_ += sizeof(type_);
-  return true;
-}
-
-bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream* out) const {
-  if (method_bitmap_size_ != 0) {
-    if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) {
-      PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation();
-      return false;
-    }
-    oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_);
-
-    if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) {
-      PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation();
-      return false;
-    }
-    oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_;
-  }
-
-  if (!out->WriteFully(method_offsets_.data(), GetMethodOffsetsRawSize())) {
-    PLOG(ERROR) << "Failed to write method offsets to " << out->GetLocation();
-    return false;
-  }
-  oat_writer->size_oat_class_method_offsets_ += GetMethodOffsetsRawSize();
-  return true;
-}
-
-const uint8_t* OatWriter::LookupBootImageInternTableSlot(const DexFile& dex_file,
-                                                         dex::StringIndex string_idx)
-    NO_THREAD_SAFETY_ANALYSIS {  // Single-threaded OatWriter can avoid locking.
-  uint32_t utf16_length;
-  const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
-  DCHECK_EQ(utf16_length, CountModifiedUtf8Chars(utf8_data));
-  InternTable::Utf8String string(utf16_length,
-                                 utf8_data,
-                                 ComputeUtf16HashFromModifiedUtf8(utf8_data, utf16_length));
-  const InternTable* intern_table = Runtime::Current()->GetClassLinker()->intern_table_;
-  for (const InternTable::Table::UnorderedSet& table : intern_table->strong_interns_.tables_) {
-    auto it = table.Find(string);
-    if (it != table.end()) {
-      return reinterpret_cast<const uint8_t*>(std::addressof(*it));
-    }
-  }
-  LOG(FATAL) << "Did not find boot image string " << utf8_data;
-  UNREACHABLE();
-}
-
-const uint8_t* OatWriter::LookupBootImageClassTableSlot(const DexFile& dex_file,
-                                                        dex::TypeIndex type_idx)
-    NO_THREAD_SAFETY_ANALYSIS {  // Single-threaded OatWriter can avoid locking.
-  const char* descriptor = dex_file.StringByTypeIdx(type_idx);
-  ClassTable::DescriptorHashPair pair(descriptor, ComputeModifiedUtf8Hash(descriptor));
-  ClassTable* table = Runtime::Current()->GetClassLinker()->boot_class_table_.get();
-  for (const ClassTable::ClassSet& class_set : table->classes_) {
-    auto it = class_set.Find(pair);
-    if (it != class_set.end()) {
-      return reinterpret_cast<const uint8_t*>(std::addressof(*it));
-    }
-  }
-  LOG(FATAL) << "Did not find boot image class " << descriptor;
-  UNREACHABLE();
-}
-
-}  // namespace art
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
deleted file mode 100644
index ef0ce52..0000000
--- a/compiler/oat_writer.h
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright (C) 2011 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_COMPILER_OAT_WRITER_H_
-#define ART_COMPILER_OAT_WRITER_H_
-
-#include <stdint.h>
-#include <cstddef>
-#include <memory>
-
-#include "base/array_ref.h"
-#include "base/dchecked_vector.h"
-#include "linker/relative_patcher.h"  // For linker::RelativePatcherTargetProvider.
-#include "mem_map.h"
-#include "method_reference.h"
-#include "mirror/class.h"
-#include "oat.h"
-#include "os.h"
-#include "safe_map.h"
-#include "string_reference.h"
-#include "type_reference.h"
-
-namespace art {
-
-class BitVector;
-class CompiledMethod;
-class CompilerDriver;
-class ImageWriter;
-class ProfileCompilationInfo;
-class OutputStream;
-class TimingLogger;
-class TypeLookupTable;
-class VdexFile;
-class ZipEntry;
-
-namespace debug {
-struct MethodDebugInfo;
-}  // namespace debug
-
-namespace linker {
-class MultiOatRelativePatcher;
-}  // namespace linker
-
-namespace verifier {
-  class VerifierDeps;
-}  // namespace verifier
-
-// OatHeader         variable length with count of D OatDexFiles
-//
-// TypeLookupTable[0] one descriptor to class def index hash table for each OatDexFile.
-// TypeLookupTable[1]
-// ...
-// TypeLookupTable[D]
-//
-// ClassOffsets[0]   one table of OatClass offsets for each class def for each OatDexFile.
-// ClassOffsets[1]
-// ...
-// ClassOffsets[D]
-//
-// OatClass[0]       one variable sized OatClass for each of C DexFile::ClassDefs
-// OatClass[1]       contains OatClass entries with class status, offsets to code, etc.
-// ...
-// OatClass[C]
-//
-// MethodBssMapping  one variable sized MethodBssMapping for each dex file, optional.
-// MethodBssMapping
-// ...
-// MethodBssMapping
-//
-// VmapTable         one variable sized VmapTable blob (CodeInfo or QuickeningInfo).
-// VmapTable         VmapTables are deduplicated.
-// ...
-// VmapTable
-//
-// MethodInfo        one variable sized blob with MethodInfo.
-// MethodInfo        MethodInfos are deduplicated.
-// ...
-// MethodInfo
-//
-// OatDexFile[0]     one variable sized OatDexFile with offsets to Dex and OatClasses
-// OatDexFile[1]
-// ...
-// OatDexFile[D]
-//
-// padding           if necessary so that the following code will be page aligned
-//
-// OatMethodHeader   fixed size header for a CompiledMethod including the size of the MethodCode.
-// MethodCode        one variable sized blob with the code of a CompiledMethod.
-// OatMethodHeader   (OatMethodHeader, MethodCode) pairs are deduplicated.
-// MethodCode
-// ...
-// OatMethodHeader
-// MethodCode
-//
-class OatWriter {
- public:
-  enum class CreateTypeLookupTable {
-    kCreate,
-    kDontCreate,
-    kDefault = kCreate
-  };
-
-  OatWriter(bool compiling_boot_image, TimingLogger* timings, ProfileCompilationInfo* info);
-
-  // To produce a valid oat file, the user must first add sources with any combination of
-  //   - AddDexFileSource(),
-  //   - AddZippedDexFilesSource(),
-  //   - AddRawDexFileSource(),
-  //   - AddVdexDexFilesSource().
-  // Then the user must call in order
-  //   - WriteAndOpenDexFiles()
-  //   - Initialize()
-  //   - WriteVerifierDeps()
-  //   - WriteQuickeningInfo()
-  //   - WriteChecksumsAndVdexHeader()
-  //   - PrepareLayout(),
-  //   - WriteRodata(),
-  //   - WriteCode(),
-  //   - WriteHeader().
-
-  // Add dex file source(s) from a file, either a plain dex file or
-  // a zip file with one or more dex files.
-  bool AddDexFileSource(
-      const char* filename,
-      const char* location,
-      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
-  // Add dex file source(s) from a zip file specified by a file handle.
-  bool AddZippedDexFilesSource(
-      File&& zip_fd,
-      const char* location,
-      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
-  // Add dex file source from raw memory.
-  bool AddRawDexFileSource(
-      const ArrayRef<const uint8_t>& data,
-      const char* location,
-      uint32_t location_checksum,
-      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
-  // Add dex file source(s) from a vdex file.
-  bool AddVdexDexFilesSource(
-      const VdexFile& vdex_file,
-      const char* location,
-      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
-  dchecked_vector<std::string> GetSourceLocations() const;
-
-  // Write raw dex files to the vdex file, mmap the file and open the dex files from it.
-  // Supporting data structures are written into the .rodata section of the oat file.
-  // The `verify` setting dictates whether the dex file verifier should check the dex files.
-  // This is generally the case, and should only be false for tests.
-  // If `update_input_vdex` is true, then this method won't actually write the dex files,
-  // and the compiler will just re-use the existing vdex file.
-  bool WriteAndOpenDexFiles(File* vdex_file,
-                            OutputStream* oat_rodata,
-                            InstructionSet instruction_set,
-                            const InstructionSetFeatures* instruction_set_features,
-                            SafeMap<std::string, std::string>* key_value_store,
-                            bool verify,
-                            bool update_input_vdex,
-                            /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
-                            /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
-  bool WriteQuickeningInfo(OutputStream* vdex_out);
-  bool WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps);
-  bool WriteChecksumsAndVdexHeader(OutputStream* vdex_out);
-  // Initialize the writer with the given parameters.
-  void Initialize(const CompilerDriver* compiler,
-                  ImageWriter* image_writer,
-                  const std::vector<const DexFile*>& dex_files) {
-    compiler_driver_ = compiler;
-    image_writer_ = image_writer;
-    dex_files_ = &dex_files;
-  }
-
-  // Prepare layout of remaining data.
-  void PrepareLayout(linker::MultiOatRelativePatcher* relative_patcher);
-  // Write the rest of .rodata section (ClassOffsets[], OatClass[], maps).
-  bool WriteRodata(OutputStream* out);
-  // Write the code to the .text section.
-  bool WriteCode(OutputStream* out);
-  // Write the oat header. This finalizes the oat file.
-  bool WriteHeader(OutputStream* out,
-                   uint32_t image_file_location_oat_checksum,
-                   uintptr_t image_file_location_oat_begin,
-                   int32_t image_patch_delta);
-
-  // Returns whether the oat file has an associated image.
-  bool HasImage() const {
-    // Since the image is being created at the same time as the oat file,
-    // check if there's an image writer.
-    return image_writer_ != nullptr;
-  }
-
-  bool HasBootImage() const {
-    return compiling_boot_image_;
-  }
-
-  const OatHeader& GetOatHeader() const {
-    return *oat_header_;
-  }
-
-  size_t GetOatSize() const {
-    return oat_size_;
-  }
-
-  size_t GetBssSize() const {
-    return bss_size_;
-  }
-
-  size_t GetBssMethodsOffset() const {
-    return bss_methods_offset_;
-  }
-
-  size_t GetBssRootsOffset() const {
-    return bss_roots_offset_;
-  }
-
-  size_t GetOatDataOffset() const {
-    return oat_data_offset_;
-  }
-
-  ~OatWriter();
-
-  ArrayRef<const debug::MethodDebugInfo> GetMethodDebugInfo() const {
-    return ArrayRef<const debug::MethodDebugInfo>(method_info_);
-  }
-
-  const CompilerDriver* GetCompilerDriver() const {
-    return compiler_driver_;
-  }
-
- private:
-  class DexFileSource;
-  class OatClassHeader;
-  class OatClass;
-  class OatDexFile;
-
-  // The function VisitDexMethods() below iterates through all the methods in all
-  // the compiled dex files in order of their definitions. The method visitor
-  // classes provide individual bits of processing for each of the passes we need to
-  // first collect the data we want to write to the oat file and then, in later passes,
-  // to actually write it.
-  class DexMethodVisitor;
-  class OatDexMethodVisitor;
-  class InitBssLayoutMethodVisitor;
-  class InitOatClassesMethodVisitor;
-  class InitCodeMethodVisitor;
-  class InitMapMethodVisitor;
-  class InitMethodInfoVisitor;
-  class InitImageMethodVisitor;
-  class WriteCodeMethodVisitor;
-  class WriteMapMethodVisitor;
-  class WriteMethodInfoVisitor;
-  class WriteQuickeningInfoMethodVisitor;
-  class WriteQuickeningIndicesMethodVisitor;
-
-  // Visit all the methods in all the compiled dex files in their definition order
-  // with a given DexMethodVisitor.
-  bool VisitDexMethods(DexMethodVisitor* visitor);
-
-  // If `update_input_vdex` is true, then this method won't actually write the dex files,
-  // and the compiler will just re-use the existing vdex file.
-  bool WriteDexFiles(OutputStream* out, File* file, bool update_input_vdex);
-  bool WriteDexFile(OutputStream* out,
-                    File* file,
-                    OatDexFile* oat_dex_file,
-                    bool update_input_vdex);
-  bool SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file);
-  bool LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_file);
-  bool WriteDexFile(OutputStream* out,
-                    File* file,
-                    OatDexFile* oat_dex_file,
-                    ZipEntry* dex_file);
-  bool WriteDexFile(OutputStream* out,
-                    File* file,
-                    OatDexFile* oat_dex_file,
-                    File* dex_file);
-  bool WriteDexFile(OutputStream* out,
-                    OatDexFile* oat_dex_file,
-                    const uint8_t* dex_file,
-                    bool update_input_vdex);
-  bool OpenDexFiles(File* file,
-                    bool verify,
-                    /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
-                    /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
-
-  size_t InitOatHeader(InstructionSet instruction_set,
-                       const InstructionSetFeatures* instruction_set_features,
-                       uint32_t num_dex_files,
-                       SafeMap<std::string, std::string>* key_value_store);
-  size_t InitClassOffsets(size_t offset);
-  size_t InitOatClasses(size_t offset);
-  size_t InitOatMaps(size_t offset);
-  size_t InitMethodBssMappings(size_t offset);
-  size_t InitOatDexFiles(size_t offset);
-  size_t InitOatCode(size_t offset);
-  size_t InitOatCodeDexFiles(size_t offset);
-  void InitBssLayout(InstructionSet instruction_set);
-
-  size_t WriteClassOffsets(OutputStream* out, size_t file_offset, size_t relative_offset);
-  size_t WriteClasses(OutputStream* out, size_t file_offset, size_t relative_offset);
-  size_t WriteMaps(OutputStream* out, size_t file_offset, size_t relative_offset);
-  size_t WriteMethodBssMappings(OutputStream* out, size_t file_offset, size_t relative_offset);
-  size_t WriteOatDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset);
-  size_t WriteCode(OutputStream* out, size_t file_offset, size_t relative_offset);
-  size_t WriteCodeDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset);
-
-  bool RecordOatDataOffset(OutputStream* out);
-  bool ReadDexFileHeader(File* oat_file, OatDexFile* oat_dex_file);
-  bool ValidateDexFileHeader(const uint8_t* raw_header, const char* location);
-  bool WriteTypeLookupTables(OutputStream* oat_rodata,
-                             const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files);
-  bool WriteDexLayoutSections(OutputStream* oat_rodata,
-                              const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files);
-  bool WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta);
-  bool WriteUpTo16BytesAlignment(OutputStream* out, uint32_t size, uint32_t* stat);
-  void SetMultiOatRelativePatcherAdjustment();
-  void CloseSources();
-
-  bool MayHaveCompiledMethods() const;
-
-  // Find the address of the GcRoot<String> in the InternTable for a boot image string.
-  const uint8_t* LookupBootImageInternTableSlot(const DexFile& dex_file,
-                                                dex::StringIndex string_idx);
-  // Find the address of the ClassTable::TableSlot for a boot image class.
-  const uint8_t* LookupBootImageClassTableSlot(const DexFile& dex_file, dex::TypeIndex type_idx);
-
-  enum class WriteState {
-    kAddingDexFileSources,
-    kPrepareLayout,
-    kWriteRoData,
-    kWriteText,
-    kWriteHeader,
-    kDone
-  };
-
-  WriteState write_state_;
-  TimingLogger* timings_;
-
-  std::vector<std::unique_ptr<File>> raw_dex_files_;
-  std::vector<std::unique_ptr<ZipArchive>> zip_archives_;
-  std::vector<std::unique_ptr<ZipEntry>> zipped_dex_files_;
-
-  // Using std::list<> which doesn't move elements around on push/emplace_back().
-  // We need this because we keep plain pointers to the strings' c_str().
-  std::list<std::string> zipped_dex_file_locations_;
-
-  dchecked_vector<debug::MethodDebugInfo> method_info_;
-
-  const CompilerDriver* compiler_driver_;
-  ImageWriter* image_writer_;
-  const bool compiling_boot_image_;
-
-  // note OatFile does not take ownership of the DexFiles
-  const std::vector<const DexFile*>* dex_files_;
-
-  // Size required for Vdex data structures.
-  size_t vdex_size_;
-
-  // Offset of section holding Dex files inside Vdex.
-  size_t vdex_dex_files_offset_;
-
-  // Offset of section holding VerifierDeps inside Vdex.
-  size_t vdex_verifier_deps_offset_;
-
-  // Offset of section holding quickening info inside Vdex.
-  size_t vdex_quickening_info_offset_;
-
-  // Size required for Oat data structures.
-  size_t oat_size_;
-
-  // The start of the required .bss section.
-  size_t bss_start_;
-
-  // The size of the required .bss section holding the DexCache data and GC roots.
-  size_t bss_size_;
-
-  // The offset of the methods in .bss section.
-  size_t bss_methods_offset_;
-
-  // The offset of the GC roots in .bss section.
-  size_t bss_roots_offset_;
-
-  // Map for recording references to ArtMethod entries in .bss.
-  SafeMap<const DexFile*, BitVector> bss_method_entry_references_;
-
-  // Map for allocating ArtMethod entries in .bss. Indexed by MethodReference for the target
-  // method in the dex file with the "method reference value comparator" for deduplication.
-  // The value is the target offset for patching, starting at `bss_start_ + bss_methods_offset_`.
-  SafeMap<MethodReference, size_t, MethodReferenceValueComparator> bss_method_entries_;
-
-  // Map for allocating Class entries in .bss. Indexed by TypeReference for the source
-  // type in the dex file with the "type value comparator" for deduplication. The value
-  // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
-  SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_type_entries_;
-
-  // Map for allocating String entries in .bss. Indexed by StringReference for the source
-  // string in the dex file with the "string value comparator" for deduplication. The value
-  // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
-  SafeMap<StringReference, size_t, StringReferenceValueComparator> bss_string_entries_;
-
-  // Whether boot image tables should be mapped to the .bss. This is needed for compiled
-  // code that reads from these tables with PC-relative instructions.
-  bool map_boot_image_tables_to_bss_;
-
-  // Offset of the oat data from the start of the mmapped region of the elf file.
-  size_t oat_data_offset_;
-
-  // Fake OatDexFiles to hold type lookup tables for the compiler.
-  std::vector<std::unique_ptr<art::OatDexFile>> type_lookup_table_oat_dex_files_;
-
-  // data to write
-  std::unique_ptr<OatHeader> oat_header_;
-  dchecked_vector<OatDexFile> oat_dex_files_;
-  dchecked_vector<OatClassHeader> oat_class_headers_;
-  dchecked_vector<OatClass> oat_classes_;
-  std::unique_ptr<const std::vector<uint8_t>> jni_dlsym_lookup_;
-  std::unique_ptr<const std::vector<uint8_t>> quick_generic_jni_trampoline_;
-  std::unique_ptr<const std::vector<uint8_t>> quick_imt_conflict_trampoline_;
-  std::unique_ptr<const std::vector<uint8_t>> quick_resolution_trampoline_;
-  std::unique_ptr<const std::vector<uint8_t>> quick_to_interpreter_bridge_;
-
-  // output stats
-  uint32_t size_vdex_header_;
-  uint32_t size_vdex_checksums_;
-  uint32_t size_dex_file_alignment_;
-  uint32_t size_executable_offset_alignment_;
-  uint32_t size_oat_header_;
-  uint32_t size_oat_header_key_value_store_;
-  uint32_t size_dex_file_;
-  uint32_t size_verifier_deps_;
-  uint32_t size_verifier_deps_alignment_;
-  uint32_t size_quickening_info_;
-  uint32_t size_quickening_info_alignment_;
-  uint32_t size_interpreter_to_interpreter_bridge_;
-  uint32_t size_interpreter_to_compiled_code_bridge_;
-  uint32_t size_jni_dlsym_lookup_;
-  uint32_t size_quick_generic_jni_trampoline_;
-  uint32_t size_quick_imt_conflict_trampoline_;
-  uint32_t size_quick_resolution_trampoline_;
-  uint32_t size_quick_to_interpreter_bridge_;
-  uint32_t size_trampoline_alignment_;
-  uint32_t size_method_header_;
-  uint32_t size_code_;
-  uint32_t size_code_alignment_;
-  uint32_t size_relative_call_thunks_;
-  uint32_t size_misc_thunks_;
-  uint32_t size_vmap_table_;
-  uint32_t size_method_info_;
-  uint32_t size_oat_dex_file_location_size_;
-  uint32_t size_oat_dex_file_location_data_;
-  uint32_t size_oat_dex_file_location_checksum_;
-  uint32_t size_oat_dex_file_offset_;
-  uint32_t size_oat_dex_file_class_offsets_offset_;
-  uint32_t size_oat_dex_file_lookup_table_offset_;
-  uint32_t size_oat_dex_file_dex_layout_sections_offset_;
-  uint32_t size_oat_dex_file_dex_layout_sections_;
-  uint32_t size_oat_dex_file_dex_layout_sections_alignment_;
-  uint32_t size_oat_dex_file_method_bss_mapping_offset_;
-  uint32_t size_oat_lookup_table_alignment_;
-  uint32_t size_oat_lookup_table_;
-  uint32_t size_oat_class_offsets_alignment_;
-  uint32_t size_oat_class_offsets_;
-  uint32_t size_oat_class_type_;
-  uint32_t size_oat_class_status_;
-  uint32_t size_oat_class_method_bitmaps_;
-  uint32_t size_oat_class_method_offsets_;
-  uint32_t size_method_bss_mappings_;
-
-  // The helper for processing relative patches is external so that we can patch across oat files.
-  linker::MultiOatRelativePatcher* relative_patcher_;
-
-  // The locations of absolute patches relative to the start of the executable section.
-  dchecked_vector<uintptr_t> absolute_patch_locations_;
-
-  // Profile info used to generate new layout of files.
-  ProfileCompilationInfo* profile_compilation_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(OatWriter);
-};
-
-}  // namespace art
-
-#endif  // ART_COMPILER_OAT_WRITER_H_
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index e128a15..8dd2762 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -63,7 +63,6 @@
 #include "driver/compiler_driver-inl.h"
 #include "driver/compiler_options.h"
 #include "driver/dex_compilation_unit.h"
-#include "elf_writer_quick.h"
 #include "graph_checker.h"
 #include "graph_visualizer.h"
 #include "gvn.h"