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,
diff --git a/compiler/debug/elf_debug_loc_writer.h b/compiler/debug/elf_debug_loc_writer.h
index 32f624a..c321b4b 100644
--- a/compiler/debug/elf_debug_loc_writer.h
+++ b/compiler/debug/elf_debug_loc_writer.h
@@ -85,29 +85,32 @@
// The result will cover all ranges where the variable is in scope.
// PCs corresponding to stackmap with dex register map are accurate,
// all other PCs are best-effort only.
-std::vector<VariableLocation> GetVariableLocations(const MethodDebugInfo* method_info,
- uint16_t vreg,
- bool is64bitValue,
- uint32_t dex_pc_low,
- uint32_t dex_pc_high) {
+std::vector<VariableLocation> GetVariableLocations(
+ const MethodDebugInfo* method_info,
+ const std::vector<DexRegisterMap>& dex_register_maps,
+ uint16_t vreg,
+ bool is64bitValue,
+ uint32_t dex_pc_low,
+ uint32_t dex_pc_high) {
std::vector<VariableLocation> variable_locations;
// Get stack maps sorted by pc (they might not be sorted internally).
const CodeInfo code_info(method_info->compiled_method->GetVmapTable().data());
const StackMapEncoding encoding = code_info.ExtractEncoding();
- std::map<uint32_t, StackMap> stack_maps;
+ std::map<uint32_t, uint32_t> stack_maps; // low_pc -> stack_map_index.
for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(); s++) {
StackMap stack_map = code_info.GetStackMapAt(s, encoding);
DCHECK(stack_map.IsValid());
const uint32_t low_pc = method_info->low_pc + stack_map.GetNativePcOffset(encoding);
DCHECK_LE(low_pc, method_info->high_pc);
- stack_maps.emplace(low_pc, stack_map);
+ stack_maps.emplace(low_pc, s);
}
// Create entries for the requested register based on stack map data.
for (auto it = stack_maps.begin(); it != stack_maps.end(); it++) {
- const StackMap& stack_map = it->second;
const uint32_t low_pc = it->first;
+ const uint32_t stack_map_index = it->second;
+ const StackMap& stack_map = code_info.GetStackMapAt(stack_map_index, encoding);
auto next_it = it;
next_it++;
const uint32_t high_pc = next_it != stack_maps.end() ? next_it->first
@@ -126,9 +129,9 @@
// Find the location of the dex register.
DexRegisterLocation reg_lo = DexRegisterLocation::None();
DexRegisterLocation reg_hi = DexRegisterLocation::None();
- if (stack_map.HasDexRegisterMap(encoding)) {
- DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
- stack_map, encoding, method_info->code_item->registers_size_);
+ DCHECK_LT(stack_map_index, dex_register_maps.size());
+ DexRegisterMap dex_register_map = dex_register_maps[stack_map_index];
+ if (dex_register_map.IsValid()) {
reg_lo = dex_register_map.GetDexRegisterLocation(
vreg, method_info->code_item->registers_size_, code_info, encoding);
if (is64bitValue) {
@@ -159,6 +162,7 @@
// The dex register might be valid only at some points and it might
// move between machine registers and stack.
static void WriteDebugLocEntry(const MethodDebugInfo* method_info,
+ const std::vector<DexRegisterMap>& dex_register_maps,
uint16_t vreg,
bool is64bitValue,
uint32_t compilation_unit_low_pc,
@@ -175,6 +179,7 @@
std::vector<VariableLocation> variable_locations = GetVariableLocations(
method_info,
+ dex_register_maps,
vreg,
is64bitValue,
dex_pc_low,