[optimizing] Don't record None locations in the stack maps.

- moved environment recording from code generator to stack map stream
- added creation/loading factory methods for the DexRegisterMap (hides
internal details)
- added new tests

Change-Id: Ic8b6d044f0d8255c6759c19a41df332ef37876fe
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index a6ab208..9ebf887 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -577,142 +577,42 @@
   pc_info.native_pc = GetAssembler()->CodeSize();
   pc_infos_.Add(pc_info);
 
-  // Populate stack map information.
-
+  uint32_t inlining_depth = 0;
   if (instruction == nullptr) {
     // For stack overflow checks.
-    stack_map_stream_.AddStackMapEntry(dex_pc, pc_info.native_pc, 0, 0, 0, 0);
-    return;
-  }
+    stack_map_stream_.RecordEnvironment(
+       /* environment */ nullptr,
+       /* environment_size */ 0,
+       /* locations */ nullptr,
+       dex_pc,
+       pc_info.native_pc,
+       /* register_mask */ 0,
+       inlining_depth);
+  } else {
+    LocationSummary* locations = instruction->GetLocations();
+    HEnvironment* environment = instruction->GetEnvironment();
+    size_t environment_size = instruction->EnvironmentSize();
 
-  LocationSummary* locations = instruction->GetLocations();
-  HEnvironment* environment = instruction->GetEnvironment();
-
-  size_t environment_size = instruction->EnvironmentSize();
-
-  size_t inlining_depth = 0;
-  uint32_t register_mask = locations->GetRegisterMask();
-  if (locations->OnlyCallsOnSlowPath()) {
-    // In case of slow path, we currently set the location of caller-save registers
-    // to register (instead of their stack location when pushed before the slow-path
-    // call). Therefore register_mask contains both callee-save and caller-save
-    // registers that hold objects. We must remove the caller-save from the mask, since
-    // they will be overwritten by the callee.
-    register_mask &= core_callee_save_mask_;
-  }
-  // The register mask must be a subset of callee-save registers.
-  DCHECK_EQ(register_mask & core_callee_save_mask_, register_mask);
-  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(DexRegisterLocation::Kind::kNone, 0);
-      continue;
+    uint32_t register_mask = locations->GetRegisterMask();
+    if (locations->OnlyCallsOnSlowPath()) {
+      // In case of slow path, we currently set the location of caller-save registers
+      // to register (instead of their stack location when pushed before the slow-path
+      // call). Therefore register_mask contains both callee-save and caller-save
+      // registers that hold objects. We must remove the caller-save from the mask, since
+      // they will be overwritten by the callee.
+      register_mask &= core_callee_save_mask_;
     }
+    // The register mask must be a subset of callee-save registers.
+    DCHECK_EQ(register_mask & core_callee_save_mask_, register_mask);
 
-    Location location = locations->GetEnvironmentAt(i);
-    switch (location.GetKind()) {
-      case Location::kConstant: {
-        DCHECK_EQ(current, location.GetConstant());
-        if (current->IsLongConstant()) {
-          int64_t value = current->AsLongConstant()->GetValue();
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant,
-                                                Low32Bits(value));
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant,
-                                                High32Bits(value));
-          ++i;
-          DCHECK_LT(i, environment_size);
-        } else if (current->IsDoubleConstant()) {
-          int64_t value = bit_cast<double, int64_t>(current->AsDoubleConstant()->GetValue());
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant,
-                                                Low32Bits(value));
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant,
-                                                High32Bits(value));
-          ++i;
-          DCHECK_LT(i, environment_size);
-        } else if (current->IsIntConstant()) {
-          int32_t value = current->AsIntConstant()->GetValue();
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, value);
-        } else if (current->IsNullConstant()) {
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, 0);
-        } else {
-          DCHECK(current->IsFloatConstant());
-          int32_t value = bit_cast<float, int32_t>(current->AsFloatConstant()->GetValue());
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, value);
-        }
-        break;
-      }
-
-      case Location::kStackSlot: {
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack,
-                                              location.GetStackIndex());
-        break;
-      }
-
-      case Location::kDoubleStackSlot: {
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack,
-                                              location.GetStackIndex());
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack,
-                                              location.GetHighStackIndex(kVRegSize));
-        ++i;
-        DCHECK_LT(i, environment_size);
-        break;
-      }
-
-      case Location::kRegister : {
-        int id = location.reg();
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, id);
-        if (current->GetType() == Primitive::kPrimLong) {
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, id);
-          ++i;
-          DCHECK_LT(i, environment_size);
-        }
-        break;
-      }
-
-      case Location::kFpuRegister : {
-        int id = location.reg();
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, id);
-        if (current->GetType() == Primitive::kPrimDouble) {
-          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, id);
-          ++i;
-          DCHECK_LT(i, environment_size);
-        }
-        break;
-      }
-
-      case Location::kFpuRegisterPair : {
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister,
-                                              location.low());
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister,
-                                              location.high());
-        ++i;
-        DCHECK_LT(i, environment_size);
-        break;
-      }
-
-      case Location::kRegisterPair : {
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister,
-                                              location.low());
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister,
-                                              location.high());
-        ++i;
-        DCHECK_LT(i, environment_size);
-        break;
-      }
-
-      case Location::kInvalid: {
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kNone, 0);
-        break;
-      }
-
-      default:
-        LOG(FATAL) << "Unexpected kind " << location.GetKind();
-    }
+    // Populate stack map information.
+    stack_map_stream_.RecordEnvironment(environment,
+                                        environment_size,
+                                        locations,
+                                        dex_pc,
+                                        pc_info.native_pc,
+                                        register_mask,
+                                        inlining_depth);
   }
 }