Cache DexRegisterMaps when writing native debug info.

I might make the function more expensive in the future so I want
to make sure it gets called only the minimum number of times.

Change-Id: I1d09ecf1db7b54d28aaa11a152226d469f514fe7
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index eed032f..bddb054 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -173,6 +173,19 @@
       info_.WriteExprLoc(DW_AT_frame_base, expr);
       WriteLazyType(dex->GetReturnTypeDescriptor(dex_proto));
 
+      // Decode dex register locations for all stack maps.
+      // It might be expensive, so do it just once and reuse the result.
+      std::vector<DexRegisterMap> dex_reg_maps;
+      if (mi->IsFromOptimizingCompiler()) {
+        const CodeInfo code_info(mi->compiled_method->GetVmapTable().data());
+        StackMapEncoding encoding = code_info.ExtractEncoding();
+        for (size_t s = 0; s < code_info.GetNumberOfStackMaps(); ++s) {
+          const StackMap& stack_map = code_info.GetStackMapAt(s, encoding);
+          dex_reg_maps.push_back(code_info.GetDexRegisterMapOf(
+              stack_map, encoding, dex_code->registers_size_));
+        }
+      }
+
       // Write parameters. DecodeDebugLocalInfo returns them as well, but it does not
       // guarantee order or uniqueness so it is safer to iterate over them manually.
       // DecodeDebugLocalInfo might not also be available if there is no debug info.
@@ -187,7 +200,7 @@
           // Write the stack location of the parameter.
           const uint32_t vreg = dex_code->registers_size_ - dex_code->ins_size_ + arg_reg;
           const bool is64bitValue = false;
-          WriteRegLocation(mi, vreg, is64bitValue, compilation_unit.low_pc);
+          WriteRegLocation(mi, dex_reg_maps, vreg, is64bitValue, compilation_unit.low_pc);
         }
         arg_reg++;
         info_.EndTag();
@@ -206,7 +219,7 @@
           if (dex_code != nullptr) {
             // Write the stack location of the parameter.
             const uint32_t vreg = dex_code->registers_size_ - dex_code->ins_size_ + arg_reg;
-            WriteRegLocation(mi, vreg, is64bitValue, compilation_unit.low_pc);
+            WriteRegLocation(mi, dex_reg_maps, vreg, is64bitValue, compilation_unit.low_pc);
           }
           arg_reg += is64bitValue ? 2 : 1;
           info_.EndTag();
@@ -229,8 +242,13 @@
             WriteName(var.name_);
             WriteLazyType(var.descriptor_);
             bool is64bitValue = var.descriptor_[0] == 'D' || var.descriptor_[0] == 'J';
-            WriteRegLocation(mi, var.reg_, is64bitValue, compilation_unit.low_pc,
-                             var.start_address_, var.end_address_);
+            WriteRegLocation(mi,
+                             dex_reg_maps,
+                             var.reg_,
+                             is64bitValue,
+                             compilation_unit.low_pc,
+                             var.start_address_,
+                             var.end_address_);
             info_.EndTag();
           }
         }
@@ -424,12 +442,14 @@
   // The dex register might be valid only at some points and it might
   // move between machine registers and stack.
   void WriteRegLocation(const MethodDebugInfo* method_info,
+                        const std::vector<DexRegisterMap>& dex_register_maps,
                         uint16_t vreg,
                         bool is64bitValue,
                         uint32_t compilation_unit_low_pc,
                         uint32_t dex_pc_low = 0,
                         uint32_t dex_pc_high = 0xFFFFFFFF) {
     WriteDebugLocEntry(method_info,
+                       dex_register_maps,
                        vreg,
                        is64bitValue,
                        compilation_unit_low_pc,