Add stack map fast path for GC.

Test: test-art-host-gtest-stack_map_test
Change-Id: Ia04a07b560fcce2fb955d66d1924ee224dec420d
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index 8858cbe..3918b65 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -301,10 +301,10 @@
   EncodeVarintBits(out, fp_spill_mask_);
   EncodeVarintBits(out, num_dex_registers_);
   EncodeTable(out, stack_maps_);
-  EncodeTable(out, inline_infos_);
-  EncodeTable(out, method_infos_);
   EncodeTable(out, register_masks_);
   EncodeTable(out, stack_masks_);
+  EncodeTable(out, inline_infos_);
+  EncodeTable(out, method_infos_);
   EncodeTable(out, dex_register_masks_);
   EncodeTable(out, dex_register_maps_);
   EncodeTable(out, dex_register_catalog_);
diff --git a/runtime/oat.h b/runtime/oat.h
index 0a34ea0..037c8f9 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@
 class PACKED(4) OatHeader {
  public:
   static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
-  // Last oat version changed reason: Pass Class reference to clinit entrypoint.
-  static constexpr uint8_t kOatVersion[] = { '1', '6', '0', '\0' };
+  // Last oat version changed reason: Add stack map fast path for GC.
+  static constexpr uint8_t kOatVersion[] = { '1', '6', '1', '\0' };
 
   static constexpr const char* kImageLocationKey = "image-location";
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 1b78b5a..d1000c5 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -56,13 +56,16 @@
   fp_spill_mask_ = DecodeVarintBits(reader);
   number_of_dex_registers_ = DecodeVarintBits(reader);
   DecodeTable(stack_maps_, reader, data);
+  DecodeTable(register_masks_, reader, data);
+  DecodeTable(stack_masks_, reader, data);
+  if (flags & DecodeFlags::GcMasksOnly) {
+    return;
+  }
   DecodeTable(inline_infos_, reader, data);
   DecodeTable(method_infos_, reader, data);
   if (flags & DecodeFlags::InlineInfoOnly) {
     return;
   }
-  DecodeTable(register_masks_, reader, data);
-  DecodeTable(stack_masks_, reader, data);
   DecodeTable(dex_register_masks_, reader, data);
   DecodeTable(dex_register_maps_, reader, data);
   DecodeTable(dex_register_catalog_, reader, data);
@@ -97,10 +100,10 @@
   EncodeVarintBits(writer, DecodeVarintBits(reader));  // fp_spill_mask_.
   EncodeVarintBits(writer, DecodeVarintBits(reader));  // number_of_dex_registers_.
   DedupeTable<StackMap>(writer, reader, dedupe_map);
-  DedupeTable<InlineInfo>(writer, reader, dedupe_map);
-  DedupeTable<MethodInfo>(writer, reader, dedupe_map);
   DedupeTable<RegisterMask>(writer, reader, dedupe_map);
   DedupeTable<MaskInfo>(writer, reader, dedupe_map);
+  DedupeTable<InlineInfo>(writer, reader, dedupe_map);
+  DedupeTable<MethodInfo>(writer, reader, dedupe_map);
   DedupeTable<MaskInfo>(writer, reader, dedupe_map);
   DedupeTable<DexRegisterMapInfo>(writer, reader, dedupe_map);
   DedupeTable<DexRegisterInfo>(writer, reader, dedupe_map);
@@ -211,10 +214,10 @@
   Stats* stats = parent->Child("CodeInfo");
   stats->AddBytes(Size());
   AddTableSizeStats<StackMap>("StackMaps", stack_maps_, stats);
-  AddTableSizeStats<InlineInfo>("InlineInfos", inline_infos_, stats);
-  AddTableSizeStats<MethodInfo>("MethodInfo", method_infos_, stats);
   AddTableSizeStats<RegisterMask>("RegisterMasks", register_masks_, stats);
   AddTableSizeStats<MaskInfo>("StackMasks", stack_masks_, stats);
+  AddTableSizeStats<InlineInfo>("InlineInfos", inline_infos_, stats);
+  AddTableSizeStats<MethodInfo>("MethodInfo", method_infos_, stats);
   AddTableSizeStats<MaskInfo>("DexRegisterMasks", dex_register_masks_, stats);
   AddTableSizeStats<DexRegisterMapInfo>("DexRegisterMaps", dex_register_maps_, stats);
   AddTableSizeStats<DexRegisterInfo>("DexRegisterCatalog", dex_register_catalog_, stats);
@@ -276,10 +279,10 @@
   vios->Stream() << "CodeInfo\n";
   ScopedIndentation indent1(vios);
   DumpTable<StackMap>(vios, "StackMaps", stack_maps_, verbose);
-  DumpTable<InlineInfo>(vios, "InlineInfos", inline_infos_, verbose);
-  DumpTable<MethodInfo>(vios, "MethodInfo", method_infos_, verbose);
   DumpTable<RegisterMask>(vios, "RegisterMasks", register_masks_, verbose);
   DumpTable<MaskInfo>(vios, "StackMasks", stack_masks_, verbose, true /* is_mask */);
+  DumpTable<InlineInfo>(vios, "InlineInfos", inline_infos_, verbose);
+  DumpTable<MethodInfo>(vios, "MethodInfo", method_infos_, verbose);
   DumpTable<MaskInfo>(vios, "DexRegisterMasks", dex_register_masks_, verbose, true /* is_mask */);
   DumpTable<DexRegisterMapInfo>(vios, "DexRegisterMaps", dex_register_maps_, verbose);
   DumpTable<DexRegisterInfo>(vios, "DexRegisterCatalog", dex_register_catalog_, verbose);
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index acde3e3..d6db05a 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -271,9 +271,11 @@
  public:
   enum DecodeFlags {
     Default = 0,
+    // Limits the decoding only to the data needed by GC.
+    GcMasksOnly = 1,
     // Limits the decoding only to the main stack map table and inline info table.
     // This is sufficient for many use cases and makes the header decoding faster.
-    InlineInfoOnly = 1,
+    InlineInfoOnly = 2,
   };
 
   explicit CodeInfo(const uint8_t* data, DecodeFlags flags = DecodeFlags::Default) {
@@ -446,10 +448,10 @@
   uint32_t fp_spill_mask_;
   uint32_t number_of_dex_registers_;
   BitTable<StackMap> stack_maps_;
-  BitTable<InlineInfo> inline_infos_;
-  BitTable<MethodInfo> method_infos_;
   BitTable<RegisterMask> register_masks_;
   BitTable<MaskInfo> stack_masks_;
+  BitTable<InlineInfo> inline_infos_;
+  BitTable<MethodInfo> method_infos_;
   BitTable<MaskInfo> dex_register_masks_;
   BitTable<DexRegisterMapInfo> dex_register_maps_;
   BitTable<DexRegisterInfo> dex_register_catalog_;
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 69ac01e..0703a07 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3604,7 +3604,9 @@
       StackReference<mirror::Object>* vreg_base = reinterpret_cast<StackReference<mirror::Object>*>(
           reinterpret_cast<uintptr_t>(cur_quick_frame));
       uintptr_t native_pc_offset = method_header->NativeQuickPcOffset(GetCurrentQuickFramePc());
-      CodeInfo code_info(method_header);
+      CodeInfo code_info(method_header, kPrecise
+          ? CodeInfo::DecodeFlags::Default  // We will need dex register maps.
+          : CodeInfo::DecodeFlags::GcMasksOnly);
       StackMap map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
       DCHECK(map.IsValid());
 
@@ -3621,7 +3623,7 @@
             vreg_info.VisitStack(&new_ref, i, this);
             if (ref != new_ref) {
               ref_addr->Assign(new_ref);
-           }
+            }
           }
         }
       }