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"
