ART: Swap-space in the compiler

Introduce a swap-space and corresponding allocator to transparently
switch native allocations to memory backed by a file.

Bug: 18596910

(cherry picked from commit 62746d8d9c4400e4764f162b22bfb1a32be287a9)

Change-Id: I131448f3907115054a592af73db86d2b9257ea33
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 7d14de1..3c36ffa 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -504,7 +504,7 @@
 }
 
 struct OatWriter::GcMapDataAccess {
-  static const std::vector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
+  static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
     return compiled_method->GetGcMap();
   }
 
@@ -526,7 +526,7 @@
 };
 
 struct OatWriter::MappingTableDataAccess {
-  static const std::vector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
+  static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
     return compiled_method->GetMappingTable();
   }
 
@@ -548,7 +548,7 @@
 };
 
 struct OatWriter::VmapTableDataAccess {
-  static const std::vector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
+  static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
     return &compiled_method->GetVmapTable();
   }
 
@@ -719,7 +719,7 @@
       // Derived from CompiledMethod.
       uint32_t quick_code_offset = 0;
 
-      const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode();
+      const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode();
       CHECK(quick_code != nullptr);
       offset_ = writer_->relative_call_patcher_->ReserveSpace(offset_, compiled_method);
       offset_ = compiled_method->AlignCode(offset_);
@@ -829,7 +829,7 @@
         } else {
           status = mirror::Class::kStatusNotReady;
         }
-        std::vector<uint8_t> const * gc_map = compiled_method->GetGcMap();
+        const SwapVector<uint8_t>* gc_map = compiled_method->GetGcMap();
         if (gc_map != nullptr) {
           size_t gc_map_size = gc_map->size() * sizeof(gc_map[0]);
           bool is_native = it.MemberIsNative();
@@ -871,7 +871,7 @@
       DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
       DCHECK_EQ(DataAccess::GetOffset(oat_class, method_offsets_index_), 0u);
 
-      const std::vector<uint8_t>* map = DataAccess::GetData(compiled_method);
+      const SwapVector<uint8_t>* map = DataAccess::GetData(compiled_method);
       uint32_t map_size = map == nullptr ? 0 : map->size() * sizeof((*map)[0]);
       if (map_size != 0u) {
         auto lb = dedupe_map_.lower_bound(map);
@@ -893,7 +893,7 @@
  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 std::vector<uint8_t>*, uint32_t> dedupe_map_;
+  SafeMap<const SwapVector<uint8_t>*, uint32_t> dedupe_map_;
 };
 
 class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
@@ -990,8 +990,11 @@
       size_t file_offset = file_offset_;
       OutputStream* out = out_;
 
-      const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode();
+      const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode();
       if (quick_code != nullptr) {
+        // Need a wrapper if we create a copy for patching.
+        ArrayRef<const uint8_t> wrapped(*quick_code);
+
         offset_ = writer_->relative_call_patcher_->WriteThunks(out, offset_);
         if (offset_ == 0u) {
           ReportWriteFailure("relative call thunk", it);
@@ -1030,8 +1033,8 @@
           DCHECK_OFFSET_();
 
           if (!compiled_method->GetPatches().empty()) {
-            patched_code_ =  *quick_code;
-            quick_code = &patched_code_;
+            patched_code_ = std::vector<uint8_t>(quick_code->begin(), quick_code->end());
+            wrapped = ArrayRef<const uint8_t>(patched_code_);
             for (const LinkerPatch& patch : compiled_method->GetPatches()) {
               if (patch.Type() == kLinkerPatchCallRelative) {
                 // NOTE: Relative calls across oat files are not supported.
@@ -1052,8 +1055,8 @@
             }
           }
 
-          writer_->oat_header_->UpdateChecksum(&(*quick_code)[0], code_size);
-          if (!out->WriteFully(&(*quick_code)[0], code_size)) {
+          writer_->oat_header_->UpdateChecksum(wrapped.data(), code_size);
+          if (!out->WriteFully(wrapped.data(), code_size)) {
             ReportWriteFailure("method code", it);
             return false;
           }
@@ -1170,7 +1173,7 @@
       ++method_offsets_index_;
 
       // Write deduplicated map.
-      const std::vector<uint8_t>* map = DataAccess::GetData(compiled_method);
+      const SwapVector<uint8_t>* map = DataAccess::GetData(compiled_method);
       size_t map_size = map == nullptr ? 0 : map->size() * sizeof((*map)[0]);
       DCHECK((map_size == 0u && map_offset == 0u) ||
             (map_size != 0u && map_offset != 0u && map_offset <= offset_))