diff options
-rw-r--r-- | compiler/optimizing/stack_map_stream.cc | 48 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_stream.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_test.cc | 318 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 6 | ||||
-rw-r--r-- | runtime/art_method.cc | 5 | ||||
-rw-r--r-- | runtime/check_reference_map_visitor.h | 13 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils-inl.h | 7 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 9 | ||||
-rw-r--r-- | runtime/jni_internal.cc | 2 | ||||
-rw-r--r-- | runtime/jni_internal_test.cc | 2 | ||||
-rw-r--r-- | runtime/mirror/class.h | 7 | ||||
-rw-r--r-- | runtime/stack.cc | 41 | ||||
-rw-r--r-- | runtime/stack_map.cc | 211 | ||||
-rw-r--r-- | runtime/stack_map.h | 409 | ||||
-rw-r--r-- | runtime/thread.cc | 7 |
15 files changed, 542 insertions, 544 deletions
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc index 5663e3973d..42b9182d55 100644 --- a/compiler/optimizing/stack_map_stream.cc +++ b/compiler/optimizing/stack_map_stream.cc @@ -133,13 +133,13 @@ size_t StackMapStream::PrepareForFillIn() { stack_mask_size_ = RoundUp(stack_mask_number_of_bits, kBitsPerByte) / kBitsPerByte; inline_info_size_ = ComputeInlineInfoSize(); dex_register_maps_size_ = ComputeDexRegisterMapsSize(); - stack_maps_size_ = stack_maps_.Size() - * StackMap::ComputeStackMapSize(stack_mask_size_, - inline_info_size_, - dex_register_maps_size_, - dex_pc_max_, - native_pc_offset_max_, - register_mask_max_); + stack_map_encoding_ = StackMapEncoding::CreateFromSizes(stack_mask_size_, + inline_info_size_, + dex_register_maps_size_, + dex_pc_max_, + native_pc_offset_max_, + register_mask_max_); + stack_maps_size_ = stack_maps_.Size() * stack_map_encoding_.ComputeStackMapSize(); dex_register_location_catalog_size_ = ComputeDexRegisterLocationCatalogSize(); // Note: use RoundUp to word-size here if you want CodeInfo objects to be word aligned. @@ -235,14 +235,9 @@ void StackMapStream::FillIn(MemoryRegion region) { MemoryRegion inline_infos_region = region.Subregion( inline_infos_start_, inline_info_size_); - code_info.SetEncoding(inline_info_size_, - dex_register_maps_size_, - dex_pc_max_, - native_pc_offset_max_, - register_mask_max_); + code_info.SetEncoding(stack_map_encoding_); code_info.SetNumberOfStackMaps(stack_maps_.Size()); - code_info.SetStackMaskSize(stack_mask_size_); - DCHECK_EQ(code_info.GetStackMapsSize(), stack_maps_size_); + DCHECK_EQ(code_info.GetStackMapsSize(code_info.ExtractEncoding()), stack_maps_size_); // Set the Dex register location catalog. code_info.SetNumberOfDexRegisterLocationCatalogEntries(location_catalog_entries_.Size()); @@ -263,26 +258,27 @@ void StackMapStream::FillIn(MemoryRegion region) { uintptr_t next_dex_register_map_offset = 0; uintptr_t next_inline_info_offset = 0; for (size_t i = 0, e = stack_maps_.Size(); i < e; ++i) { - StackMap stack_map = code_info.GetStackMapAt(i); + StackMap stack_map = code_info.GetStackMapAt(i, stack_map_encoding_); StackMapEntry entry = stack_maps_.Get(i); - stack_map.SetDexPc(code_info, entry.dex_pc); - stack_map.SetNativePcOffset(code_info, entry.native_pc_offset); - stack_map.SetRegisterMask(code_info, entry.register_mask); + stack_map.SetDexPc(stack_map_encoding_, entry.dex_pc); + stack_map.SetNativePcOffset(stack_map_encoding_, entry.native_pc_offset); + stack_map.SetRegisterMask(stack_map_encoding_, entry.register_mask); if (entry.sp_mask != nullptr) { - stack_map.SetStackMask(code_info, *entry.sp_mask); + stack_map.SetStackMask(stack_map_encoding_, *entry.sp_mask); } if (entry.num_dex_registers == 0) { // No dex map available. - stack_map.SetDexRegisterMapOffset(code_info, StackMap::kNoDexRegisterMap); + stack_map.SetDexRegisterMapOffset(stack_map_encoding_, StackMap::kNoDexRegisterMap); } else { // Search for an entry with the same dex map. if (entry.same_dex_register_map_as_ != kNoSameDexMapFound) { // If we have a hit reuse the offset. - stack_map.SetDexRegisterMapOffset(code_info, - code_info.GetStackMapAt(entry.same_dex_register_map_as_) - .GetDexRegisterMapOffset(code_info)); + stack_map.SetDexRegisterMapOffset( + stack_map_encoding_, + code_info.GetStackMapAt(entry.same_dex_register_map_as_, stack_map_encoding_) + .GetDexRegisterMapOffset(stack_map_encoding_)); } else { // New dex registers maps should be added to the stack map. MemoryRegion register_region = dex_register_locations_region.Subregion( @@ -291,7 +287,7 @@ void StackMapStream::FillIn(MemoryRegion region) { next_dex_register_map_offset += register_region.size(); DexRegisterMap dex_register_map(register_region); stack_map.SetDexRegisterMapOffset( - code_info, register_region.start() - dex_register_locations_region.start()); + stack_map_encoding_, register_region.start() - dex_register_locations_region.start()); // Set the dex register location. FillInDexRegisterMap(dex_register_map, @@ -311,7 +307,7 @@ void StackMapStream::FillIn(MemoryRegion region) { // Currently relative to the dex register map. stack_map.SetInlineDescriptorOffset( - code_info, inline_region.start() - dex_register_locations_region.start()); + stack_map_encoding_, inline_region.start() - dex_register_locations_region.start()); inline_info.SetDepth(entry.inlining_depth); for (size_t depth = 0; depth < entry.inlining_depth; ++depth) { @@ -341,7 +337,7 @@ void StackMapStream::FillIn(MemoryRegion region) { } } else { if (inline_info_size_ != 0) { - stack_map.SetInlineDescriptorOffset(code_info, StackMap::kNoInlineInfo); + stack_map.SetInlineDescriptorOffset(stack_map_encoding_, StackMap::kNoInlineInfo); } } } diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h index 0af983b1bf..274d573350 100644 --- a/compiler/optimizing/stack_map_stream.h +++ b/compiler/optimizing/stack_map_stream.h @@ -171,6 +171,7 @@ class StackMapStream : public ValueObject { StackMapEntry current_entry_; InlineInfoEntry current_inline_info_; + StackMapEncoding stack_map_encoding_; size_t stack_mask_size_; size_t inline_info_size_; size_t dex_register_maps_size_; diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc index 666fb604c0..b4ac1b4d1a 100644 --- a/compiler/optimizing/stack_map_test.cc +++ b/compiler/optimizing/stack_map_test.cc @@ -51,32 +51,33 @@ TEST(StackMapTest, Test1) { stream.FillIn(region); CodeInfo code_info(region); - ASSERT_EQ(0u, code_info.GetStackMaskSize()); + StackMapEncoding encoding = code_info.ExtractEncoding(); + ASSERT_EQ(0u, encoding.NumberOfBytesForStackMask()); ASSERT_EQ(1u, code_info.GetNumberOfStackMaps()); uint32_t number_of_location_catalog_entries = code_info.GetNumberOfDexRegisterLocationCatalogEntries(); ASSERT_EQ(2u, number_of_location_catalog_entries); - DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(); + DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding); // The Dex register location catalog contains: // - one 1-byte short Dex register location, and // - one 5-byte large Dex register location. size_t expected_location_catalog_size = 1u + 5u; ASSERT_EQ(expected_location_catalog_size, location_catalog.Size()); - StackMap stack_map = code_info.GetStackMapAt(0); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0))); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64))); - ASSERT_EQ(0u, stack_map.GetDexPc(code_info)); - ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info)); - ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info)); + StackMap stack_map = code_info.GetStackMapAt(0, encoding); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding))); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding))); + ASSERT_EQ(0u, stack_map.GetDexPc(encoding)); + ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding)); + ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding)); - MemoryRegion stack_mask = stack_map.GetStackMask(code_info); + MemoryRegion stack_mask = stack_map.GetStackMask(encoding); ASSERT_TRUE(SameBits(stack_mask, sp_mask)); - ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info)); + ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding)); DexRegisterMap dex_register_map = - code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers); + code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers); ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0)); ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1)); ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers)); @@ -86,16 +87,17 @@ TEST(StackMapTest, Test1) { size_t expected_dex_register_map_size = 1u + 1u; ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size()); - ASSERT_EQ(Kind::kInStack, - dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kConstant, - dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kInStack, - dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kConstantLargeValue, - dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info)); - ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info)); - ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info)); + ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind( + 1, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind( + 1, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding)); size_t index0 = dex_register_map.GetLocationCatalogEntryIndex( 0, number_of_dex_registers, number_of_location_catalog_entries); @@ -112,7 +114,7 @@ TEST(StackMapTest, Test1) { ASSERT_EQ(0, location0.GetValue()); ASSERT_EQ(-2, location1.GetValue()); - ASSERT_FALSE(stack_map.HasInlineInfo(code_info)); + ASSERT_FALSE(stack_map.HasInlineInfo(encoding)); } TEST(StackMapTest, Test2) { @@ -148,13 +150,14 @@ TEST(StackMapTest, Test2) { stream.FillIn(region); CodeInfo code_info(region); - ASSERT_EQ(2u, code_info.GetStackMaskSize()); + StackMapEncoding encoding = code_info.ExtractEncoding(); + ASSERT_EQ(2u, encoding.NumberOfBytesForStackMask()); ASSERT_EQ(2u, code_info.GetNumberOfStackMaps()); uint32_t number_of_location_catalog_entries = code_info.GetNumberOfDexRegisterLocationCatalogEntries(); ASSERT_EQ(4u, number_of_location_catalog_entries); - DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(); + DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding); // The Dex register location catalog contains: // - three 1-byte short Dex register locations, and // - one 5-byte large Dex register location. @@ -163,19 +166,19 @@ TEST(StackMapTest, Test2) { // First stack map. { - StackMap stack_map = code_info.GetStackMapAt(0); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0))); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64))); - ASSERT_EQ(0u, stack_map.GetDexPc(code_info)); - ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info)); - ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info)); - - MemoryRegion stack_mask = stack_map.GetStackMask(code_info); + StackMap stack_map = code_info.GetStackMapAt(0, encoding); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding))); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding))); + ASSERT_EQ(0u, stack_map.GetDexPc(encoding)); + ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding)); + ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding)); + + MemoryRegion stack_mask = stack_map.GetStackMask(encoding); ASSERT_TRUE(SameBits(stack_mask, sp_mask1)); - ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info)); + ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding)); DexRegisterMap dex_register_map = - code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers); + code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers); ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0)); ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1)); ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers)); @@ -185,16 +188,17 @@ TEST(StackMapTest, Test2) { size_t expected_dex_register_map_size = 1u + 1u; ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size()); - ASSERT_EQ(Kind::kInStack, - dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kConstant, - dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kInStack, - dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kConstantLargeValue, - dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info)); - ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info)); - ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info)); + ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind( + 1, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind( + 1, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding)); size_t index0 = dex_register_map.GetLocationCatalogEntryIndex( 0, number_of_dex_registers, number_of_location_catalog_entries); @@ -211,8 +215,8 @@ TEST(StackMapTest, Test2) { ASSERT_EQ(0, location0.GetValue()); ASSERT_EQ(-2, location1.GetValue()); - ASSERT_TRUE(stack_map.HasInlineInfo(code_info)); - InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map); + ASSERT_TRUE(stack_map.HasInlineInfo(encoding)); + InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding); ASSERT_EQ(2u, inline_info.GetDepth()); ASSERT_EQ(82u, inline_info.GetMethodIndexAtDepth(0)); ASSERT_EQ(42u, inline_info.GetMethodIndexAtDepth(1)); @@ -224,19 +228,19 @@ TEST(StackMapTest, Test2) { // Second stack map. { - StackMap stack_map = code_info.GetStackMapAt(1); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u))); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u))); - ASSERT_EQ(1u, stack_map.GetDexPc(code_info)); - ASSERT_EQ(128u, stack_map.GetNativePcOffset(code_info)); - ASSERT_EQ(0xFFu, stack_map.GetRegisterMask(code_info)); - - MemoryRegion stack_mask = stack_map.GetStackMask(code_info); + StackMap stack_map = code_info.GetStackMapAt(1, encoding); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u, encoding))); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u, encoding))); + ASSERT_EQ(1u, stack_map.GetDexPc(encoding)); + ASSERT_EQ(128u, stack_map.GetNativePcOffset(encoding)); + ASSERT_EQ(0xFFu, stack_map.GetRegisterMask(encoding)); + + MemoryRegion stack_mask = stack_map.GetStackMask(encoding); ASSERT_TRUE(SameBits(stack_mask, sp_mask2)); - ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info)); + ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding)); DexRegisterMap dex_register_map = - code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers); + code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers); ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0)); ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1)); ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers)); @@ -246,16 +250,18 @@ TEST(StackMapTest, Test2) { size_t expected_dex_register_map_size = 1u + 1u; ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size()); - ASSERT_EQ(Kind::kInRegister, - dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kInFpuRegister, - dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kInRegister, - dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kInFpuRegister, - dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info)); - ASSERT_EQ(18, dex_register_map.GetMachineRegister(0, number_of_dex_registers, code_info)); - ASSERT_EQ(3, dex_register_map.GetMachineRegister(1, number_of_dex_registers, code_info)); + ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind( + 1, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind( + 1, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(18, dex_register_map.GetMachineRegister( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(3, dex_register_map.GetMachineRegister( + 1, number_of_dex_registers, code_info, encoding)); size_t index0 = dex_register_map.GetLocationCatalogEntryIndex( 0, number_of_dex_registers, number_of_location_catalog_entries); @@ -272,7 +278,7 @@ TEST(StackMapTest, Test2) { ASSERT_EQ(18, location0.GetValue()); ASSERT_EQ(3, location1.GetValue()); - ASSERT_FALSE(stack_map.HasInlineInfo(code_info)); + ASSERT_FALSE(stack_map.HasInlineInfo(encoding)); } } @@ -294,28 +300,29 @@ TEST(StackMapTest, TestNonLiveDexRegisters) { stream.FillIn(region); CodeInfo code_info(region); - ASSERT_EQ(0u, code_info.GetStackMaskSize()); + StackMapEncoding encoding = code_info.ExtractEncoding(); + ASSERT_EQ(0u, encoding.NumberOfBytesForStackMask()); ASSERT_EQ(1u, code_info.GetNumberOfStackMaps()); uint32_t number_of_location_catalog_entries = code_info.GetNumberOfDexRegisterLocationCatalogEntries(); ASSERT_EQ(1u, number_of_location_catalog_entries); - DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(); + DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding); // The Dex register location catalog contains: // - one 5-byte large Dex register location. size_t expected_location_catalog_size = 5u; ASSERT_EQ(expected_location_catalog_size, location_catalog.Size()); - StackMap stack_map = code_info.GetStackMapAt(0); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0))); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64))); - ASSERT_EQ(0u, stack_map.GetDexPc(code_info)); - ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info)); - ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info)); + StackMap stack_map = code_info.GetStackMapAt(0, encoding); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding))); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding))); + ASSERT_EQ(0u, stack_map.GetDexPc(encoding)); + ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding)); + ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding)); - ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info)); + ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding)); DexRegisterMap dex_register_map = - code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers); + code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers); ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0)); ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1)); ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers)); @@ -325,15 +332,15 @@ TEST(StackMapTest, TestNonLiveDexRegisters) { size_t expected_dex_register_map_size = 1u + 0u; ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size()); - ASSERT_EQ(Kind::kNone, - dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kConstant, - dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kNone, - dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info)); - ASSERT_EQ(Kind::kConstantLargeValue, - dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info)); - ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info)); + ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationKind( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind( + 1, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationInternalKind( + 0, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind( + 1, number_of_dex_registers, code_info, encoding)); + ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding)); size_t index0 = dex_register_map.GetLocationCatalogEntryIndex( 0, number_of_dex_registers, number_of_location_catalog_entries); @@ -350,7 +357,7 @@ TEST(StackMapTest, TestNonLiveDexRegisters) { ASSERT_EQ(0, location0.GetValue()); ASSERT_EQ(-2, location1.GetValue()); - ASSERT_FALSE(stack_map.HasInlineInfo(code_info)); + ASSERT_FALSE(stack_map.HasInlineInfo(encoding)); } // Generate a stack map whose dex register offset is @@ -387,6 +394,7 @@ TEST(StackMapTest, DexRegisterMapOffsetOverflow) { stream.FillIn(region); CodeInfo code_info(region); + StackMapEncoding encoding = code_info.ExtractEncoding(); // The location catalog contains two entries (DexRegisterLocation(kConstant, 0) // and DexRegisterLocation(kConstant, 1)), therefore the location catalog index // has a size of 1 bit. @@ -402,20 +410,20 @@ TEST(StackMapTest, DexRegisterMapOffsetOverflow) { // locations (that is, 127 bytes of data). // Hence it has a size of 255 bytes, and therefore... ASSERT_EQ(128u, DexRegisterMap::GetLiveBitMaskSize(number_of_dex_registers)); - StackMap stack_map0 = code_info.GetStackMapAt(0); + StackMap stack_map0 = code_info.GetStackMapAt(0, encoding); DexRegisterMap dex_register_map0 = - code_info.GetDexRegisterMapOf(stack_map0, number_of_dex_registers); + code_info.GetDexRegisterMapOf(stack_map0, encoding, number_of_dex_registers); ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers, number_of_location_catalog_entries)); ASSERT_EQ(255u, dex_register_map0.Size()); - StackMap stack_map1 = code_info.GetStackMapAt(1); - ASSERT_TRUE(stack_map1.HasDexRegisterMap(code_info)); + StackMap stack_map1 = code_info.GetStackMapAt(1, encoding); + ASSERT_TRUE(stack_map1.HasDexRegisterMap(encoding)); // ...the offset of the second Dex register map (relative to the // beginning of the Dex register maps region) is 255 (i.e., // kNoDexRegisterMapSmallEncoding). - ASSERT_NE(stack_map1.GetDexRegisterMapOffset(code_info), StackMap::kNoDexRegisterMap); - ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(code_info), 0xFFu); + ASSERT_NE(stack_map1.GetDexRegisterMapOffset(encoding), StackMap::kNoDexRegisterMap); + ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(encoding), 0xFFu); } TEST(StackMapTest, TestShareDexRegisterMap) { @@ -447,28 +455,30 @@ TEST(StackMapTest, TestShareDexRegisterMap) { stream.FillIn(region); CodeInfo ci(region); + StackMapEncoding encoding = ci.ExtractEncoding(); + // Verify first stack map. - StackMap sm0 = ci.GetStackMapAt(0); - DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, number_of_dex_registers); - ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci)); - ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci)); + StackMap sm0 = ci.GetStackMapAt(0, encoding); + DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, number_of_dex_registers); + ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci, encoding)); + ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci, encoding)); // Verify second stack map. - StackMap sm1 = ci.GetStackMapAt(1); - DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, number_of_dex_registers); - ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci)); - ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci)); + StackMap sm1 = ci.GetStackMapAt(1, encoding); + DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, encoding, number_of_dex_registers); + ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci, encoding)); + ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci, encoding)); // Verify third stack map. - StackMap sm2 = ci.GetStackMapAt(2); - DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, number_of_dex_registers); - ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci)); - ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci)); + StackMap sm2 = ci.GetStackMapAt(2, encoding); + DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, encoding, number_of_dex_registers); + ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci, encoding)); + ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci, encoding)); // Verify dex register map offsets. - ASSERT_EQ(sm0.GetDexRegisterMapOffset(ci), sm1.GetDexRegisterMapOffset(ci)); - ASSERT_NE(sm0.GetDexRegisterMapOffset(ci), sm2.GetDexRegisterMapOffset(ci)); - ASSERT_NE(sm1.GetDexRegisterMapOffset(ci), sm2.GetDexRegisterMapOffset(ci)); + ASSERT_EQ(sm0.GetDexRegisterMapOffset(encoding), sm1.GetDexRegisterMapOffset(encoding)); + ASSERT_NE(sm0.GetDexRegisterMapOffset(encoding), sm2.GetDexRegisterMapOffset(encoding)); + ASSERT_NE(sm1.GetDexRegisterMapOffset(encoding), sm2.GetDexRegisterMapOffset(encoding)); } TEST(StackMapTest, TestNoDexRegisterMap) { @@ -487,24 +497,25 @@ TEST(StackMapTest, TestNoDexRegisterMap) { stream.FillIn(region); CodeInfo code_info(region); - ASSERT_EQ(0u, code_info.GetStackMaskSize()); + StackMapEncoding encoding = code_info.ExtractEncoding(); + ASSERT_EQ(0u, encoding.NumberOfBytesForStackMask()); ASSERT_EQ(1u, code_info.GetNumberOfStackMaps()); uint32_t number_of_location_catalog_entries = code_info.GetNumberOfDexRegisterLocationCatalogEntries(); ASSERT_EQ(0u, number_of_location_catalog_entries); - DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(); + DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding); ASSERT_EQ(0u, location_catalog.Size()); - StackMap stack_map = code_info.GetStackMapAt(0); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0))); - ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64))); - ASSERT_EQ(0u, stack_map.GetDexPc(code_info)); - ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info)); - ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info)); + StackMap stack_map = code_info.GetStackMapAt(0, encoding); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding))); + ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding))); + ASSERT_EQ(0u, stack_map.GetDexPc(encoding)); + ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding)); + ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding)); - ASSERT_FALSE(stack_map.HasDexRegisterMap(code_info)); - ASSERT_FALSE(stack_map.HasInlineInfo(code_info)); + ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding)); + ASSERT_FALSE(stack_map.HasInlineInfo(encoding)); } TEST(StackMapTest, InlineTest) { @@ -579,16 +590,17 @@ TEST(StackMapTest, InlineTest) { stream.FillIn(region); CodeInfo ci(region); + StackMapEncoding encoding = ci.ExtractEncoding(); { // Verify first stack map. - StackMap sm0 = ci.GetStackMapAt(0); + StackMap sm0 = ci.GetStackMapAt(0, encoding); - DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, 2); - ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci)); - ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci)); + DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, 2); + ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding)); + ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding)); - InlineInfo if0 = ci.GetInlineInfoOf(sm0); + InlineInfo if0 = ci.GetInlineInfoOf(sm0, encoding); ASSERT_EQ(2u, if0.GetDepth()); ASSERT_EQ(2u, if0.GetDexPcAtDepth(0)); ASSERT_EQ(42u, if0.GetMethodIndexAtDepth(0)); @@ -597,24 +609,24 @@ TEST(StackMapTest, InlineTest) { ASSERT_EQ(82u, if0.GetMethodIndexAtDepth(1)); ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(1)); - DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, 1); - ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci)); + DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, encoding, 1); + ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding)); - DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, 3); - ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci)); - ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci)); - ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci)); + DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, encoding, 3); + ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding)); + ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci, encoding)); + ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci, encoding)); } { // Verify second stack map. - StackMap sm1 = ci.GetStackMapAt(1); + StackMap sm1 = ci.GetStackMapAt(1, encoding); - DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, 2); - ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci)); - ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci)); + DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, encoding, 2); + ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding)); + ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding)); - InlineInfo if1 = ci.GetInlineInfoOf(sm1); + InlineInfo if1 = ci.GetInlineInfoOf(sm1, encoding); ASSERT_EQ(3u, if1.GetDepth()); ASSERT_EQ(2u, if1.GetDexPcAtDepth(0)); ASSERT_EQ(42u, if1.GetMethodIndexAtDepth(0)); @@ -626,36 +638,36 @@ TEST(StackMapTest, InlineTest) { ASSERT_EQ(52u, if1.GetMethodIndexAtDepth(2)); ASSERT_EQ(kVirtual, if1.GetInvokeTypeAtDepth(2)); - DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, 1); - ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci)); + DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, encoding, 1); + ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding)); - DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, 3); - ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci)); - ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci)); - ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci)); + DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, encoding, 3); + ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding)); + ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci, encoding)); + ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci, encoding)); ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(2)); } { // Verify third stack map. - StackMap sm2 = ci.GetStackMapAt(2); + StackMap sm2 = ci.GetStackMapAt(2, encoding); - DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, 2); + DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, encoding, 2); ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0)); - ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci)); - ASSERT_FALSE(sm2.HasInlineInfo(ci)); + ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding)); + ASSERT_FALSE(sm2.HasInlineInfo(encoding)); } { // Verify fourth stack map. - StackMap sm3 = ci.GetStackMapAt(3); + StackMap sm3 = ci.GetStackMapAt(3, encoding); - DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, 2); - ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci)); - ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci)); + DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, encoding, 2); + ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding)); + ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding)); - InlineInfo if2 = ci.GetInlineInfoOf(sm3); + InlineInfo if2 = ci.GetInlineInfoOf(sm3, encoding); ASSERT_EQ(3u, if2.GetDepth()); ASSERT_EQ(2u, if2.GetDexPcAtDepth(0)); ASSERT_EQ(42u, if2.GetMethodIndexAtDepth(0)); @@ -669,12 +681,12 @@ TEST(StackMapTest, InlineTest) { ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(0)); - DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, 1); - ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci)); + DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, encoding, 1); + ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci, encoding)); - DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, 2); + DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, encoding, 2); ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0)); - ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci)); + ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci, encoding)); } } diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index e039d10583..96d5654d65 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -1346,9 +1346,11 @@ class OatDumper { const void* raw_code_info = oat_method.GetVmapTable(); if (raw_code_info != nullptr) { CodeInfo code_info(raw_code_info); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(offset); + StackMapEncoding encoding = code_info.ExtractEncoding(); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(offset, encoding); if (stack_map.IsValid()) { - stack_map.Dump(os, code_info, oat_method.GetCodeOffset(), code_item->registers_size_); + stack_map.Dump( + os, code_info, encoding, oat_method.GetCodeOffset(), code_item->registers_size_); } } } diff --git a/runtime/art_method.cc b/runtime/art_method.cc index 349013cfd0..fe26438eac 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -182,9 +182,10 @@ uint32_t ArtMethod::ToDexPc(const uintptr_t pc, bool abort_on_failure) { uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(entry_point); if (IsOptimized(sizeof(void*))) { CodeInfo code_info = GetOptimizedCodeInfo(); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset); + StackMapEncoding encoding = code_info.ExtractEncoding(); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset, encoding); if (stack_map.IsValid()) { - return stack_map.GetDexPc(code_info); + return stack_map.GetDexPc(encoding); } } else { MappingTable table(entry_point != nullptr ? diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h index d323379e4c..504b7536f6 100644 --- a/runtime/check_reference_map_visitor.h +++ b/runtime/check_reference_map_visitor.h @@ -65,17 +65,18 @@ class CheckReferenceMapVisitor : public StackVisitor { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); CodeInfo code_info = m->GetOptimizedCodeInfo(); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); + StackMapEncoding encoding = code_info.ExtractEncoding(); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); uint16_t number_of_dex_registers = m->GetCodeItem()->registers_size_; DexRegisterMap dex_register_map = - code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers); - MemoryRegion stack_mask = stack_map.GetStackMask(code_info); - uint32_t register_mask = stack_map.GetRegisterMask(code_info); + code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers); + MemoryRegion stack_mask = stack_map.GetStackMask(encoding); + uint32_t register_mask = stack_map.GetRegisterMask(encoding); for (int i = 0; i < number_of_references; ++i) { int reg = registers[i]; CHECK(reg < m->GetCodeItem()->registers_size_); - DexRegisterLocation location = - dex_register_map.GetDexRegisterLocation(reg, number_of_dex_registers, code_info); + DexRegisterLocation location = dex_register_map.GetDexRegisterLocation( + reg, number_of_dex_registers, code_info, encoding); switch (location.GetKind()) { case DexRegisterLocation::Kind::kNone: // Not set, should not be a reference. diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index dbd24a276f..b0cbd02880 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -77,10 +77,11 @@ inline ArtMethod* GetCalleeSaveMethodCaller(ArtMethod** sp, (reinterpret_cast<uint8_t*>(sp) + callee_return_pc_offset)); uintptr_t native_pc_offset = outer_method->NativeQuickPcOffset(caller_pc); CodeInfo code_info = outer_method->GetOptimizedCodeInfo(); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); + StackMapEncoding encoding = code_info.ExtractEncoding(); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); DCHECK(stack_map.IsValid()); - if (stack_map.HasInlineInfo(code_info)) { - InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map); + if (stack_map.HasInlineInfo(encoding)) { + InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding); uint32_t method_index = inline_info.GetMethodIndexAtDepth(inline_info.GetDepth() - 1); InvokeType invoke_type = static_cast<InvokeType>( inline_info.GetInvokeTypeAtDepth(inline_info.GetDepth() - 1)); diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 042c33f7ff..cc83db1e59 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -314,13 +314,14 @@ class QuickArgumentVisitor { if (outer_method->IsOptimized(sizeof(void*))) { CodeInfo code_info = outer_method->GetOptimizedCodeInfo(); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset); + StackMapEncoding encoding = code_info.ExtractEncoding(); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset, encoding); DCHECK(stack_map.IsValid()); - if (stack_map.HasInlineInfo(code_info)) { - InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map); + if (stack_map.HasInlineInfo(encoding)) { + InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding); return inline_info.GetDexPcAtDepth(inline_info.GetDepth() - 1); } else { - return stack_map.GetDexPc(code_info); + return stack_map.GetDexPc(encoding); } } else { return outer_method->ToDexPc(outer_pc); diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 6ab44551d0..cb36183977 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -406,7 +406,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(java_class); ScopedObjectAccess soa(env); mirror::Class* c = soa.Decode<mirror::Class*>(java_class); - return soa.AddLocalReference<jclass>(c->GetSuperClass()); + return soa.AddLocalReference<jclass>(c->IsInterface() ? nullptr : c->GetSuperClass()); } // Note: java_class1 should be safely castable to java_class2, and diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index 99eb365094..2a0cb28f0c 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -1238,7 +1238,7 @@ TEST_F(JniInternalTest, GetSuperclass) { ASSERT_NE(runnable_interface, nullptr); ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class))); ASSERT_EQ(env_->GetSuperclass(object_class), nullptr); - ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface))); + ASSERT_EQ(env_->GetSuperclass(runnable_interface), nullptr); // Null as class should fail. CheckJniAbortCatcher jni_abort_catcher; diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index ba8a693bdb..551e7e290a 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1207,7 +1207,12 @@ class MANAGED Class FINAL : public Object { // Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName HeapReference<String> name_; - // The superclass, or null if this is java.lang.Object, an interface or primitive type. + // The superclass, or null if this is java.lang.Object or a primitive type. + // + // Note that interfaces have java.lang.Object as their + // superclass. This doesn't match the expectations in JNI + // GetSuperClass or java.lang.Class.getSuperClass() which need to + // check for interfaces and return null. HeapReference<Class> super_class_; // If class verify fails, we must return same error on subsequent tries. diff --git a/runtime/stack.cc b/runtime/stack.cc index 411088794a..5aeca98a88 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -113,9 +113,10 @@ InlineInfo StackVisitor::GetCurrentInlineInfo() const { ArtMethod* outer_method = *GetCurrentQuickFrame(); uint32_t native_pc_offset = outer_method->NativeQuickPcOffset(cur_quick_frame_pc_); CodeInfo code_info = outer_method->GetOptimizedCodeInfo(); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); + StackMapEncoding encoding = code_info.ExtractEncoding(); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); DCHECK(stack_map.IsValid()); - return code_info.GetInlineInfoOf(stack_map); + return code_info.GetInlineInfoOf(stack_map, encoding); } ArtMethod* StackVisitor::GetMethod() const { @@ -274,34 +275,40 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin const void* code_pointer = outer_method->GetQuickOatCodePointer(sizeof(void*)); DCHECK(code_pointer != nullptr); CodeInfo code_info = outer_method->GetOptimizedCodeInfo(); + StackMapEncoding encoding = code_info.ExtractEncoding(); uint32_t native_pc_offset = outer_method->NativeQuickPcOffset(cur_quick_frame_pc_); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); DCHECK(stack_map.IsValid()); size_t depth_in_stack_map = current_inlining_depth_ - 1; DexRegisterMap dex_register_map = IsInInlinedFrame() - ? code_info.GetDexRegisterMapAtDepth( - depth_in_stack_map, code_info.GetInlineInfoOf(stack_map), number_of_dex_registers) - : code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers); + ? code_info.GetDexRegisterMapAtDepth(depth_in_stack_map, + code_info.GetInlineInfoOf(stack_map, encoding), + encoding, + number_of_dex_registers) + : code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers); DexRegisterLocation::Kind location_kind = - dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info); + dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info, encoding); switch (location_kind) { case DexRegisterLocation::Kind::kInStack: { - const int32_t offset = - dex_register_map.GetStackOffsetInBytes(vreg, number_of_dex_registers, code_info); + const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg, + number_of_dex_registers, + code_info, + encoding); const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset; *val = *reinterpret_cast<const uint32_t*>(addr); return true; } case DexRegisterLocation::Kind::kInRegister: case DexRegisterLocation::Kind::kInFpuRegister: { - uint32_t reg = dex_register_map.GetMachineRegister(vreg, number_of_dex_registers, code_info); + uint32_t reg = + dex_register_map.GetMachineRegister(vreg, number_of_dex_registers, code_info, encoding); return GetRegisterIfAccessible(reg, kind, val); } case DexRegisterLocation::Kind::kConstant: - *val = dex_register_map.GetConstant(vreg, number_of_dex_registers, code_info); + *val = dex_register_map.GetConstant(vreg, number_of_dex_registers, code_info, encoding); return true; case DexRegisterLocation::Kind::kNone: return false; @@ -309,7 +316,10 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin LOG(FATAL) << "Unexpected location kind" << DexRegisterLocation::PrettyDescriptor( - dex_register_map.GetLocationInternalKind(vreg, number_of_dex_registers, code_info)); + dex_register_map.GetLocationInternalKind(vreg, + number_of_dex_registers, + code_info, + encoding)); UNREACHABLE(); } } @@ -782,10 +792,11 @@ void StackVisitor::WalkStack(bool include_transitions) { if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames) && method->IsOptimized(sizeof(void*))) { CodeInfo code_info = method->GetOptimizedCodeInfo(); + StackMapEncoding encoding = code_info.ExtractEncoding(); uint32_t native_pc_offset = method->NativeQuickPcOffset(cur_quick_frame_pc_); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); - if (stack_map.IsValid() && stack_map.HasInlineInfo(code_info)) { - InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); + if (stack_map.IsValid() && stack_map.HasInlineInfo(encoding)) { + InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding); DCHECK_EQ(current_inlining_depth_, 0u); for (current_inlining_depth_ = inline_info.GetDepth(); current_inlining_depth_ != 0; diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc index a64071ff05..f8fc2a9e90 100644 --- a/runtime/stack_map.cc +++ b/runtime/stack_map.cc @@ -28,9 +28,10 @@ constexpr uint32_t StackMap::kNoInlineInfo; DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(uint16_t dex_register_number, uint16_t number_of_dex_registers, - const CodeInfo& code_info) const { + const CodeInfo& code_info, + const StackMapEncoding& enc) const { DexRegisterLocationCatalog dex_register_location_catalog = - code_info.GetDexRegisterLocationCatalog(); + code_info.GetDexRegisterLocationCatalog(enc); size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( dex_register_number, number_of_dex_registers, @@ -40,9 +41,10 @@ DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(uint16_t dex_r DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number, uint16_t number_of_dex_registers, - const CodeInfo& code_info) const { + const CodeInfo& code_info, + const StackMapEncoding& enc) const { DexRegisterLocationCatalog dex_register_location_catalog = - code_info.GetDexRegisterLocationCatalog(); + code_info.GetDexRegisterLocationCatalog(enc); size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( dex_register_number, number_of_dex_registers, @@ -50,156 +52,43 @@ DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index); } -// Loads `number_of_bytes` at the given `offset` and assemble a uint32_t. If `check_max` is true, -// this method converts a maximum value of size `number_of_bytes` into a uint32_t 0xFFFFFFFF. -static uint32_t LoadAt(MemoryRegion region, - size_t number_of_bytes, - size_t offset, - bool check_max = false) { +uint32_t StackMap::LoadAt(size_t number_of_bytes, size_t offset, bool check_max) const { if (number_of_bytes == 0u) { DCHECK(!check_max); return 0; } else if (number_of_bytes == 1u) { - uint8_t value = region.LoadUnaligned<uint8_t>(offset); - if (check_max && value == 0xFF) { - return -1; - } else { - return value; - } + uint8_t value = region_.LoadUnaligned<uint8_t>(offset); + return (check_max && value == 0xFF) ? -1 : value; } else if (number_of_bytes == 2u) { - uint16_t value = region.LoadUnaligned<uint16_t>(offset); - if (check_max && value == 0xFFFF) { - return -1; - } else { - return value; - } + uint16_t value = region_.LoadUnaligned<uint16_t>(offset); + return (check_max && value == 0xFFFF) ? -1 : value; } else if (number_of_bytes == 3u) { - uint16_t low = region.LoadUnaligned<uint16_t>(offset); - uint16_t high = region.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t)); + uint16_t low = region_.LoadUnaligned<uint16_t>(offset); + uint16_t high = region_.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t)); uint32_t value = (high << 16) + low; - if (check_max && value == 0xFFFFFF) { - return -1; - } else { - return value; - } + return (check_max && value == 0xFFFFFF) ? -1 : value; } else { DCHECK_EQ(number_of_bytes, 4u); - return region.LoadUnaligned<uint32_t>(offset); + return region_.LoadUnaligned<uint32_t>(offset); } } -static void StoreAt(MemoryRegion region, size_t number_of_bytes, size_t offset, uint32_t value) { +void StackMap::StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const { if (number_of_bytes == 0u) { DCHECK_EQ(value, 0u); } else if (number_of_bytes == 1u) { - region.StoreUnaligned<uint8_t>(offset, value); + region_.StoreUnaligned<uint8_t>(offset, value); } else if (number_of_bytes == 2u) { - region.StoreUnaligned<uint16_t>(offset, value); + region_.StoreUnaligned<uint16_t>(offset, value); } else if (number_of_bytes == 3u) { - region.StoreUnaligned<uint16_t>(offset, Low16Bits(value)); - region.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value)); + region_.StoreUnaligned<uint16_t>(offset, Low16Bits(value)); + region_.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value)); } else { - region.StoreUnaligned<uint32_t>(offset, value); + region_.StoreUnaligned<uint32_t>(offset, value); DCHECK_EQ(number_of_bytes, 4u); } } -uint32_t StackMap::GetDexPc(const CodeInfo& info) const { - return LoadAt(region_, info.NumberOfBytesForDexPc(), info.ComputeStackMapDexPcOffset()); -} - -void StackMap::SetDexPc(const CodeInfo& info, uint32_t dex_pc) { - StoreAt(region_, info.NumberOfBytesForDexPc(), info.ComputeStackMapDexPcOffset(), dex_pc); -} - -uint32_t StackMap::GetNativePcOffset(const CodeInfo& info) const { - return LoadAt(region_, info.NumberOfBytesForNativePc(), info.ComputeStackMapNativePcOffset()); -} - -void StackMap::SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset) { - StoreAt(region_, info.NumberOfBytesForNativePc(), info.ComputeStackMapNativePcOffset(), native_pc_offset); -} - -uint32_t StackMap::GetDexRegisterMapOffset(const CodeInfo& info) const { - return LoadAt(region_, - info.NumberOfBytesForDexRegisterMap(), - info.ComputeStackMapDexRegisterMapOffset(), - /* check_max */ true); -} - -void StackMap::SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset) { - StoreAt(region_, - info.NumberOfBytesForDexRegisterMap(), - info.ComputeStackMapDexRegisterMapOffset(), - offset); -} - -uint32_t StackMap::GetInlineDescriptorOffset(const CodeInfo& info) const { - if (!info.HasInlineInfo()) return kNoInlineInfo; - return LoadAt(region_, - info.NumberOfBytesForInlineInfo(), - info.ComputeStackMapInlineInfoOffset(), - /* check_max */ true); -} - -void StackMap::SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset) { - DCHECK(info.HasInlineInfo()); - StoreAt(region_, - info.NumberOfBytesForInlineInfo(), - info.ComputeStackMapInlineInfoOffset(), - offset); -} - -uint32_t StackMap::GetRegisterMask(const CodeInfo& info) const { - return LoadAt(region_, - info.NumberOfBytesForRegisterMask(), - info.ComputeStackMapRegisterMaskOffset()); -} - -void StackMap::SetRegisterMask(const CodeInfo& info, uint32_t mask) { - StoreAt(region_, - info.NumberOfBytesForRegisterMask(), - info.ComputeStackMapRegisterMaskOffset(), - mask); -} - -size_t StackMap::ComputeStackMapSizeInternal(size_t stack_mask_size, - size_t number_of_bytes_for_inline_info, - size_t number_of_bytes_for_dex_map, - size_t number_of_bytes_for_dex_pc, - size_t number_of_bytes_for_native_pc, - size_t number_of_bytes_for_register_mask) { - return stack_mask_size - + number_of_bytes_for_inline_info - + number_of_bytes_for_dex_map - + number_of_bytes_for_dex_pc - + number_of_bytes_for_native_pc - + number_of_bytes_for_register_mask; -} - -size_t StackMap::ComputeStackMapSize(size_t stack_mask_size, - size_t inline_info_size, - size_t dex_register_map_size, - size_t dex_pc_max, - size_t native_pc_max, - size_t register_mask_max) { - return ComputeStackMapSizeInternal( - stack_mask_size, - inline_info_size == 0 - ? 0 - // + 1 to also encode kNoInlineInfo. - : CodeInfo::EncodingSizeInBytes(inline_info_size + dex_register_map_size + 1), - // + 1 to also encode kNoDexRegisterMap. - CodeInfo::EncodingSizeInBytes(dex_register_map_size + 1), - CodeInfo::EncodingSizeInBytes(dex_pc_max), - CodeInfo::EncodingSizeInBytes(native_pc_max), - CodeInfo::EncodingSizeInBytes(register_mask_max)); -} - -MemoryRegion StackMap::GetStackMask(const CodeInfo& info) const { - return region_.Subregion(info.ComputeStackMapStackMaskOffset(), info.GetStackMaskSize()); -} - static void DumpRegisterMapping(std::ostream& os, size_t dex_register_num, DexRegisterLocation location, @@ -216,6 +105,7 @@ void CodeInfo::Dump(std::ostream& os, uint32_t code_offset, uint16_t number_of_dex_registers, bool dump_stack_maps) const { + StackMapEncoding encoding = ExtractEncoding(); uint32_t code_info_size = GetOverallSize(); size_t number_of_stack_maps = GetNumberOfStackMaps(); Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count); @@ -223,21 +113,26 @@ void CodeInfo::Dump(std::ostream& os, indented_os << "Optimized CodeInfo (size=" << code_info_size << ", number_of_dex_registers=" << number_of_dex_registers << ", number_of_stack_maps=" << number_of_stack_maps - << ", has_inline_info=" << HasInlineInfo() - << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo() - << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap() - << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc() - << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc() - << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask() + << ", has_inline_info=" << encoding.HasInlineInfo() + << ", number_of_bytes_for_inline_info=" << encoding.NumberOfBytesForInlineInfo() + << ", number_of_bytes_for_dex_register_map=" + << encoding.NumberOfBytesForDexRegisterMap() + << ", number_of_bytes_for_dex_pc=" << encoding.NumberOfBytesForDexPc() + << ", number_of_bytes_for_native_pc=" << encoding.NumberOfBytesForNativePc() + << ", number_of_bytes_for_register_mask=" << encoding.NumberOfBytesForRegisterMask() << ")\n"; // Display the Dex register location catalog. - GetDexRegisterLocationCatalog().Dump(indented_os, *this); + GetDexRegisterLocationCatalog(encoding).Dump(indented_os, *this); // Display stack maps along with (live) Dex register maps. if (dump_stack_maps) { for (size_t i = 0; i < number_of_stack_maps; ++i) { - StackMap stack_map = GetStackMapAt(i); - stack_map.Dump( - indented_os, *this, code_offset, number_of_dex_registers, " " + std::to_string(i)); + StackMap stack_map = GetStackMapAt(i, encoding); + stack_map.Dump(indented_os, + *this, + encoding, + code_offset, + number_of_dex_registers, + " " + std::to_string(i)); } } // TODO: Dump the stack map's inline information? We need to know more from the caller: @@ -245,9 +140,10 @@ void CodeInfo::Dump(std::ostream& os, } void DexRegisterLocationCatalog::Dump(std::ostream& os, const CodeInfo& code_info) { + StackMapEncoding encoding = code_info.ExtractEncoding(); size_t number_of_location_catalog_entries = code_info.GetNumberOfDexRegisterLocationCatalogEntries(); - size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(); + size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(encoding); Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count); std::ostream indented_os(&indent_filter); indented_os @@ -262,6 +158,7 @@ void DexRegisterLocationCatalog::Dump(std::ostream& os, const CodeInfo& code_inf void DexRegisterMap::Dump(std::ostream& os, const CodeInfo& code_info, uint16_t number_of_dex_registers) const { + StackMapEncoding encoding = code_info.ExtractEncoding(); size_t number_of_location_catalog_entries = code_info.GetNumberOfDexRegisterLocationCatalogEntries(); Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count); @@ -271,7 +168,10 @@ void DexRegisterMap::Dump(std::ostream& os, if (IsDexRegisterLive(j)) { size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( j, number_of_dex_registers, number_of_location_catalog_entries); - DexRegisterLocation location = GetDexRegisterLocation(j, number_of_dex_registers, code_info); + DexRegisterLocation location = GetDexRegisterLocation(j, + number_of_dex_registers, + code_info, + encoding); DumpRegisterMapping( indented_os, j, location, "v", "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]"); @@ -281,6 +181,7 @@ void DexRegisterMap::Dump(std::ostream& os, void StackMap::Dump(std::ostream& os, const CodeInfo& code_info, + const StackMapEncoding& encoding, uint32_t code_offset, uint16_t number_of_dex_registers, const std::string& header_suffix) const { @@ -288,21 +189,22 @@ void StackMap::Dump(std::ostream& os, std::ostream indented_os(&indent_filter); indented_os << "StackMap" << header_suffix << std::hex - << " [native_pc=0x" << code_offset + GetNativePcOffset(code_info) << "]" - << " (dex_pc=0x" << GetDexPc(code_info) - << ", native_pc_offset=0x" << GetNativePcOffset(code_info) - << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(code_info) - << ", inline_info_offset=0x" << GetInlineDescriptorOffset(code_info) - << ", register_mask=0x" << GetRegisterMask(code_info) + << " [native_pc=0x" << code_offset + GetNativePcOffset(encoding) << "]" + << " (dex_pc=0x" << GetDexPc(encoding) + << ", native_pc_offset=0x" << GetNativePcOffset(encoding) + << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(encoding) + << ", inline_info_offset=0x" << GetInlineDescriptorOffset(encoding) + << ", register_mask=0x" << GetRegisterMask(encoding) << std::dec << ", stack_mask=0b"; - MemoryRegion stack_mask = GetStackMask(code_info); + MemoryRegion stack_mask = GetStackMask(encoding); for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) { indented_os << stack_mask.LoadBit(e - i - 1); } indented_os << ")\n"; - if (HasDexRegisterMap(code_info)) { - DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(*this, number_of_dex_registers); + if (HasDexRegisterMap(encoding)) { + DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf( + *this, encoding, number_of_dex_registers); dex_register_map.Dump(os, code_info, number_of_dex_registers); } } @@ -321,8 +223,9 @@ void InlineInfo::Dump(std::ostream& os, << ", method_index=0x" << GetMethodIndexAtDepth(i) << ")\n"; if (HasDexRegisterMapAtDepth(i)) { + StackMapEncoding encoding = code_info.ExtractEncoding(); DexRegisterMap dex_register_map = - code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]); + code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]); dex_register_map.Dump(indented_os, code_info, number_of_dex_registers[i]); } } diff --git a/runtime/stack_map.h b/runtime/stack_map.h index 7f33e6d090..4e420084d1 100644 --- a/runtime/stack_map.h +++ b/runtime/stack_map.h @@ -32,6 +32,7 @@ static constexpr ssize_t kFrameSlotSize = 4; static constexpr size_t kVRegSize = 4; class CodeInfo; +class StackMapEncoding; /** * Classes in the following file are wrapper on stack map information backed @@ -437,26 +438,30 @@ class DexRegisterMap { // Get the surface kind of Dex register `dex_register_number`. DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number, uint16_t number_of_dex_registers, - const CodeInfo& code_info) const { + const CodeInfo& code_info, + const StackMapEncoding& enc) const { return DexRegisterLocation::ConvertToSurfaceKind( - GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info)); + GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info, enc)); } // Get the internal kind of Dex register `dex_register_number`. DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number, uint16_t number_of_dex_registers, - const CodeInfo& code_info) const; + const CodeInfo& code_info, + const StackMapEncoding& enc) const; // Get the Dex register location `dex_register_number`. DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number, uint16_t number_of_dex_registers, - const CodeInfo& code_info) const; + const CodeInfo& code_info, + const StackMapEncoding& enc) const; int32_t GetStackOffsetInBytes(uint16_t dex_register_number, uint16_t number_of_dex_registers, - const CodeInfo& code_info) const { + const CodeInfo& code_info, + const StackMapEncoding& enc) const { DexRegisterLocation location = - GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info); + GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack); // GetDexRegisterLocation returns the offset in bytes. return location.GetValue(); @@ -464,9 +469,10 @@ class DexRegisterMap { int32_t GetConstant(uint16_t dex_register_number, uint16_t number_of_dex_registers, - const CodeInfo& code_info) const { + const CodeInfo& code_info, + const StackMapEncoding& enc) const { DexRegisterLocation location = - GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info); + GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant) << DexRegisterLocation::PrettyDescriptor(location.GetKind()); return location.GetValue(); @@ -474,9 +480,10 @@ class DexRegisterMap { int32_t GetMachineRegister(uint16_t dex_register_number, uint16_t number_of_dex_registers, - const CodeInfo& code_info) const { + const CodeInfo& code_info, + const StackMapEncoding& enc) const { DexRegisterLocation location = - GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info); + GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister) << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind()); @@ -628,6 +635,111 @@ class DexRegisterMap { friend class StackMapStream; }; +class StackMapEncoding { + public: + StackMapEncoding() {} + + StackMapEncoding(size_t stack_mask_size, + size_t bytes_for_inline_info, + size_t bytes_for_dex_register_map, + size_t bytes_for_dex_pc, + size_t bytes_for_native_pc, + size_t bytes_for_register_mask) + : bytes_for_stack_mask_(stack_mask_size), + bytes_for_inline_info_(bytes_for_inline_info), + bytes_for_dex_register_map_(bytes_for_dex_register_map), + bytes_for_dex_pc_(bytes_for_dex_pc), + bytes_for_native_pc_(bytes_for_native_pc), + bytes_for_register_mask_(bytes_for_register_mask) {} + + static StackMapEncoding CreateFromSizes(size_t stack_mask_size, + size_t inline_info_size, + size_t dex_register_map_size, + size_t dex_pc_max, + size_t native_pc_max, + size_t register_mask_max) { + return StackMapEncoding( + stack_mask_size, + // + 1 to also encode kNoInlineInfo: if an inline info offset + // is at 0xFF, we want to overflow to a larger encoding, because it will + // conflict with kNoInlineInfo. + // The offset is relative to the dex register map. TODO: Change this. + inline_info_size == 0 + ? 0 + : EncodingSizeInBytes(dex_register_map_size + inline_info_size + 1), + // + 1 to also encode kNoDexRegisterMap: if a dex register map offset + // is at 0xFF, we want to overflow to a larger encoding, because it will + // conflict with kNoDexRegisterMap. + EncodingSizeInBytes(dex_register_map_size + 1), + EncodingSizeInBytes(dex_pc_max), + EncodingSizeInBytes(native_pc_max), + EncodingSizeInBytes(register_mask_max)); + } + + // Get the size of one stack map of this CodeInfo object, in bytes. + // All stack maps of a CodeInfo have the same size. + size_t ComputeStackMapSize() const { + return bytes_for_register_mask_ + + bytes_for_stack_mask_ + + bytes_for_inline_info_ + + bytes_for_dex_register_map_ + + bytes_for_dex_pc_ + + bytes_for_native_pc_; + } + + bool HasInlineInfo() const { return bytes_for_inline_info_ > 0; } + + size_t NumberOfBytesForStackMask() const { return bytes_for_stack_mask_; } + size_t NumberOfBytesForInlineInfo() const { return bytes_for_inline_info_; } + size_t NumberOfBytesForDexRegisterMap() const { return bytes_for_dex_register_map_; } + size_t NumberOfBytesForDexPc() const { return bytes_for_dex_pc_; } + size_t NumberOfBytesForNativePc() const { return bytes_for_native_pc_; } + size_t NumberOfBytesForRegisterMask() const { return bytes_for_register_mask_; } + + size_t ComputeStackMapRegisterMaskOffset() const { + return kRegisterMaskOffset; + } + + size_t ComputeStackMapStackMaskOffset() const { + return ComputeStackMapRegisterMaskOffset() + bytes_for_register_mask_; + } + + size_t ComputeStackMapDexPcOffset() const { + return ComputeStackMapStackMaskOffset() + bytes_for_stack_mask_; + } + + size_t ComputeStackMapNativePcOffset() const { + return ComputeStackMapDexPcOffset() + bytes_for_dex_pc_; + } + + size_t ComputeStackMapDexRegisterMapOffset() const { + return ComputeStackMapNativePcOffset() + bytes_for_native_pc_; + } + + size_t ComputeStackMapInlineInfoOffset() const { + return ComputeStackMapDexRegisterMapOffset() + bytes_for_dex_register_map_; + } + + private: + static size_t EncodingSizeInBytes(size_t max_element) { + DCHECK(IsUint<32>(max_element)); + return (max_element == 0) ? 0 + : IsUint<8>(max_element) ? 1 + : IsUint<16>(max_element) ? 2 + : IsUint<24>(max_element) ? 3 + : 4; + } + + static constexpr int kRegisterMaskOffset = 0; + + size_t bytes_for_stack_mask_; + size_t bytes_for_inline_info_; + size_t bytes_for_dex_register_map_; + size_t bytes_for_dex_pc_; + size_t bytes_for_native_pc_; + size_t bytes_for_register_mask_; +}; + /** * A Stack Map holds compilation information for a specific PC necessary for: * - Mapping it to a dex PC, @@ -642,44 +754,82 @@ class DexRegisterMap { */ class StackMap { public: - explicit StackMap(MemoryRegion region) : region_(region) {} StackMap() {} + explicit StackMap(MemoryRegion region) : region_(region) {} bool IsValid() const { return region_.pointer() != nullptr; } - uint32_t GetDexPc(const CodeInfo& info) const; + uint32_t GetDexPc(const StackMapEncoding& encoding) const { + return LoadAt(encoding.NumberOfBytesForDexPc(), encoding.ComputeStackMapDexPcOffset()); + } - void SetDexPc(const CodeInfo& info, uint32_t dex_pc); + void SetDexPc(const StackMapEncoding& encoding, uint32_t dex_pc) { + StoreAt(encoding.NumberOfBytesForDexPc(), encoding.ComputeStackMapDexPcOffset(), dex_pc); + } - uint32_t GetNativePcOffset(const CodeInfo& info) const; + uint32_t GetNativePcOffset(const StackMapEncoding& encoding) const { + return LoadAt(encoding.NumberOfBytesForNativePc(), encoding.ComputeStackMapNativePcOffset()); + } - void SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset); + void SetNativePcOffset(const StackMapEncoding& encoding, uint32_t native_pc_offset) { + StoreAt(encoding.NumberOfBytesForNativePc(), + encoding.ComputeStackMapNativePcOffset(), + native_pc_offset); + } - uint32_t GetDexRegisterMapOffset(const CodeInfo& info) const; + uint32_t GetDexRegisterMapOffset(const StackMapEncoding& encoding) const { + return LoadAt(encoding.NumberOfBytesForDexRegisterMap(), + encoding.ComputeStackMapDexRegisterMapOffset(), + /* check_max */ true); + } - void SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset); + void SetDexRegisterMapOffset(const StackMapEncoding& encoding, uint32_t offset) { + StoreAt(encoding.NumberOfBytesForDexRegisterMap(), + encoding.ComputeStackMapDexRegisterMapOffset(), + offset); + } - uint32_t GetInlineDescriptorOffset(const CodeInfo& info) const; + uint32_t GetInlineDescriptorOffset(const StackMapEncoding& encoding) const { + if (!encoding.HasInlineInfo()) return kNoInlineInfo; + return LoadAt(encoding.NumberOfBytesForInlineInfo(), + encoding.ComputeStackMapInlineInfoOffset(), + /* check_max */ true); + } - void SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset); + void SetInlineDescriptorOffset(const StackMapEncoding& encoding, uint32_t offset) { + DCHECK(encoding.HasInlineInfo()); + StoreAt(encoding.NumberOfBytesForInlineInfo(), + encoding.ComputeStackMapInlineInfoOffset(), + offset); + } - uint32_t GetRegisterMask(const CodeInfo& info) const; + uint32_t GetRegisterMask(const StackMapEncoding& encoding) const { + return LoadAt(encoding.NumberOfBytesForRegisterMask(), + encoding.ComputeStackMapRegisterMaskOffset()); + } - void SetRegisterMask(const CodeInfo& info, uint32_t mask); + void SetRegisterMask(const StackMapEncoding& encoding, uint32_t mask) { + StoreAt(encoding.NumberOfBytesForRegisterMask(), + encoding.ComputeStackMapRegisterMaskOffset(), + mask); + } - MemoryRegion GetStackMask(const CodeInfo& info) const; + MemoryRegion GetStackMask(const StackMapEncoding& encoding) const { + return region_.Subregion(encoding.ComputeStackMapStackMaskOffset(), + encoding.NumberOfBytesForStackMask()); + } - void SetStackMask(const CodeInfo& info, const BitVector& sp_map) { - MemoryRegion region = GetStackMask(info); + void SetStackMask(const StackMapEncoding& encoding, const BitVector& sp_map) { + MemoryRegion region = GetStackMask(encoding); sp_map.CopyTo(region.start(), region.size()); } - bool HasDexRegisterMap(const CodeInfo& info) const { - return GetDexRegisterMapOffset(info) != kNoDexRegisterMap; + bool HasDexRegisterMap(const StackMapEncoding& encoding) const { + return GetDexRegisterMapOffset(encoding) != kNoDexRegisterMap; } - bool HasInlineInfo(const CodeInfo& info) const { - return GetInlineDescriptorOffset(info) != kNoInlineInfo; + bool HasInlineInfo(const StackMapEncoding& encoding) const { + return GetInlineDescriptorOffset(encoding) != kNoInlineInfo; } bool Equals(const StackMap& other) const { @@ -687,15 +837,9 @@ class StackMap { && region_.size() == other.region_.size(); } - static size_t ComputeStackMapSize(size_t stack_mask_size, - size_t inline_info_size, - size_t dex_register_map_size, - size_t dex_pc_max, - size_t native_pc_max, - size_t register_mask_max); - void Dump(std::ostream& os, const CodeInfo& code_info, + const StackMapEncoding& encoding, uint32_t code_offset, uint16_t number_of_dex_registers, const std::string& header_suffix = "") const; @@ -709,21 +853,17 @@ class StackMap { static constexpr uint32_t kNoInlineInfo = -1; private: - static size_t ComputeStackMapSizeInternal(size_t stack_mask_size, - size_t number_of_bytes_for_inline_info, - size_t number_of_bytes_for_dex_map, - size_t number_of_bytes_for_dex_pc, - size_t number_of_bytes_for_native_pc, - size_t number_of_bytes_for_register_mask); - // TODO: Instead of plain types such as "uint32_t", introduce // typedefs (and document the memory layout of StackMap). - static constexpr int kRegisterMaskOffset = 0; static constexpr int kFixedSize = 0; + // Loads `number_of_bytes` at the given `offset` and assemble a uint32_t. If `check_max` is true, + // this method converts a maximum value of size `number_of_bytes` into a uint32_t 0xFFFFFFFF. + uint32_t LoadAt(size_t number_of_bytes, size_t offset, bool check_max = false) const; + void StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const; + MemoryRegion region_; - friend class CodeInfo; friend class StackMapStream; }; @@ -827,39 +967,23 @@ class CodeInfo { region_ = MemoryRegion(const_cast<void*>(data), size); } - static size_t EncodingSizeInBytes(size_t max_element) { - DCHECK(IsUint<32>(max_element)); - return (max_element == 0) ? 0 - : IsUint<8>(max_element) ? 1 - : IsUint<16>(max_element) ? 2 - : IsUint<24>(max_element) ? 3 - : 4; + StackMapEncoding ExtractEncoding() const { + return StackMapEncoding(region_.LoadUnaligned<uint32_t>(kStackMaskSizeOffset), + GetNumberOfBytesForEncoding(kInlineInfoBitOffset), + GetNumberOfBytesForEncoding(kDexRegisterMapBitOffset), + GetNumberOfBytesForEncoding(kDexPcBitOffset), + GetNumberOfBytesForEncoding(kNativePcBitOffset), + GetNumberOfBytesForEncoding(kRegisterMaskBitOffset)); } - void SetEncoding(size_t inline_info_size, - size_t dex_register_map_size, - size_t dex_pc_max, - size_t native_pc_max, - size_t register_mask_max) { - if (inline_info_size != 0) { - region_.StoreBit(kHasInlineInfoBitOffset, 1); - // + 1 to also encode kNoInlineInfo: if an inline info offset - // is at 0xFF, we want to overflow to a larger encoding, because it will - // conflict with kNoInlineInfo. - // The offset is relative to the dex register map. TODO: Change this. - SetEncodingAt(kInlineInfoBitOffset, - EncodingSizeInBytes(dex_register_map_size + inline_info_size + 1)); - } else { - region_.StoreBit(kHasInlineInfoBitOffset, 0); - SetEncodingAt(kInlineInfoBitOffset, 0); - } - // + 1 to also encode kNoDexRegisterMap: if a dex register map offset - // is at 0xFF, we want to overflow to a larger encoding, because it will - // conflict with kNoDexRegisterMap. - SetEncodingAt(kDexRegisterMapBitOffset, EncodingSizeInBytes(dex_register_map_size + 1)); - SetEncodingAt(kDexPcBitOffset, EncodingSizeInBytes(dex_pc_max)); - SetEncodingAt(kNativePcBitOffset, EncodingSizeInBytes(native_pc_max)); - SetEncodingAt(kRegisterMaskBitOffset, EncodingSizeInBytes(register_mask_max)); + void SetEncoding(const StackMapEncoding& encoding) { + region_.StoreUnaligned<uint32_t>(kStackMaskSizeOffset, encoding.NumberOfBytesForStackMask()); + region_.StoreBit(kHasInlineInfoBitOffset, encoding.NumberOfBytesForInlineInfo() != 0); + SetEncodingAt(kInlineInfoBitOffset, encoding.NumberOfBytesForInlineInfo()); + SetEncodingAt(kDexRegisterMapBitOffset, encoding.NumberOfBytesForDexRegisterMap()); + SetEncodingAt(kDexPcBitOffset, encoding.NumberOfBytesForDexPc()); + SetEncodingAt(kNativePcBitOffset, encoding.NumberOfBytesForNativePc()); + SetEncodingAt(kRegisterMaskBitOffset, encoding.NumberOfBytesForRegisterMask()); } void SetEncodingAt(size_t bit_offset, size_t number_of_bytes) { @@ -880,64 +1004,15 @@ class CodeInfo { return region_.LoadBit(kHasInlineInfoBitOffset); } - size_t NumberOfBytesForInlineInfo() const { - return GetNumberOfBytesForEncoding(kInlineInfoBitOffset); - } - - size_t NumberOfBytesForDexRegisterMap() const { - return GetNumberOfBytesForEncoding(kDexRegisterMapBitOffset); - } - - size_t NumberOfBytesForRegisterMask() const { - return GetNumberOfBytesForEncoding(kRegisterMaskBitOffset); - } - - size_t NumberOfBytesForNativePc() const { - return GetNumberOfBytesForEncoding(kNativePcBitOffset); - } - - size_t NumberOfBytesForDexPc() const { - return GetNumberOfBytesForEncoding(kDexPcBitOffset); - } - - size_t ComputeStackMapRegisterMaskOffset() const { - return StackMap::kRegisterMaskOffset; - } - - size_t ComputeStackMapStackMaskOffset() const { - return ComputeStackMapRegisterMaskOffset() - + (NumberOfBytesForRegisterMask() * sizeof(uint8_t)); - } - - size_t ComputeStackMapDexPcOffset() const { - return ComputeStackMapStackMaskOffset() + GetStackMaskSize(); - } - - size_t ComputeStackMapNativePcOffset() const { - return ComputeStackMapDexPcOffset() - + (NumberOfBytesForDexPc() * sizeof(uint8_t)); - } - - size_t ComputeStackMapDexRegisterMapOffset() const { - return ComputeStackMapNativePcOffset() - + (NumberOfBytesForNativePc() * sizeof(uint8_t)); - } - - size_t ComputeStackMapInlineInfoOffset() const { - CHECK(HasInlineInfo()); - return ComputeStackMapDexRegisterMapOffset() - + (NumberOfBytesForDexRegisterMap() * sizeof(uint8_t)); - } - - DexRegisterLocationCatalog GetDexRegisterLocationCatalog() const { + DexRegisterLocationCatalog GetDexRegisterLocationCatalog(const StackMapEncoding& encoding) const { return DexRegisterLocationCatalog(region_.Subregion( - GetDexRegisterLocationCatalogOffset(), - GetDexRegisterLocationCatalogSize())); + GetDexRegisterLocationCatalogOffset(encoding), + GetDexRegisterLocationCatalogSize(encoding))); } - StackMap GetStackMapAt(size_t i) const { - size_t size = StackMapSize(); - return StackMap(GetStackMaps().Subregion(i * size, size)); + StackMap GetStackMapAt(size_t i, const StackMapEncoding& encoding) const { + size_t stack_map_size = encoding.ComputeStackMapSize(); + return StackMap(GetStackMaps(encoding).Subregion(i * stack_map_size, stack_map_size)); } uint32_t GetOverallSize() const { @@ -956,19 +1031,11 @@ class CodeInfo { region_.StoreUnaligned<uint32_t>(kNumberOfDexRegisterLocationCatalogEntriesOffset, num_entries); } - uint32_t GetDexRegisterLocationCatalogSize() const { - return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(), + uint32_t GetDexRegisterLocationCatalogSize(const StackMapEncoding& encoding) const { + return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(encoding), GetNumberOfDexRegisterLocationCatalogEntries()); } - uint32_t GetStackMaskSize() const { - return region_.LoadUnaligned<uint32_t>(kStackMaskSizeOffset); - } - - void SetStackMaskSize(uint32_t size) { - region_.StoreUnaligned<uint32_t>(kStackMaskSizeOffset, size); - } - size_t GetNumberOfStackMaps() const { return region_.LoadUnaligned<uint32_t>(kNumberOfStackMapsOffset); } @@ -977,37 +1044,30 @@ class CodeInfo { region_.StoreUnaligned<uint32_t>(kNumberOfStackMapsOffset, number_of_stack_maps); } - // Get the size of one stack map of this CodeInfo object, in bytes. - // All stack maps of a CodeInfo have the same size. - size_t StackMapSize() const { - return StackMap::ComputeStackMapSizeInternal(GetStackMaskSize(), - NumberOfBytesForInlineInfo(), - NumberOfBytesForDexRegisterMap(), - NumberOfBytesForDexPc(), - NumberOfBytesForNativePc(), - NumberOfBytesForRegisterMask()); - } - // Get the size all the stack maps of this CodeInfo object, in bytes. - size_t GetStackMapsSize() const { - return StackMapSize() * GetNumberOfStackMaps(); + size_t GetStackMapsSize(const StackMapEncoding& encoding) const { + return encoding.ComputeStackMapSize() * GetNumberOfStackMaps(); } - uint32_t GetDexRegisterLocationCatalogOffset() const { - return GetStackMapsOffset() + GetStackMapsSize(); + uint32_t GetDexRegisterLocationCatalogOffset(const StackMapEncoding& encoding) const { + return GetStackMapsOffset() + GetStackMapsSize(encoding); } - size_t GetDexRegisterMapsOffset() const { - return GetDexRegisterLocationCatalogOffset() + GetDexRegisterLocationCatalogSize(); + size_t GetDexRegisterMapsOffset(const StackMapEncoding& encoding) const { + return GetDexRegisterLocationCatalogOffset(encoding) + + GetDexRegisterLocationCatalogSize(encoding); } uint32_t GetStackMapsOffset() const { return kFixedSize; } - DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const { - DCHECK(stack_map.HasDexRegisterMap(*this)); - uint32_t offset = GetDexRegisterMapsOffset() + stack_map.GetDexRegisterMapOffset(*this); + DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, + const StackMapEncoding& encoding, + uint32_t number_of_dex_registers) const { + DCHECK(stack_map.HasDexRegisterMap(encoding)); + uint32_t offset = GetDexRegisterMapsOffset(encoding) + + stack_map.GetDexRegisterMapOffset(encoding); size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers); return DexRegisterMap(region_.Subregion(offset, size)); } @@ -1015,37 +1075,40 @@ class CodeInfo { // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`. DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth, InlineInfo inline_info, + const StackMapEncoding& encoding, uint32_t number_of_dex_registers) const { DCHECK(inline_info.HasDexRegisterMapAtDepth(depth)); - uint32_t offset = - GetDexRegisterMapsOffset() + inline_info.GetDexRegisterMapOffsetAtDepth(depth); + uint32_t offset = GetDexRegisterMapsOffset(encoding) + + inline_info.GetDexRegisterMapOffsetAtDepth(depth); size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers); return DexRegisterMap(region_.Subregion(offset, size)); } - InlineInfo GetInlineInfoOf(StackMap stack_map) const { - DCHECK(stack_map.HasInlineInfo(*this)); - uint32_t offset = stack_map.GetInlineDescriptorOffset(*this) + GetDexRegisterMapsOffset(); + InlineInfo GetInlineInfoOf(StackMap stack_map, const StackMapEncoding& encoding) const { + DCHECK(stack_map.HasInlineInfo(encoding)); + uint32_t offset = stack_map.GetInlineDescriptorOffset(encoding) + + GetDexRegisterMapsOffset(encoding); uint8_t depth = region_.LoadUnaligned<uint8_t>(offset); return InlineInfo(region_.Subregion(offset, InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize())); } - StackMap GetStackMapForDexPc(uint32_t dex_pc) const { + StackMap GetStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const { for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { - StackMap stack_map = GetStackMapAt(i); - if (stack_map.GetDexPc(*this) == dex_pc) { + StackMap stack_map = GetStackMapAt(i, encoding); + if (stack_map.GetDexPc(encoding) == dex_pc) { return stack_map; } } return StackMap(); } - StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const { + StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset, + const StackMapEncoding& encoding) 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); - if (stack_map.GetNativePcOffset(*this) == native_pc_offset) { + StackMap stack_map = GetStackMapAt(i, encoding); + if (stack_map.GetNativePcOffset(encoding) == native_pc_offset) { return stack_map; } } @@ -1081,10 +1144,10 @@ class CodeInfo { static constexpr int kNativePcBitOffset = kDexPcBitOffset + 3; static constexpr int kRegisterMaskBitOffset = kNativePcBitOffset + 3; - MemoryRegion GetStackMaps() const { + MemoryRegion GetStackMaps(const StackMapEncoding& encoding) const { return region_.size() == 0 ? MemoryRegion() - : region_.Subregion(GetStackMapsOffset(), GetStackMapsSize()); + : region_.Subregion(GetStackMapsOffset(), GetStackMapsSize(encoding)); } // Compute the size of the Dex register map associated to the stack map at diff --git a/runtime/thread.cc b/runtime/thread.cc index 67f611e422..4203b96f24 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -2273,9 +2273,10 @@ class ReferenceMapVisitor : public StackVisitor { const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(m, sizeof(void*)); uintptr_t native_pc_offset = m->NativeQuickPcOffset(GetCurrentQuickFramePc(), entry_point); CodeInfo code_info = m->GetOptimizedCodeInfo(); - StackMap map = code_info.GetStackMapForNativePcOffset(native_pc_offset); + StackMapEncoding encoding = code_info.ExtractEncoding(); + StackMap map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); DCHECK(map.IsValid()); - MemoryRegion mask = map.GetStackMask(code_info); + MemoryRegion mask = map.GetStackMask(encoding); // Visit stack entries that hold pointers. for (size_t i = 0; i < mask.size_in_bits(); ++i) { if (mask.LoadBit(i)) { @@ -2291,7 +2292,7 @@ class ReferenceMapVisitor : public StackVisitor { } } // Visit callee-save registers that hold pointers. - uint32_t register_mask = map.GetRegisterMask(code_info); + uint32_t register_mask = map.GetRegisterMask(encoding); for (size_t i = 0; i < BitSizeOf<uint32_t>(); ++i) { if (register_mask & (1 << i)) { mirror::Object** ref_addr = reinterpret_cast<mirror::Object**>(GetGPRAddress(i)); |