Add Kind column to stack maps.

Add 'Kind' column to stack maps which marks special stack map types,
and use it at run-time to add extra sanity checks.

It will also allow us to binary search the stack maps.

The column increases .oat file by 0.2%.

Test: test-art-host-gtest-stack_map_test
Change-Id: I2a9143afa0e32bb06174604ca81a64c41fed232f
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index b3feb78..45a81cf 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -1055,7 +1055,8 @@
 
 void CodeGenerator::RecordPcInfo(HInstruction* instruction,
                                  uint32_t dex_pc,
-                                 SlowPathCode* slow_path) {
+                                 SlowPathCode* slow_path,
+                                 bool native_debug_info) {
   if (instruction != nullptr) {
     // The code generated for some type conversions
     // may call the runtime, thus normally requiring a subsequent
@@ -1120,12 +1121,23 @@
     outer_dex_pc = outer_environment->GetDexPc();
     outer_environment_size = outer_environment->Size();
   }
+
+  HLoopInformation* info = instruction->GetBlock()->GetLoopInformation();
+  bool osr =
+      instruction->IsSuspendCheck() &&
+      (info != nullptr) &&
+      graph_->IsCompilingOsr() &&
+      (inlining_depth == 0);
+  StackMap::Kind kind = native_debug_info
+      ? StackMap::Kind::Debug
+      : (osr ? StackMap::Kind::OSR : StackMap::Kind::Default);
   stack_map_stream->BeginStackMapEntry(outer_dex_pc,
                                        native_pc,
                                        register_mask,
                                        locations->GetStackMask(),
                                        outer_environment_size,
-                                       inlining_depth);
+                                       inlining_depth,
+                                       kind);
   EmitEnvironment(environment, slow_path);
   // Record invoke info, the common case for the trampoline is super and static invokes. Only
   // record these to reduce oat file size.
@@ -1138,19 +1150,9 @@
   }
   stack_map_stream->EndStackMapEntry();
 
-  HLoopInformation* info = instruction->GetBlock()->GetLoopInformation();
-  if (instruction->IsSuspendCheck() &&
-      (info != nullptr) &&
-      graph_->IsCompilingOsr() &&
-      (inlining_depth == 0)) {
+  if (osr) {
     DCHECK_EQ(info->GetSuspendCheck(), instruction);
-    // We duplicate the stack map as a marker that this stack map can be an OSR entry.
-    // Duplicating it avoids having the runtime recognize and skip an OSR stack map.
     DCHECK(info->IsIrreducible());
-    stack_map_stream->BeginStackMapEntry(
-        dex_pc, native_pc, register_mask, locations->GetStackMask(), outer_environment_size, 0);
-    EmitEnvironment(instruction->GetEnvironment(), slow_path);
-    stack_map_stream->EndStackMapEntry();
     if (kIsDebugBuild) {
       for (size_t i = 0, environment_size = environment->Size(); i < environment_size; ++i) {
         HInstruction* in_environment = environment->GetInstructionAt(i);
@@ -1167,14 +1169,6 @@
         }
       }
     }
-  } else if (kIsDebugBuild) {
-    // Ensure stack maps are unique, by checking that the native pc in the stack map
-    // last emitted is different than the native pc of the stack map just emitted.
-    size_t number_of_stack_maps = stack_map_stream->GetNumberOfStackMaps();
-    if (number_of_stack_maps > 1) {
-      DCHECK_NE(stack_map_stream->GetStackMapNativePcOffset(number_of_stack_maps - 1),
-                stack_map_stream->GetStackMapNativePcOffset(number_of_stack_maps - 2));
-    }
   }
 }
 
@@ -1196,12 +1190,11 @@
       // Ensure that we do not collide with the stack map of the previous instruction.
       GenerateNop();
     }
-    RecordPcInfo(instruction, dex_pc, slow_path);
+    RecordPcInfo(instruction, dex_pc, slow_path, /* native_debug_info */ true);
   }
 }
 
 void CodeGenerator::RecordCatchBlockInfo() {
-  ArenaAllocator* allocator = graph_->GetAllocator();
   StackMapStream* stack_map_stream = GetStackMapStream();
 
   for (HBasicBlock* block : *block_order_) {
@@ -1213,28 +1206,24 @@
     uint32_t num_vregs = graph_->GetNumberOfVRegs();
     uint32_t inlining_depth = 0;  // Inlining of catch blocks is not supported at the moment.
     uint32_t native_pc = GetAddressOf(block);
-    uint32_t register_mask = 0;   // Not used.
-
-    // The stack mask is not used, so we leave it empty.
-    ArenaBitVector* stack_mask =
-        ArenaBitVector::Create(allocator, 0, /* expandable */ true, kArenaAllocCodeGenerator);
 
     stack_map_stream->BeginStackMapEntry(dex_pc,
                                          native_pc,
-                                         register_mask,
-                                         stack_mask,
+                                         /* register_mask */ 0,
+                                         /* stack_mask */ nullptr,
                                          num_vregs,
-                                         inlining_depth);
+                                         inlining_depth,
+                                         StackMap::Kind::Catch);
 
     HInstruction* current_phi = block->GetFirstPhi();
     for (size_t vreg = 0; vreg < num_vregs; ++vreg) {
-    while (current_phi != nullptr && current_phi->AsPhi()->GetRegNumber() < vreg) {
-      HInstruction* next_phi = current_phi->GetNext();
-      DCHECK(next_phi == nullptr ||
-             current_phi->AsPhi()->GetRegNumber() <= next_phi->AsPhi()->GetRegNumber())
-          << "Phis need to be sorted by vreg number to keep this a linear-time loop.";
-      current_phi = next_phi;
-    }
+      while (current_phi != nullptr && current_phi->AsPhi()->GetRegNumber() < vreg) {
+        HInstruction* next_phi = current_phi->GetNext();
+        DCHECK(next_phi == nullptr ||
+               current_phi->AsPhi()->GetRegNumber() <= next_phi->AsPhi()->GetRegNumber())
+            << "Phis need to be sorted by vreg number to keep this a linear-time loop.";
+        current_phi = next_phi;
+      }
 
       if (current_phi == nullptr || current_phi->AsPhi()->GetRegNumber() != vreg) {
         stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kNone, 0);