diff options
-rw-r--r-- | compiler/optimizing/code_generator.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_stream.h | 31 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_test.cc | 2 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 104 | ||||
-rw-r--r-- | runtime/stack_map.h | 55 |
5 files changed, 141 insertions, 53 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 5b395c8..2a57fdc 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -620,7 +620,7 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction, uint32_t dex_pc) { Location location = locations->GetEnvironmentAt(i); switch (location.GetKind()) { case Location::kConstant: { - DCHECK(current == location.GetConstant()); + DCHECK_EQ(current, location.GetConstant()); if (current->IsLongConstant()) { int64_t value = current->AsLongConstant()->GetValue(); stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kConstant, Low32Bits(value)); diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h index 3974e53..5283d5d 100644 --- a/compiler/optimizing/stack_map_stream.h +++ b/compiler/optimizing/stack_map_stream.h @@ -166,18 +166,23 @@ class StackMapStream : public ValueObject { stack_map.SetStackMask(*entry.sp_mask); } - // Set the register map. - MemoryRegion register_region = dex_register_maps_region.Subregion( - next_dex_register_map_offset, - DexRegisterMap::kFixedSize + entry.num_dex_registers * DexRegisterMap::SingleEntrySize()); - next_dex_register_map_offset += register_region.size(); - DexRegisterMap dex_register_map(register_region); - stack_map.SetDexRegisterMapOffset(register_region.start() - memory_start); - - for (size_t j = 0; j < entry.num_dex_registers; ++j) { - DexRegisterEntry register_entry = - dex_register_maps_.Get(j + entry.dex_register_maps_start_index); - dex_register_map.SetRegisterInfo(j, register_entry.kind, register_entry.value); + if (entry.num_dex_registers != 0) { + // Set the register map. + MemoryRegion register_region = dex_register_maps_region.Subregion( + next_dex_register_map_offset, + DexRegisterMap::kFixedSize + + entry.num_dex_registers * DexRegisterMap::SingleEntrySize()); + next_dex_register_map_offset += register_region.size(); + DexRegisterMap dex_register_map(register_region); + stack_map.SetDexRegisterMapOffset(register_region.start() - memory_start); + + for (size_t j = 0; j < entry.num_dex_registers; ++j) { + DexRegisterEntry register_entry = + dex_register_maps_.Get(j + entry.dex_register_maps_start_index); + dex_register_map.SetRegisterInfo(j, register_entry.kind, register_entry.value); + } + } else { + stack_map.SetDexRegisterMapOffset(StackMap::kNoDexRegisterMap); } // Set the inlining info. @@ -196,7 +201,7 @@ class StackMapStream : public ValueObject { inline_info.SetMethodReferenceIndexAtDepth(j, inline_entry.method_index); } } else { - stack_map.SetInlineDescriptorOffset(InlineInfo::kNoInlineInfo); + stack_map.SetInlineDescriptorOffset(StackMap::kNoInlineInfo); } } } diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc index 5ee6ae0..744fb45 100644 --- a/compiler/optimizing/stack_map_test.cc +++ b/compiler/optimizing/stack_map_test.cc @@ -61,6 +61,7 @@ TEST(StackMapTest, Test1) { MemoryRegion stack_mask = stack_map.GetStackMask(); ASSERT_TRUE(SameBits(stack_mask, sp_mask)); + ASSERT_TRUE(stack_map.HasDexRegisterMap()); DexRegisterMap dex_registers = code_info.GetDexRegisterMapOf(stack_map, 2); ASSERT_EQ(DexRegisterMap::kInStack, dex_registers.GetLocationKind(0)); ASSERT_EQ(DexRegisterMap::kConstant, dex_registers.GetLocationKind(1)); @@ -107,6 +108,7 @@ TEST(StackMapTest, Test2) { MemoryRegion stack_mask = stack_map.GetStackMask(); ASSERT_TRUE(SameBits(stack_mask, sp_mask1)); + ASSERT_TRUE(stack_map.HasDexRegisterMap()); DexRegisterMap dex_registers = code_info.GetDexRegisterMapOf(stack_map, 2); ASSERT_EQ(DexRegisterMap::kInStack, dex_registers.GetLocationKind(0)); ASSERT_EQ(DexRegisterMap::kConstant, dex_registers.GetLocationKind(1)); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 931cca7..11ccafb 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -764,7 +764,7 @@ class OatDumper { oat_method.GetVmapTableOffsetOffset()); success = false; } else if (options_->dump_vmap_) { - DumpVmap(*indent2_os, oat_method); + DumpVmapData(*indent2_os, oat_method, code_item); } } { @@ -869,37 +869,87 @@ class OatDumper { os << ")"; } - void DumpVmap(std::ostream& os, const OatFile::OatMethod& oat_method) { - // If the native GC map is null, then this method has been compiled with the - // optimizing compiler. The optimizing compiler currently outputs its stack map - // in the vmap table, and the code below does not work with such a stack map. + // Display data stored at the the vmap offset of an oat method. + void DumpVmapData(std::ostream& os, + const OatFile::OatMethod& oat_method, + const DexFile::CodeItem* code_item) { if (oat_method.GetGcMap() == nullptr) { - return; + // If the native GC map is null, then this method has been + // compiled with the optimizing compiler. The optimizing + // compiler currently outputs its stack maps in the vmap table. + const void* raw_code_info = oat_method.GetVmapTable(); + if (raw_code_info != nullptr) { + CodeInfo code_info(raw_code_info); + DCHECK(code_item != nullptr); + DumpCodeInfo(os, code_info, *code_item); + } + } else { + // Otherwise, display the vmap table. + const uint8_t* raw_table = oat_method.GetVmapTable(); + if (raw_table != nullptr) { + VmapTable vmap_table(raw_table); + DumpVmapTable(os, oat_method, vmap_table); + } } - const uint8_t* raw_table = oat_method.GetVmapTable(); - if (raw_table != nullptr) { - const VmapTable vmap_table(raw_table); - bool first = true; - bool processing_fp = false; - uint32_t spill_mask = oat_method.GetCoreSpillMask(); - for (size_t i = 0; i < vmap_table.Size(); i++) { - uint16_t dex_reg = vmap_table[i]; - uint32_t cpu_reg = vmap_table.ComputeRegister(spill_mask, i, - processing_fp ? kFloatVReg : kIntVReg); - os << (first ? "v" : ", v") << dex_reg; - if (!processing_fp) { - os << "/r" << cpu_reg; - } else { - os << "/fr" << cpu_reg; - } - first = false; - if (!processing_fp && dex_reg == 0xFFFF) { - processing_fp = true; - spill_mask = oat_method.GetFpSpillMask(); + } + + // Display a CodeInfo object emitted by the optimizing compiler. + void DumpCodeInfo(std::ostream& os, + const CodeInfo& code_info, + const DexFile::CodeItem& code_item) { + uint16_t number_of_dex_registers = code_item.registers_size_; + uint32_t code_info_size = code_info.GetOverallSize(); + size_t number_of_stack_maps = code_info.GetNumberOfStackMaps(); + os << " Optimized CodeInfo (size=" << code_info_size + << ", number_of_dex_registers=" << number_of_dex_registers + << ", number_of_stack_maps=" << number_of_stack_maps << ")\n"; + for (size_t i = 0; i < number_of_stack_maps; ++i) { + StackMap stack_map = code_info.GetStackMapAt(i); + // TODO: Display stack_mask value. + os << " StackMap " << i + << std::hex + << " (dex_pc=0x" << stack_map.GetDexPc() + << ", native_pc_offset=0x" << stack_map.GetNativePcOffset() + << ", register_mask=0x" << stack_map.GetRegisterMask() + << std::dec + << ")\n"; + if (stack_map.HasDexRegisterMap()) { + DexRegisterMap dex_register_map = + code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers); + for (size_t j = 0; j < number_of_dex_registers; ++j) { + os << " v" << j << ": " + << DexRegisterMap::PrettyDescriptor(dex_register_map.GetLocationKind(j)) + << " (" << dex_register_map.GetValue(j) << ")\n"; } } - os << "\n"; + // TODO: Display more information from code_info. + } + } + + // Display a vmap table. + void DumpVmapTable(std::ostream& os, + const OatFile::OatMethod& oat_method, + const VmapTable& vmap_table) { + bool first = true; + bool processing_fp = false; + uint32_t spill_mask = oat_method.GetCoreSpillMask(); + for (size_t i = 0; i < vmap_table.Size(); i++) { + uint16_t dex_reg = vmap_table[i]; + uint32_t cpu_reg = vmap_table.ComputeRegister(spill_mask, i, + processing_fp ? kFloatVReg : kIntVReg); + os << (first ? "v" : ", v") << dex_reg; + if (!processing_fp) { + os << "/r" << cpu_reg; + } else { + os << "/fr" << cpu_reg; + } + first = false; + if (!processing_fp && dex_reg == 0xFFFF) { + processing_fp = true; + spill_mask = oat_method.GetFpSpillMask(); + } } + os << "\n"; } void DumpVregLocations(std::ostream& os, const OatFile::OatMethod& oat_method, diff --git a/runtime/stack_map.h b/runtime/stack_map.h index 7cc3e57..fd22361 100644 --- a/runtime/stack_map.h +++ b/runtime/stack_map.h @@ -61,8 +61,6 @@ class InlineInfo { static constexpr int kDepthOffset = 0; static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t); - static constexpr uint32_t kNoInlineInfo = -1; - MemoryRegion region_; friend class CodeInfo; @@ -76,10 +74,11 @@ class InlineInfo { * [location_kind, register_value]+. * * The location_kind for a Dex register can either be: - * - Constant: register_value holds the constant, - * - Stack: register_value holds the stack offset, - * - Register: register_value holds the physical register number. - * - None: the register has no location yet, meaning it has not been set. + * - kConstant: register_value holds the constant, + * - kStack: register_value holds the stack offset, + * - kRegister: register_value holds the physical register number. + * - kFpuRegister: register_value holds the physical register number. + * - kNone: the register has no location yet, meaning it has not been set. */ class DexRegisterMap { public: @@ -93,6 +92,24 @@ class DexRegisterMap { kConstant }; + static const char* PrettyDescriptor(LocationKind kind) { + switch (kind) { + case kNone: + return "none"; + case kInStack: + return "in stack"; + case kInRegister: + return "in register"; + case kInFpuRegister: + return "in fpu register"; + case kConstant: + return "as constant"; + default: + LOG(FATAL) << "Invalid location kind " << static_cast<int>(kind); + return nullptr; + } + } + LocationKind GetLocationKind(uint16_t register_index) const { return region_.Load<LocationKind>( kFixedSize + register_index * SingleEntrySize()); @@ -191,11 +208,15 @@ class StackMap { } } + bool HasDexRegisterMap() const { + return GetDexRegisterMapOffset() != kNoDexRegisterMap; + } + bool HasInlineInfo() const { - return GetInlineDescriptorOffset() != InlineInfo::kNoInlineInfo; + return GetInlineDescriptorOffset() != kNoInlineInfo; } - bool Equals(const StackMap& other) { + bool Equals(const StackMap& other) const { return region_.pointer() == other.region_.pointer() && region_.size() == other.region_.size(); } @@ -205,6 +226,14 @@ class StackMap { return RoundUp(StackMap::kFixedSize + stack_mask_size, 4); } + // Special (invalid) offset for the DexRegisterMapOffset field meaning + // that there is no Dex register map for this stack map. + static constexpr uint32_t kNoDexRegisterMap = -1; + + // Special (invalid) offset for the InlineDescriptorOffset field meaning + // that there is no inline info for this stack map. + static constexpr uint32_t kNoInlineInfo = -1; + private: static constexpr int kDexPcOffset = 0; static constexpr int kNativePcOffsetOffset = kDexPcOffset + sizeof(uint32_t); @@ -271,20 +300,22 @@ class CodeInfo { return StackMap::ComputeAlignedStackMapSize(GetStackMaskSize()); } - DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) { + DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const { + DCHECK(stack_map.HasDexRegisterMap()); uint32_t offset = stack_map.GetDexRegisterMapOffset(); return DexRegisterMap(region_.Subregion(offset, DexRegisterMap::kFixedSize + number_of_dex_registers * DexRegisterMap::SingleEntrySize())); } - InlineInfo GetInlineInfoOf(StackMap stack_map) { + InlineInfo GetInlineInfoOf(StackMap stack_map) const { + DCHECK(stack_map.HasInlineInfo()); uint32_t offset = stack_map.GetInlineDescriptorOffset(); uint8_t depth = region_.Load<uint8_t>(offset); return InlineInfo(region_.Subregion(offset, InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize())); } - StackMap GetStackMapForDexPc(uint32_t dex_pc) { + StackMap GetStackMapForDexPc(uint32_t dex_pc) const { for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { StackMap stack_map = GetStackMapAt(i); if (stack_map.GetDexPc() == dex_pc) { @@ -295,7 +326,7 @@ class CodeInfo { UNREACHABLE(); } - StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) { + StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const { // TODO: stack maps are sorted by native pc, we can do a binary search. for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { StackMap stack_map = GetStackMapAt(i); |