Add GC map to oat file

Change-Id: Ied0462c711a09e2542f231c3b2fa31239958bd28
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index 67bdd9a..40230b4 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -5,16 +5,17 @@
 namespace art {
 
 CompiledMethod::CompiledMethod(InstructionSet instruction_set,
-                               std::vector<short>& short_code,
+                               const std::vector<uint16_t>& short_code,
                                const size_t frame_size_in_bytes,
                                const uint32_t core_spill_mask,
                                const uint32_t fp_spill_mask,
-                               std::vector<uint32_t>& mapping_table,
-                               std::vector<uint16_t>& vmap_table)
+                               const std::vector<uint32_t>& mapping_table,
+                               const std::vector<uint16_t>& vmap_table)
     : instruction_set_(instruction_set), frame_size_in_bytes_(frame_size_in_bytes),
       core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask) {
   CHECK_NE(short_code.size(), 0U);
   CHECK_GE(vmap_table.size(), 1U);  // should always contain an entry for LR
+  CHECK_LE(vmap_table.size(), (1U << 16) - 1); // length must fit in 2^16-1
 
   size_t code_byte_count = short_code.size() * sizeof(short_code[0]);
   std::vector<uint8_t> byte_code(code_byte_count);
@@ -42,8 +43,33 @@
   DCHECK_EQ(vmap_table_[0], static_cast<uint32_t>(__builtin_popcount(core_spill_mask) + __builtin_popcount(fp_spill_mask)));
 }
 
+void CompiledMethod::SetGcMap(const std::vector<uint8_t>& gc_map) {
+  CHECK_NE(gc_map.size(), 0U);
+
+  // Should only be used with CompiledMethods created with oatCompileMethod
+  CHECK_NE(mapping_table_.size(), 0U);
+  CHECK_NE(vmap_table_.size(), 0U);
+
+  std::vector<uint8_t> length_prefixed_gc_map;
+  length_prefixed_gc_map.push_back((gc_map.size() & 0xff000000) >> 24);
+  length_prefixed_gc_map.push_back((gc_map.size() & 0x00ff0000) >> 16);
+  length_prefixed_gc_map.push_back((gc_map.size() & 0x0000ff00) >> 8);
+  length_prefixed_gc_map.push_back((gc_map.size() & 0x000000ff) >> 0);
+  length_prefixed_gc_map.insert(length_prefixed_gc_map.end(),
+                                gc_map.begin(),
+                                gc_map.end());
+  DCHECK_EQ(gc_map.size() + 4, length_prefixed_gc_map.size());
+  DCHECK_EQ(gc_map.size(),
+            static_cast<size_t>((length_prefixed_gc_map[0] << 24) |
+                                (length_prefixed_gc_map[1] << 16) |
+                                (length_prefixed_gc_map[2] << 8) |
+                                (length_prefixed_gc_map[3] << 0)));
+
+  gc_map_ = length_prefixed_gc_map;
+}
+
 CompiledMethod::CompiledMethod(InstructionSet instruction_set,
-                               std::vector<uint8_t>& code,
+                               const std::vector<uint8_t>& code,
                                const size_t frame_size_in_bytes,
                                const uint32_t core_spill_mask,
                                const uint32_t fp_spill_mask)
@@ -82,6 +108,10 @@
   return vmap_table_;
 }
 
+const std::vector<uint8_t>& CompiledMethod::GetGcMap() const {
+  return gc_map_;
+}
+
 uint32_t CompiledMethod::AlignCode(uint32_t offset) const {
   return AlignCode(offset, instruction_set_);
 }