summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/code_generator.cc2
-rw-r--r--compiler/optimizing/stack_map_stream.h31
-rw-r--r--compiler/optimizing/stack_map_test.cc2
-rw-r--r--oatdump/oatdump.cc104
-rw-r--r--runtime/stack_map.h55
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);