Runtime support for the new stack maps for the opt compiler.

Now most of the methods supported by the compiler can be optimized,
instead of using the baseline.

Change-Id: I80ab36a34913fa4e7dd576c7bf55af63594dc1fa
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 7269fff..7731e6e 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -41,10 +41,11 @@
   if (!is_leaf) {
     MarkNotLeaf();
   }
-  ComputeFrameSize(GetGraph()->GetMaximumNumberOfOutVRegs()
-                   + GetGraph()->GetNumberOfLocalVRegs()
-                   + GetGraph()->GetNumberOfTemporaries()
-                   + 1 /* filler */);
+  ComputeFrameSize(GetGraph()->GetNumberOfLocalVRegs()
+                     + GetGraph()->GetNumberOfTemporaries()
+                     + 1 /* filler */,
+                   GetGraph()->GetMaximumNumberOfOutVRegs()
+                     + 1 /* current method */);
   GenerateFrameEntry();
 
   for (size_t i = 0, e = blocks.Size(); i < e; ++i) {
@@ -110,10 +111,10 @@
   return -1;
 }
 
-void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots) {
+void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots, size_t number_of_out_slots) {
   SetFrameSize(RoundUp(
       number_of_spill_slots * kVRegSize
-      + kVRegSize  // Art method
+      + number_of_out_slots * kVRegSize
       + FrameEntrySpillSize(),
       kStackAlignment));
 }
@@ -376,4 +377,95 @@
   *data = vmap_encoder.GetData();
 }
 
+void CodeGenerator::BuildStackMaps(std::vector<uint8_t>* data) {
+  uint32_t size = stack_map_stream_.ComputeNeededSize();
+  data->resize(size);
+  MemoryRegion region(data->data(), size);
+  stack_map_stream_.FillIn(region);
+}
+
+void CodeGenerator::RecordPcInfo(HInstruction* instruction, uint32_t dex_pc) {
+  // Collect PC infos for the mapping table.
+  struct PcInfo pc_info;
+  pc_info.dex_pc = dex_pc;
+  pc_info.native_pc = GetAssembler()->CodeSize();
+  pc_infos_.Add(pc_info);
+
+  // Populate stack map information.
+
+  if (instruction == nullptr) {
+    // For stack overflow checks.
+    stack_map_stream_.AddStackMapEntry(dex_pc, pc_info.native_pc, 0, 0, 0, 0);
+    return;
+  }
+
+  LocationSummary* locations = instruction->GetLocations();
+  HEnvironment* environment = instruction->GetEnvironment();
+
+  size_t environment_size = instruction->EnvironmentSize();
+
+  size_t register_mask = 0;
+  size_t inlining_depth = 0;
+  stack_map_stream_.AddStackMapEntry(
+      dex_pc, pc_info.native_pc, register_mask,
+      locations->GetStackMask(), environment_size, inlining_depth);
+
+  // Walk over the environment, and record the location of dex registers.
+  for (size_t i = 0; i < environment_size; ++i) {
+    HInstruction* current = environment->GetInstructionAt(i);
+    if (current == nullptr) {
+      stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kNone, 0);
+      continue;
+    }
+
+    Location location = locations->GetEnvironmentAt(i);
+    switch (location.GetKind()) {
+      case Location::kConstant: {
+        DCHECK(current == location.GetConstant());
+        if (current->IsLongConstant()) {
+          int64_t value = current->AsLongConstant()->GetValue();
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kConstant, Low32Bits(value));
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kConstant, High32Bits(value));
+          ++i;
+          DCHECK_LT(i, environment_size);
+        } else {
+          DCHECK(current->IsIntConstant());
+          int32_t value = current->AsIntConstant()->GetValue();
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kConstant, value);
+        }
+        break;
+      }
+
+      case Location::kStackSlot: {
+        stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInStack, location.GetStackIndex());
+        break;
+      }
+
+      case Location::kDoubleStackSlot: {
+        stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInStack, location.GetStackIndex());
+        stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInStack,
+                                              location.GetHighStackIndex(kVRegSize));
+        ++i;
+        DCHECK_LT(i, environment_size);
+        break;
+      }
+
+      case Location::kRegister : {
+        int id = location.reg().RegId();
+        stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInRegister, id);
+        if (current->GetType() == Primitive::kPrimDouble
+            || current->GetType() == Primitive::kPrimLong) {
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInRegister, id);
+          ++i;
+          DCHECK_LT(i, environment_size);
+        }
+        break;
+      }
+
+      default:
+        LOG(FATAL) << "Unexpected kind " << location.GetKind();
+    }
+  }
+}
+
 }  // namespace art