Add Kind column to stack maps.
Add 'Kind' column to stack maps which marks special stack map types,
and use it at run-time to add extra sanity checks.
It will also allow us to binary search the stack maps.
The column increases .oat file by 0.2%.
Test: test-art-host-gtest-stack_map_test
Change-Id: I2a9143afa0e32bb06174604ca81a64c41fed232f
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index ea358c6..faa196f 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -157,16 +157,23 @@
* - Knowing the inlining information,
* - Knowing the values of dex registers.
*/
-class StackMap : public BitTable<7>::Accessor {
+class StackMap : public BitTable<8>::Accessor {
public:
+ enum Kind {
+ Default = -1,
+ Catch = 0,
+ OSR = 1,
+ Debug = 2,
+ };
BIT_TABLE_HEADER()
- BIT_TABLE_COLUMN(0, PackedNativePc)
- BIT_TABLE_COLUMN(1, DexPc)
- BIT_TABLE_COLUMN(2, RegisterMaskIndex)
- BIT_TABLE_COLUMN(3, StackMaskIndex)
- BIT_TABLE_COLUMN(4, InlineInfoIndex)
- BIT_TABLE_COLUMN(5, DexRegisterMaskIndex)
- BIT_TABLE_COLUMN(6, DexRegisterMapIndex)
+ BIT_TABLE_COLUMN(0, Kind)
+ BIT_TABLE_COLUMN(1, PackedNativePc)
+ BIT_TABLE_COLUMN(2, DexPc)
+ BIT_TABLE_COLUMN(3, RegisterMaskIndex)
+ BIT_TABLE_COLUMN(4, StackMaskIndex)
+ BIT_TABLE_COLUMN(5, InlineInfoIndex)
+ BIT_TABLE_COLUMN(6, DexRegisterMaskIndex)
+ BIT_TABLE_COLUMN(7, DexRegisterMapIndex)
ALWAYS_INLINE uint32_t GetNativePcOffset(InstructionSet instruction_set) const {
return UnpackNativePc(Get<kPackedNativePc>(), instruction_set);
@@ -415,19 +422,18 @@
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) {
+ if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() != StackMap::Kind::Debug) {
return stack_map;
}
}
return StackMap();
}
- // Searches the stack map list backwards because catch stack maps are stored
- // at the end.
+ // Searches the stack map list backwards because catch stack maps are stored at the end.
StackMap GetCatchStackMapForDexPc(uint32_t dex_pc) const {
for (size_t i = GetNumberOfStackMaps(); i > 0; --i) {
StackMap stack_map = GetStackMapAt(i - 1);
- if (stack_map.GetDexPc() == dex_pc) {
+ if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() == StackMap::Kind::Catch) {
return stack_map;
}
}
@@ -435,41 +441,26 @@
}
StackMap GetOsrStackMapForDexPc(uint32_t dex_pc) const {
- size_t e = GetNumberOfStackMaps();
- if (e == 0) {
- // There cannot be OSR stack map if there is no stack map.
- return StackMap();
- }
- // Walk over all stack maps. If two consecutive stack maps are identical, then we
- // have found a stack map suitable for OSR.
- for (size_t i = 0; i < e - 1; ++i) {
+ for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
StackMap stack_map = GetStackMapAt(i);
- if (stack_map.GetDexPc() == dex_pc) {
- StackMap other = GetStackMapAt(i + 1);
- if (other.GetDexPc() == dex_pc &&
- other.GetNativePcOffset(kRuntimeISA) ==
- stack_map.GetNativePcOffset(kRuntimeISA)) {
- if (i < e - 2) {
- // Make sure there are not three identical stack maps following each other.
- DCHECK_NE(
- stack_map.GetNativePcOffset(kRuntimeISA),
- GetStackMapAt(i + 2).GetNativePcOffset(kRuntimeISA));
- }
- return stack_map;
- }
+ if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() == StackMap::Kind::OSR) {
+ return stack_map;
}
}
return StackMap();
}
- StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const {
+ StackMap GetStackMapForNativePcOffset(uint32_t pc, InstructionSet isa = kRuntimeISA) const {
// TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack
// maps are not. If we knew that the method does not have try/catch,
// we could do binary search.
for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
StackMap stack_map = GetStackMapAt(i);
- if (stack_map.GetNativePcOffset(kRuntimeISA) == native_pc_offset) {
- return stack_map;
+ if (stack_map.GetNativePcOffset(isa) == pc) {
+ StackMap::Kind kind = static_cast<StackMap::Kind>(stack_map.GetKind());
+ if (kind == StackMap::Kind::Default || kind == StackMap::Kind::OSR) {
+ return stack_map;
+ }
}
}
return StackMap();