summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/debug/elf_debug_info_writer.h7
-rw-r--r--compiler/debug/elf_debug_line_writer.h13
-rw-r--r--compiler/debug/elf_debug_loc_writer.h17
-rw-r--r--compiler/optimizing/code_generator.cc3
-rw-r--r--compiler/optimizing/code_generator.h1
-rw-r--r--compiler/optimizing/stack_map_stream.cc395
-rw-r--r--compiler/optimizing/stack_map_stream.h41
-rw-r--r--compiler/optimizing/stack_map_test.cc545
-rw-r--r--libartbase/Android.bp1
-rw-r--r--libartbase/base/bit_memory_region.h13
-rw-r--r--libartbase/base/bit_table.h220
-rw-r--r--libartbase/base/bit_table_test.cc117
-rw-r--r--oatdump/oatdump.cc93
-rw-r--r--oatdump/oatdump_test.h1
-rw-r--r--runtime/check_reference_map_visitor.h13
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h15
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc12
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc47
-rw-r--r--runtime/jit/jit.cc14
-rw-r--r--runtime/oat.h4
-rw-r--r--runtime/oat_quick_method_header.cc17
-rw-r--r--runtime/oat_quick_method_header.h5
-rw-r--r--runtime/quick_exception_handler.cc47
-rw-r--r--runtime/stack.cc58
-rw-r--r--runtime/stack_map.cc113
-rw-r--r--runtime/stack_map.h997
-rw-r--r--runtime/thread.cc20
-rw-r--r--test/566-polymorphic-inlining/polymorphic_inline.cc5
-rw-r--r--test/knownfailures.json6
-rwxr-xr-xtools/run-jdwp-tests.sh4
30 files changed, 1196 insertions, 1648 deletions
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index 893cad288b..87e679fbea 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -207,11 +207,10 @@ class ElfCompilationUnitWriter {
std::vector<DexRegisterMap> dex_reg_maps;
if (accessor.HasCodeItem() && mi->code_info != nullptr) {
const CodeInfo code_info(mi->code_info);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- for (size_t s = 0; s < code_info.GetNumberOfStackMaps(encoding); ++s) {
- const StackMap& stack_map = code_info.GetStackMapAt(s, encoding);
+ for (size_t s = 0; s < code_info.GetNumberOfStackMaps(); ++s) {
+ const StackMap stack_map = code_info.GetStackMapAt(s);
dex_reg_maps.push_back(code_info.GetDexRegisterMapOf(
- stack_map, encoding, accessor.RegistersSize()));
+ stack_map, accessor.RegistersSize()));
}
}
diff --git a/compiler/debug/elf_debug_line_writer.h b/compiler/debug/elf_debug_line_writer.h
index 44504c1efb..a7adab5506 100644
--- a/compiler/debug/elf_debug_line_writer.h
+++ b/compiler/debug/elf_debug_line_writer.h
@@ -100,15 +100,14 @@ class ElfDebugLineWriter {
if (mi->code_info != nullptr) {
// Use stack maps to create mapping table from pc to dex.
const CodeInfo code_info(mi->code_info);
- const CodeInfoEncoding encoding = code_info.ExtractEncoding();
- pc2dex_map.reserve(code_info.GetNumberOfStackMaps(encoding));
- for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(encoding); s++) {
- StackMap stack_map = code_info.GetStackMapAt(s, encoding);
+ pc2dex_map.reserve(code_info.GetNumberOfStackMaps());
+ for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(); s++) {
+ StackMap stack_map = code_info.GetStackMapAt(s);
DCHECK(stack_map.IsValid());
- const uint32_t pc = stack_map.GetNativePcOffset(encoding.stack_map.encoding, isa);
- const int32_t dex = stack_map.GetDexPc(encoding.stack_map.encoding);
+ const uint32_t pc = stack_map.GetNativePcOffset(isa);
+ const int32_t dex = stack_map.GetDexPc();
pc2dex_map.push_back({pc, dex});
- if (stack_map.HasDexRegisterMap(encoding.stack_map.encoding)) {
+ if (stack_map.HasDexRegisterMap()) {
// Guess that the first map with local variables is the end of prologue.
prologue_end = std::min(prologue_end, pc);
}
diff --git a/compiler/debug/elf_debug_loc_writer.h b/compiler/debug/elf_debug_loc_writer.h
index 9ea9f01cd9..c1bf915212 100644
--- a/compiler/debug/elf_debug_loc_writer.h
+++ b/compiler/debug/elf_debug_loc_writer.h
@@ -99,12 +99,11 @@ static std::vector<VariableLocation> GetVariableLocations(
// Get stack maps sorted by pc (they might not be sorted internally).
// TODO(dsrbecky) Remove this once stackmaps get sorted by pc.
const CodeInfo code_info(method_info->code_info);
- const CodeInfoEncoding encoding = code_info.ExtractEncoding();
std::map<uint32_t, uint32_t> stack_maps; // low_pc -> stack_map_index.
- for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(encoding); s++) {
- StackMap stack_map = code_info.GetStackMapAt(s, encoding);
+ for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(); s++) {
+ StackMap stack_map = code_info.GetStackMapAt(s);
DCHECK(stack_map.IsValid());
- if (!stack_map.HasDexRegisterMap(encoding.stack_map.encoding)) {
+ if (!stack_map.HasDexRegisterMap()) {
// The compiler creates stackmaps without register maps at the start of
// basic blocks in order to keep instruction-accurate line number mapping.
// However, we never stop at those (breakpoint locations always have map).
@@ -112,7 +111,7 @@ static std::vector<VariableLocation> GetVariableLocations(
// The main reason for this is to save space by avoiding undefined gaps.
continue;
}
- const uint32_t pc_offset = stack_map.GetNativePcOffset(encoding.stack_map.encoding, isa);
+ const uint32_t pc_offset = stack_map.GetNativePcOffset(isa);
DCHECK_LE(pc_offset, method_info->code_size);
DCHECK_LE(compilation_unit_code_address, method_info->code_address);
const uint32_t low_pc = dchecked_integral_cast<uint32_t>(
@@ -124,7 +123,7 @@ static std::vector<VariableLocation> GetVariableLocations(
for (auto it = stack_maps.begin(); it != stack_maps.end(); it++) {
const uint32_t low_pc = it->first;
const uint32_t stack_map_index = it->second;
- const StackMap& stack_map = code_info.GetStackMapAt(stack_map_index, encoding);
+ const StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
auto next_it = it;
next_it++;
const uint32_t high_pc = next_it != stack_maps.end()
@@ -136,7 +135,7 @@ static std::vector<VariableLocation> GetVariableLocations(
}
// Check that the stack map is in the requested range.
- uint32_t dex_pc = stack_map.GetDexPc(encoding.stack_map.encoding);
+ uint32_t dex_pc = stack_map.GetDexPc();
if (!(dex_pc_low <= dex_pc && dex_pc < dex_pc_high)) {
// The variable is not in scope at this PC. Therefore omit the entry.
// Note that this is different to None() entry which means in scope, but unknown location.
@@ -151,10 +150,10 @@ static std::vector<VariableLocation> GetVariableLocations(
DCHECK(dex_register_map.IsValid());
CodeItemDataAccessor accessor(*method_info->dex_file, method_info->code_item);
reg_lo = dex_register_map.GetDexRegisterLocation(
- vreg, accessor.RegistersSize(), code_info, encoding);
+ vreg, accessor.RegistersSize(), code_info);
if (is64bitValue) {
reg_hi = dex_register_map.GetDexRegisterLocation(
- vreg + 1, accessor.RegistersSize(), code_info, encoding);
+ vreg + 1, accessor.RegistersSize(), code_info);
}
// Add location entry for this address range.
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index fb556f435a..de1be5b871 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -975,11 +975,10 @@ static void CheckCovers(uint32_t dex_pc,
const CodeInfo& code_info,
const ArenaVector<HSuspendCheck*>& loop_headers,
ArenaVector<size_t>* covered) {
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
for (size_t i = 0; i < loop_headers.size(); ++i) {
if (loop_headers[i]->GetDexPc() == dex_pc) {
if (graph.IsCompilingOsr()) {
- DCHECK(code_info.GetOsrStackMapForDexPc(dex_pc, encoding).IsValid());
+ DCHECK(code_info.GetOsrStackMapForDexPc(dex_pc).IsValid());
}
++(*covered)[i];
}
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index bcb25997f4..a340446ac3 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -35,7 +35,6 @@
#include "optimizing_compiler_stats.h"
#include "read_barrier_option.h"
#include "stack.h"
-#include "stack_map.h"
#include "utils/label.h"
namespace art {
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index bf7c5542ef..aa28c8b500 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -51,15 +51,7 @@ void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
if (sp_mask != nullptr) {
stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
}
- if (inlining_depth > 0) {
- number_of_stack_maps_with_inline_info_++;
- }
- // Note: dex_pc can be kNoDexPc for native method intrinsics.
- if (dex_pc != dex::kDexNoIndex && (dex_pc_max_ == dex::kDexNoIndex || dex_pc_max_ < dex_pc)) {
- dex_pc_max_ = dex_pc;
- }
- register_mask_max_ = std::max(register_mask_max_, register_mask);
current_dex_register_ = 0;
}
@@ -146,51 +138,6 @@ void StackMapStream::EndInlineInfoEntry() {
current_inline_info_ = InlineInfoEntry();
}
-CodeOffset StackMapStream::ComputeMaxNativePcCodeOffset() const {
- CodeOffset max_native_pc_offset;
- for (const StackMapEntry& entry : stack_maps_) {
- max_native_pc_offset = std::max(max_native_pc_offset, entry.native_pc_code_offset);
- }
- return max_native_pc_offset;
-}
-
-size_t StackMapStream::PrepareForFillIn() {
- CodeInfoEncoding encoding;
- encoding.dex_register_map.num_entries = 0; // TODO: Remove this field.
- encoding.dex_register_map.num_bytes = ComputeDexRegisterMapsSize();
- encoding.location_catalog.num_entries = location_catalog_entries_.size();
- encoding.location_catalog.num_bytes = ComputeDexRegisterLocationCatalogSize();
- encoding.inline_info.num_entries = inline_infos_.size();
- // Must be done before calling ComputeInlineInfoEncoding since ComputeInlineInfoEncoding requires
- // dex_method_index_idx to be filled in.
- PrepareMethodIndices();
- ComputeInlineInfoEncoding(&encoding.inline_info.encoding,
- encoding.dex_register_map.num_bytes);
- CodeOffset max_native_pc_offset = ComputeMaxNativePcCodeOffset();
- // Prepare the CodeInfo variable-sized encoding.
- encoding.stack_mask.encoding.num_bits = stack_mask_max_ + 1; // Need room for max element too.
- encoding.stack_mask.num_entries = PrepareStackMasks(encoding.stack_mask.encoding.num_bits);
- encoding.register_mask.encoding.num_bits = MinimumBitsToStore(register_mask_max_);
- encoding.register_mask.num_entries = PrepareRegisterMasks();
- encoding.stack_map.num_entries = stack_maps_.size();
- encoding.stack_map.encoding.SetFromSizes(
- // The stack map contains compressed native PC offsets.
- max_native_pc_offset.CompressedValue(),
- dex_pc_max_,
- encoding.dex_register_map.num_bytes,
- encoding.inline_info.num_entries,
- encoding.register_mask.num_entries,
- encoding.stack_mask.num_entries);
- ComputeInvokeInfoEncoding(&encoding);
- DCHECK_EQ(code_info_encoding_.size(), 0u);
- encoding.Compress(&code_info_encoding_);
- encoding.ComputeTableOffsets();
- // Compute table offsets so we can get the non header size.
- DCHECK_EQ(encoding.HeaderSize(), code_info_encoding_.size());
- needed_size_ = code_info_encoding_.size() + encoding.NonHeaderSize();
- return needed_size_;
-}
-
size_t StackMapStream::ComputeDexRegisterLocationCatalogSize() const {
size_t size = DexRegisterLocationCatalog::kFixedSize;
for (const DexRegisterLocation& dex_register_location : location_catalog_entries_) {
@@ -204,6 +151,10 @@ size_t StackMapStream::DexRegisterMapEntry::ComputeSize(size_t catalog_size) con
if (num_dex_registers == 0u) {
return 0u; // No register map will be emitted.
}
+ size_t number_of_live_dex_registers = live_dex_registers_mask->NumSetBits();
+ if (live_dex_registers_mask->NumSetBits() == 0) {
+ return 0u; // No register map will be emitted.
+ }
DCHECK(live_dex_registers_mask != nullptr);
// Size of the map in bytes.
@@ -211,7 +162,6 @@ size_t StackMapStream::DexRegisterMapEntry::ComputeSize(size_t catalog_size) con
// Add the live bit mask for the Dex register liveness.
size += DexRegisterMap::GetLiveBitMaskSize(num_dex_registers);
// Compute the size of the set of live Dex register entries.
- size_t number_of_live_dex_registers = live_dex_registers_mask->NumSetBits();
size_t map_entries_size_in_bits =
DexRegisterMap::SingleEntrySizeInBits(catalog_size) * number_of_live_dex_registers;
size_t map_entries_size_in_bytes =
@@ -220,86 +170,6 @@ size_t StackMapStream::DexRegisterMapEntry::ComputeSize(size_t catalog_size) con
return size;
}
-size_t StackMapStream::ComputeDexRegisterMapsSize() const {
- size_t size = 0;
- for (const DexRegisterMapEntry& entry : dex_register_entries_) {
- size += entry.ComputeSize(location_catalog_entries_.size());
- }
- return size;
-}
-
-void StackMapStream::ComputeInvokeInfoEncoding(CodeInfoEncoding* encoding) {
- DCHECK(encoding != nullptr);
- uint32_t native_pc_max = 0;
- uint16_t method_index_max = 0;
- size_t invoke_infos_count = 0;
- size_t invoke_type_max = 0;
- for (const StackMapEntry& entry : stack_maps_) {
- if (entry.dex_method_index != dex::kDexNoIndex) {
- native_pc_max = std::max(native_pc_max, entry.native_pc_code_offset.CompressedValue());
- method_index_max = std::max(method_index_max, static_cast<uint16_t>(entry.dex_method_index));
- invoke_type_max = std::max(invoke_type_max, static_cast<size_t>(entry.invoke_type));
- ++invoke_infos_count;
- }
- }
- encoding->invoke_info.num_entries = invoke_infos_count;
- encoding->invoke_info.encoding.SetFromSizes(native_pc_max, invoke_type_max, method_index_max);
-}
-
-void StackMapStream::ComputeInlineInfoEncoding(InlineInfoEncoding* encoding,
- size_t dex_register_maps_bytes) {
- uint32_t method_index_max = 0;
- uint32_t dex_pc_max = dex::kDexNoIndex;
- uint32_t extra_data_max = 0;
-
- uint32_t inline_info_index = 0;
- for (const StackMapEntry& entry : stack_maps_) {
- for (size_t j = 0; j < entry.inlining_depth; ++j) {
- InlineInfoEntry inline_entry = inline_infos_[inline_info_index++];
- if (inline_entry.method == nullptr) {
- method_index_max = std::max(method_index_max, inline_entry.dex_method_index_idx);
- extra_data_max = std::max(extra_data_max, 1u);
- } else {
- method_index_max = std::max(
- method_index_max, High32Bits(reinterpret_cast<uintptr_t>(inline_entry.method)));
- extra_data_max = std::max(
- extra_data_max, Low32Bits(reinterpret_cast<uintptr_t>(inline_entry.method)));
- }
- if (inline_entry.dex_pc != dex::kDexNoIndex &&
- (dex_pc_max == dex::kDexNoIndex || dex_pc_max < inline_entry.dex_pc)) {
- dex_pc_max = inline_entry.dex_pc;
- }
- }
- }
- DCHECK_EQ(inline_info_index, inline_infos_.size());
-
- encoding->SetFromSizes(method_index_max, dex_pc_max, extra_data_max, dex_register_maps_bytes);
-}
-
-size_t StackMapStream::MaybeCopyDexRegisterMap(DexRegisterMapEntry& entry,
- size_t* current_offset,
- MemoryRegion dex_register_locations_region) {
- DCHECK(current_offset != nullptr);
- if ((entry.num_dex_registers == 0) || (entry.live_dex_registers_mask->NumSetBits() == 0)) {
- // No dex register map needed.
- return StackMap::kNoDexRegisterMap;
- }
- if (entry.offset == DexRegisterMapEntry::kOffsetUnassigned) {
- // Not already copied, need to copy and and assign an offset.
- entry.offset = *current_offset;
- const size_t entry_size = entry.ComputeSize(location_catalog_entries_.size());
- DexRegisterMap dex_register_map(
- dex_register_locations_region.Subregion(entry.offset, entry_size));
- *current_offset += entry_size;
- // Fill in the map since it was just added.
- FillInDexRegisterMap(dex_register_map,
- entry.num_dex_registers,
- *entry.live_dex_registers_mask,
- entry.locations_start_index);
- }
- return entry.offset;
-}
-
void StackMapStream::FillInMethodInfo(MemoryRegion region) {
{
MethodInfo info(region.begin(), method_indices_.size());
@@ -318,30 +188,64 @@ void StackMapStream::FillInMethodInfo(MemoryRegion region) {
}
}
-void StackMapStream::FillInCodeInfo(MemoryRegion region) {
- DCHECK_EQ(0u, current_entry_.dex_pc) << "EndStackMapEntry not called after BeginStackMapEntry";
- DCHECK_NE(0u, needed_size_) << "PrepareForFillIn not called before FillIn";
+template<typename Vector>
+static MemoryRegion EncodeMemoryRegion(Vector* out, size_t* bit_offset, uint32_t bit_length) {
+ uint32_t byte_length = BitsToBytesRoundUp(bit_length);
+ EncodeVarintBits(out, bit_offset, byte_length);
+ *bit_offset = RoundUp(*bit_offset, kBitsPerByte);
+ out->resize(out->size() + byte_length);
+ MemoryRegion region(out->data() + *bit_offset / kBitsPerByte, byte_length);
+ *bit_offset += kBitsPerByte * byte_length;
+ return region;
+}
- DCHECK_EQ(region.size(), needed_size_);
+template<uint32_t NumColumns>
+using ScopedBitTableBuilder = BitTableBuilder<NumColumns, ScopedArenaAllocatorAdapter<uint32_t>>;
- // Note that the memory region does not have to be zeroed when we JIT code
- // because we do not use the arena allocator there.
+size_t StackMapStream::PrepareForFillIn() {
+ size_t bit_offset = 0;
+ out_.clear();
- // Write the CodeInfo header.
- region.CopyFrom(0, MemoryRegion(code_info_encoding_.data(), code_info_encoding_.size()));
+ // Decide the offsets of dex register map entries, but do not write them out yet.
+ // Needs to be done first as it modifies the stack map entry.
+ size_t dex_register_map_bytes = 0;
+ for (DexRegisterMapEntry& entry : dex_register_entries_) {
+ size_t size = entry.ComputeSize(location_catalog_entries_.size());
+ entry.offset = size == 0 ? DexRegisterMapEntry::kOffsetUnassigned : dex_register_map_bytes;
+ dex_register_map_bytes += size;
+ }
- CodeInfo code_info(region);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- DCHECK_EQ(encoding.stack_map.num_entries, stack_maps_.size());
+ // Must be done before calling ComputeInlineInfoEncoding since ComputeInlineInfoEncoding requires
+ // dex_method_index_idx to be filled in.
+ PrepareMethodIndices();
- MemoryRegion dex_register_locations_region = region.Subregion(
- encoding.dex_register_map.byte_offset,
- encoding.dex_register_map.num_bytes);
+ // Dedup stack masks. Needs to be done first as it modifies the stack map entry.
+ size_t stack_mask_bits = stack_mask_max_ + 1; // Need room for max element too.
+ size_t num_stack_masks = PrepareStackMasks(stack_mask_bits);
+
+ // Dedup register masks. Needs to be done first as it modifies the stack map entry.
+ size_t num_register_masks = PrepareRegisterMasks();
+
+ // Write dex register maps.
+ MemoryRegion dex_register_map_region =
+ EncodeMemoryRegion(&out_, &bit_offset, dex_register_map_bytes * kBitsPerByte);
+ for (DexRegisterMapEntry& entry : dex_register_entries_) {
+ size_t entry_size = entry.ComputeSize(location_catalog_entries_.size());
+ if (entry_size != 0) {
+ DexRegisterMap dex_register_map(
+ dex_register_map_region.Subregion(entry.offset, entry_size));
+ FillInDexRegisterMap(dex_register_map,
+ entry.num_dex_registers,
+ *entry.live_dex_registers_mask,
+ entry.locations_start_index);
+ }
+ }
- // Set the Dex register location catalog.
- MemoryRegion dex_register_location_catalog_region = region.Subregion(
- encoding.location_catalog.byte_offset,
- encoding.location_catalog.num_bytes);
+ // Write dex register catalog.
+ EncodeVarintBits(&out_, &bit_offset, location_catalog_entries_.size());
+ size_t location_catalog_bytes = ComputeDexRegisterLocationCatalogSize();
+ MemoryRegion dex_register_location_catalog_region =
+ EncodeMemoryRegion(&out_, &bit_offset, location_catalog_bytes * kBitsPerByte);
DexRegisterLocationCatalog dex_register_location_catalog(dex_register_location_catalog_region);
// Offset in `dex_register_location_catalog` where to store the next
// register location.
@@ -353,82 +257,70 @@ void StackMapStream::FillInCodeInfo(MemoryRegion region) {
// Ensure we reached the end of the Dex registers location_catalog.
DCHECK_EQ(location_catalog_offset, dex_register_location_catalog_region.size());
- ArenaBitVector empty_bitmask(allocator_, 0, /* expandable */ false, kArenaAllocStackMapStream);
- uintptr_t next_dex_register_map_offset = 0;
- uintptr_t next_inline_info_index = 0;
- size_t invoke_info_idx = 0;
- for (size_t i = 0, e = stack_maps_.size(); i < e; ++i) {
- StackMap stack_map = code_info.GetStackMapAt(i, encoding);
- StackMapEntry entry = stack_maps_[i];
-
- stack_map.SetDexPc(encoding.stack_map.encoding, entry.dex_pc);
- stack_map.SetNativePcCodeOffset(encoding.stack_map.encoding, entry.native_pc_code_offset);
- stack_map.SetRegisterMaskIndex(encoding.stack_map.encoding, entry.register_mask_index);
- stack_map.SetStackMaskIndex(encoding.stack_map.encoding, entry.stack_mask_index);
-
- size_t offset = MaybeCopyDexRegisterMap(dex_register_entries_[entry.dex_register_map_index],
- &next_dex_register_map_offset,
- dex_register_locations_region);
- stack_map.SetDexRegisterMapOffset(encoding.stack_map.encoding, offset);
-
+ // Write stack maps.
+ ScopedArenaAllocatorAdapter<void> adapter = allocator_->Adapter(kArenaAllocStackMapStream);
+ ScopedBitTableBuilder<StackMap::Field::kCount> stack_map_builder((adapter));
+ ScopedBitTableBuilder<InvokeInfo::Field::kCount> invoke_info_builder((adapter));
+ ScopedBitTableBuilder<InlineInfo::Field::kCount> inline_info_builder((adapter));
+ for (const StackMapEntry& entry : stack_maps_) {
if (entry.dex_method_index != dex::kDexNoIndex) {
- InvokeInfo invoke_info(code_info.GetInvokeInfo(encoding, invoke_info_idx));
- invoke_info.SetNativePcCodeOffset(encoding.invoke_info.encoding, entry.native_pc_code_offset);
- invoke_info.SetInvokeType(encoding.invoke_info.encoding, entry.invoke_type);
- invoke_info.SetMethodIndexIdx(encoding.invoke_info.encoding, entry.dex_method_index_idx);
- ++invoke_info_idx;
+ invoke_info_builder.AddRow(
+ entry.native_pc_code_offset.CompressedValue(),
+ entry.invoke_type,
+ entry.dex_method_index_idx);
}
// Set the inlining info.
- if (entry.inlining_depth != 0) {
- InlineInfo inline_info = code_info.GetInlineInfo(next_inline_info_index, encoding);
-
- // Fill in the index.
- stack_map.SetInlineInfoIndex(encoding.stack_map.encoding, next_inline_info_index);
- DCHECK_EQ(next_inline_info_index, entry.inline_infos_start_index);
- next_inline_info_index += entry.inlining_depth;
-
- inline_info.SetDepth(encoding.inline_info.encoding, entry.inlining_depth);
- DCHECK_LE(entry.inline_infos_start_index + entry.inlining_depth, inline_infos_.size());
-
- for (size_t depth = 0; depth < entry.inlining_depth; ++depth) {
- InlineInfoEntry inline_entry = inline_infos_[depth + entry.inline_infos_start_index];
- if (inline_entry.method != nullptr) {
- inline_info.SetMethodIndexIdxAtDepth(
- encoding.inline_info.encoding,
- depth,
- High32Bits(reinterpret_cast<uintptr_t>(inline_entry.method)));
- inline_info.SetExtraDataAtDepth(
- encoding.inline_info.encoding,
- depth,
- Low32Bits(reinterpret_cast<uintptr_t>(inline_entry.method)));
- } else {
- inline_info.SetMethodIndexIdxAtDepth(encoding.inline_info.encoding,
- depth,
- inline_entry.dex_method_index_idx);
- inline_info.SetExtraDataAtDepth(encoding.inline_info.encoding, depth, 1);
- }
- inline_info.SetDexPcAtDepth(encoding.inline_info.encoding, depth, inline_entry.dex_pc);
- size_t dex_register_map_offset = MaybeCopyDexRegisterMap(
- dex_register_entries_[inline_entry.dex_register_map_index],
- &next_dex_register_map_offset,
- dex_register_locations_region);
- inline_info.SetDexRegisterMapOffsetAtDepth(encoding.inline_info.encoding,
- depth,
- dex_register_map_offset);
+ uint32_t inline_info_index = StackMap::kNoValue;
+ DCHECK_LE(entry.inline_infos_start_index + entry.inlining_depth, inline_infos_.size());
+ for (size_t depth = 0; depth < entry.inlining_depth; ++depth) {
+ InlineInfoEntry inline_entry = inline_infos_[depth + entry.inline_infos_start_index];
+ uint32_t method_index_idx = inline_entry.dex_method_index_idx;
+ uint32_t extra_data = 1;
+ if (inline_entry.method != nullptr) {
+ method_index_idx = High32Bits(reinterpret_cast<uintptr_t>(inline_entry.method));
+ extra_data = Low32Bits(reinterpret_cast<uintptr_t>(inline_entry.method));
+ }
+ uint32_t index = inline_info_builder.AddRow(
+ (depth == entry.inlining_depth - 1) ? InlineInfo::kLast : InlineInfo::kMore,
+ method_index_idx,
+ inline_entry.dex_pc,
+ extra_data,
+ dex_register_entries_[inline_entry.dex_register_map_index].offset);
+ if (depth == 0) {
+ inline_info_index = index;
}
- } else if (encoding.stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0) {
- stack_map.SetInlineInfoIndex(encoding.stack_map.encoding, StackMap::kNoInlineInfo);
}
+ stack_map_builder.AddRow(
+ entry.native_pc_code_offset.CompressedValue(),
+ entry.dex_pc,
+ dex_register_entries_[entry.dex_register_map_index].offset,
+ inline_info_index,
+ entry.register_mask_index,
+ entry.stack_mask_index);
+ }
+ stack_map_builder.Encode(&out_, &bit_offset);
+ invoke_info_builder.Encode(&out_, &bit_offset);
+ inline_info_builder.Encode(&out_, &bit_offset);
+
+ // Write register masks table.
+ ScopedBitTableBuilder<1> register_mask_builder((adapter));
+ for (size_t i = 0; i < num_register_masks; ++i) {
+ register_mask_builder.AddRow(register_masks_[i]);
}
+ register_mask_builder.Encode(&out_, &bit_offset);
// Write stack masks table.
- const size_t stack_mask_bits = encoding.stack_mask.encoding.BitSize();
+ EncodeVarintBits(&out_, &bit_offset, stack_mask_bits);
+ out_.resize(BitsToBytesRoundUp(bit_offset + stack_mask_bits * num_stack_masks));
+ BitMemoryRegion stack_mask_region(MemoryRegion(out_.data(), out_.size()),
+ bit_offset,
+ stack_mask_bits * num_stack_masks);
if (stack_mask_bits > 0) {
- size_t stack_mask_bytes = RoundUp(stack_mask_bits, kBitsPerByte) / kBitsPerByte;
- for (size_t i = 0; i < encoding.stack_mask.num_entries; ++i) {
+ for (size_t i = 0; i < num_stack_masks; ++i) {
+ size_t stack_mask_bytes = BitsToBytesRoundUp(stack_mask_bits);
BitMemoryRegion src(MemoryRegion(&stack_masks_[i * stack_mask_bytes], stack_mask_bytes));
- BitMemoryRegion dst = code_info.GetStackMask(i, encoding);
+ BitMemoryRegion dst = stack_mask_region.Subregion(i * stack_mask_bits, stack_mask_bits);
for (size_t bit_index = 0; bit_index < stack_mask_bits; bit_index += BitSizeOf<uint32_t>()) {
size_t num_bits = std::min<size_t>(stack_mask_bits - bit_index, BitSizeOf<uint32_t>());
dst.StoreBits(bit_index, src.LoadBits(bit_index, num_bits), num_bits);
@@ -436,11 +328,16 @@ void StackMapStream::FillInCodeInfo(MemoryRegion region) {
}
}
- // Write register masks table.
- for (size_t i = 0; i < encoding.register_mask.num_entries; ++i) {
- BitMemoryRegion register_mask = code_info.GetRegisterMask(i, encoding);
- register_mask.StoreBits(0, register_masks_[i], encoding.register_mask.encoding.BitSize());
- }
+ return UnsignedLeb128Size(out_.size()) + out_.size();
+}
+
+void StackMapStream::FillInCodeInfo(MemoryRegion region) {
+ DCHECK_EQ(0u, current_entry_.dex_pc) << "EndStackMapEntry not called after BeginStackMapEntry";
+ DCHECK_NE(0u, out_.size()) << "PrepareForFillIn not called before FillIn";
+ DCHECK_EQ(region.size(), UnsignedLeb128Size(out_.size()) + out_.size());
+
+ uint8_t* ptr = EncodeUnsignedLeb128(region.begin(), out_.size());
+ region.CopyFromVector(ptr - region.begin(), out_);
// Verify all written data in debug build.
if (kIsDebugBuild) {
@@ -528,7 +425,6 @@ void StackMapStream::CheckDexRegisterMap(const CodeInfo& code_info,
size_t num_dex_registers,
BitVector* live_dex_registers_mask,
size_t dex_register_locations_index) const {
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
for (size_t reg = 0; reg < num_dex_registers; reg++) {
// Find the location we tried to encode.
DexRegisterLocation expected = DexRegisterLocation::None();
@@ -543,7 +439,7 @@ void StackMapStream::CheckDexRegisterMap(const CodeInfo& code_info,
} else {
DCHECK(dex_register_map.IsDexRegisterLive(reg));
DexRegisterLocation seen = dex_register_map.GetDexRegisterLocation(
- reg, num_dex_registers, code_info, encoding);
+ reg, num_dex_registers, code_info);
DCHECK_EQ(expected.GetKind(), seen.GetKind());
DCHECK_EQ(expected.GetValue(), seen.GetValue());
}
@@ -613,23 +509,23 @@ size_t StackMapStream::PrepareStackMasks(size_t entry_size_in_bits) {
// Check that all StackMapStream inputs are correctly encoded by trying to read them back.
void StackMapStream::CheckCodeInfo(MemoryRegion region) const {
CodeInfo code_info(region);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- DCHECK_EQ(code_info.GetNumberOfStackMaps(encoding), stack_maps_.size());
+ DCHECK_EQ(code_info.GetNumberOfStackMaps(), stack_maps_.size());
+ DCHECK_EQ(code_info.GetNumberOfStackMaskBits(), static_cast<uint32_t>(stack_mask_max_ + 1));
+ DCHECK_EQ(code_info.GetNumberOfLocationCatalogEntries(), location_catalog_entries_.size());
size_t invoke_info_index = 0;
for (size_t s = 0; s < stack_maps_.size(); ++s) {
- const StackMap stack_map = code_info.GetStackMapAt(s, encoding);
- const StackMapEncoding& stack_map_encoding = encoding.stack_map.encoding;
+ const StackMap stack_map = code_info.GetStackMapAt(s);
StackMapEntry entry = stack_maps_[s];
// Check main stack map fields.
- DCHECK_EQ(stack_map.GetNativePcOffset(stack_map_encoding, instruction_set_),
+ DCHECK_EQ(stack_map.GetNativePcOffset(instruction_set_),
entry.native_pc_code_offset.Uint32Value(instruction_set_));
- DCHECK_EQ(stack_map.GetDexPc(stack_map_encoding), entry.dex_pc);
- DCHECK_EQ(stack_map.GetRegisterMaskIndex(stack_map_encoding), entry.register_mask_index);
- DCHECK_EQ(code_info.GetRegisterMaskOf(encoding, stack_map), entry.register_mask);
- const size_t num_stack_mask_bits = code_info.GetNumberOfStackMaskBits(encoding);
- DCHECK_EQ(stack_map.GetStackMaskIndex(stack_map_encoding), entry.stack_mask_index);
- BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
+ DCHECK_EQ(stack_map.GetDexPc(), entry.dex_pc);
+ DCHECK_EQ(stack_map.GetRegisterMaskIndex(), entry.register_mask_index);
+ DCHECK_EQ(code_info.GetRegisterMaskOf(stack_map), entry.register_mask);
+ const size_t num_stack_mask_bits = code_info.GetNumberOfStackMaskBits();
+ DCHECK_EQ(stack_map.GetStackMaskIndex(), entry.stack_mask_index);
+ BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
if (entry.sp_mask != nullptr) {
DCHECK_GE(stack_mask.size_in_bits(), entry.sp_mask->GetNumberOfBits());
for (size_t b = 0; b < num_stack_mask_bits; b++) {
@@ -641,38 +537,36 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const {
}
}
if (entry.dex_method_index != dex::kDexNoIndex) {
- InvokeInfo invoke_info = code_info.GetInvokeInfo(encoding, invoke_info_index);
- DCHECK_EQ(invoke_info.GetNativePcOffset(encoding.invoke_info.encoding, instruction_set_),
+ InvokeInfo invoke_info = code_info.GetInvokeInfo(invoke_info_index);
+ DCHECK_EQ(invoke_info.GetNativePcOffset(instruction_set_),
entry.native_pc_code_offset.Uint32Value(instruction_set_));
- DCHECK_EQ(invoke_info.GetInvokeType(encoding.invoke_info.encoding), entry.invoke_type);
- DCHECK_EQ(invoke_info.GetMethodIndexIdx(encoding.invoke_info.encoding),
- entry.dex_method_index_idx);
+ DCHECK_EQ(invoke_info.GetInvokeType(), entry.invoke_type);
+ DCHECK_EQ(invoke_info.GetMethodIndexIdx(), entry.dex_method_index_idx);
invoke_info_index++;
}
CheckDexRegisterMap(code_info,
code_info.GetDexRegisterMapOf(
- stack_map, encoding, entry.dex_register_entry.num_dex_registers),
+ stack_map, entry.dex_register_entry.num_dex_registers),
entry.dex_register_entry.num_dex_registers,
entry.dex_register_entry.live_dex_registers_mask,
entry.dex_register_entry.locations_start_index);
// Check inline info.
- DCHECK_EQ(stack_map.HasInlineInfo(stack_map_encoding), (entry.inlining_depth != 0));
+ DCHECK_EQ(stack_map.HasInlineInfo(), (entry.inlining_depth != 0));
if (entry.inlining_depth != 0) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- DCHECK_EQ(inline_info.GetDepth(encoding.inline_info.encoding), entry.inlining_depth);
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+ DCHECK_EQ(inline_info.GetDepth(), entry.inlining_depth);
for (size_t d = 0; d < entry.inlining_depth; ++d) {
size_t inline_info_index = entry.inline_infos_start_index + d;
DCHECK_LT(inline_info_index, inline_infos_.size());
InlineInfoEntry inline_entry = inline_infos_[inline_info_index];
- DCHECK_EQ(inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, d),
- inline_entry.dex_pc);
- if (inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, d)) {
- DCHECK_EQ(inline_info.GetArtMethodAtDepth(encoding.inline_info.encoding, d),
+ DCHECK_EQ(inline_info.GetDexPcAtDepth(d), inline_entry.dex_pc);
+ if (inline_info.EncodesArtMethodAtDepth(d)) {
+ DCHECK_EQ(inline_info.GetArtMethodAtDepth(d),
inline_entry.method);
} else {
const size_t method_index_idx =
- inline_info.GetMethodIndexIdxAtDepth(encoding.inline_info.encoding, d);
+ inline_info.GetMethodIndexIdxAtDepth(d);
DCHECK_EQ(method_index_idx, inline_entry.dex_method_index_idx);
DCHECK_EQ(method_indices_[method_index_idx], inline_entry.method_index);
}
@@ -681,7 +575,6 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const {
code_info.GetDexRegisterMapAtDepth(
d,
inline_info,
- encoding,
inline_entry.dex_register_entry.num_dex_registers),
inline_entry.dex_register_entry.num_dex_registers,
inline_entry.dex_register_entry.live_dex_registers_mask,
@@ -692,7 +585,7 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const {
}
size_t StackMapStream::ComputeMethodInfoSize() const {
- DCHECK_NE(0u, needed_size_) << "PrepareForFillIn not called before " << __FUNCTION__;
+ DCHECK_NE(0u, out_.size()) << "PrepareForFillIn not called before " << __FUNCTION__;
return MethodInfo::ComputeSize(method_indices_.size());
}
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index 268e9bd6e0..ea97cf6530 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -73,36 +73,32 @@ class StackMapStream : public ValueObject {
method_indices_(allocator->Adapter(kArenaAllocStackMapStream)),
dex_register_entries_(allocator->Adapter(kArenaAllocStackMapStream)),
stack_mask_max_(-1),
- dex_pc_max_(kNoDexPc),
- register_mask_max_(0),
- number_of_stack_maps_with_inline_info_(0),
+ out_(allocator->Adapter(kArenaAllocStackMapStream)),
dex_map_hash_to_stack_map_indices_(std::less<uint32_t>(),
allocator->Adapter(kArenaAllocStackMapStream)),
current_entry_(),
current_inline_info_(),
- code_info_encoding_(allocator->Adapter(kArenaAllocStackMapStream)),
- needed_size_(0),
current_dex_register_(0),
in_inline_frame_(false) {
stack_maps_.reserve(10);
+ out_.reserve(64);
location_catalog_entries_.reserve(4);
dex_register_locations_.reserve(10 * 4);
inline_infos_.reserve(2);
- code_info_encoding_.reserve(16);
}
// A dex register map entry for a single stack map entry, contains what registers are live as
// well as indices into the location catalog.
class DexRegisterMapEntry {
public:
- static const size_t kOffsetUnassigned = -1;
+ static const uint32_t kOffsetUnassigned = -1;
BitVector* live_dex_registers_mask;
uint32_t num_dex_registers;
size_t locations_start_index;
// Computed fields
size_t hash = 0;
- size_t offset = kOffsetUnassigned;
+ uint32_t offset = kOffsetUnassigned;
size_t ComputeSize(size_t catalog_size) const;
};
@@ -113,7 +109,7 @@ class StackMapStream : public ValueObject {
CodeOffset native_pc_code_offset;
uint32_t register_mask;
BitVector* sp_mask;
- uint8_t inlining_depth;
+ uint32_t inlining_depth;
size_t inline_infos_start_index;
uint32_t stack_mask_index;
uint32_t register_mask_index;
@@ -174,11 +170,6 @@ class StackMapStream : public ValueObject {
private:
size_t ComputeDexRegisterLocationCatalogSize() const;
- size_t ComputeDexRegisterMapsSize() const;
- void ComputeInlineInfoEncoding(InlineInfoEncoding* encoding,
- size_t dex_register_maps_bytes);
-
- CodeOffset ComputeMaxNativePcCodeOffset() const;
// Returns the number of unique stack masks.
size_t PrepareStackMasks(size_t entry_size_in_bits);
@@ -197,24 +188,11 @@ class StackMapStream : public ValueObject {
bool DexRegisterMapEntryEquals(const DexRegisterMapEntry& a, const DexRegisterMapEntry& b) const;
// Fill in the corresponding entries of a register map.
- void ComputeInvokeInfoEncoding(CodeInfoEncoding* encoding);
-
- // Returns the index of an entry with the same dex register map as the current_entry,
- // or kNoSameDexMapFound if no such entry exists.
- size_t FindEntryWithTheSameDexMap();
- bool HaveTheSameDexMaps(const StackMapEntry& a, const StackMapEntry& b) const;
-
- // Fill in the corresponding entries of a register map.
void FillInDexRegisterMap(DexRegisterMap dex_register_map,
uint32_t num_dex_registers,
const BitVector& live_dex_registers_mask,
uint32_t start_index_in_dex_register_locations) const;
- // Returns the offset for the dex register inside of the dex register location region. See FillIn.
- // Only copies the dex register map if the offset for the entry is not already assigned.
- size_t MaybeCopyDexRegisterMap(DexRegisterMapEntry& entry,
- size_t* current_offset,
- MemoryRegion dex_register_locations_region);
void CheckDexRegisterMap(const CodeInfo& code_info,
const DexRegisterMap& dex_register_map,
size_t num_dex_registers,
@@ -244,21 +222,16 @@ class StackMapStream : public ValueObject {
ScopedArenaVector<uint32_t> method_indices_;
ScopedArenaVector<DexRegisterMapEntry> dex_register_entries_;
int stack_mask_max_;
- uint32_t dex_pc_max_;
- uint32_t register_mask_max_;
- size_t number_of_stack_maps_with_inline_info_;
+
+ ScopedArenaVector<uint8_t> out_;
ScopedArenaSafeMap<uint32_t, ScopedArenaVector<uint32_t>> dex_map_hash_to_stack_map_indices_;
StackMapEntry current_entry_;
InlineInfoEntry current_inline_info_;
- ScopedArenaVector<uint8_t> code_info_encoding_;
- size_t needed_size_;
uint32_t current_dex_register_;
bool in_inline_frame_;
- static constexpr uint32_t kNoSameDexMapFound = -1;
-
DISALLOW_COPY_AND_ASSIGN(StackMapStream);
};
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index e36c592662..9db7588b3a 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -29,14 +29,13 @@ namespace art {
// to the given bit vector. Returns true if they are same.
static bool CheckStackMask(
const CodeInfo& code_info,
- const CodeInfoEncoding& encoding,
const StackMap& stack_map,
const BitVector& bit_vector) {
- BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
- if (bit_vector.GetNumberOfBits() > encoding.stack_mask.encoding.BitSize()) {
+ BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
+ if (bit_vector.GetNumberOfBits() > code_info.GetNumberOfStackMaskBits()) {
return false;
}
- for (size_t i = 0; i < encoding.stack_mask.encoding.BitSize(); ++i) {
+ for (size_t i = 0; i < code_info.GetNumberOfStackMaskBits(); ++i) {
if (stack_mask.LoadBit(i) != bit_vector.IsBitSet(i)) {
return false;
}
@@ -65,30 +64,29 @@ TEST(StackMapTest, Test1) {
stream.FillInCodeInfo(region);
CodeInfo code_info(region);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
+ ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
- uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
+ uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(2u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
+ DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
// 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, 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.stack_map.encoding));
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, 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());
+ ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
- ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask));
+ ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask));
- ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
+ ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
+ code_info.GetDexRegisterMapOf(stack_map, 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));
@@ -99,16 +97,16 @@ TEST(StackMapTest, Test1) {
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, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
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));
+ 0, number_of_dex_registers, code_info));
+ ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
0, number_of_dex_registers, number_of_catalog_entries);
@@ -125,7 +123,7 @@ TEST(StackMapTest, Test1) {
ASSERT_EQ(0, location0.GetValue());
ASSERT_EQ(-2, location1.GetValue());
- ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
+ ASSERT_FALSE(stack_map.HasInlineInfo());
}
TEST(StackMapTest, Test2) {
@@ -179,12 +177,11 @@ TEST(StackMapTest, Test2) {
stream.FillInCodeInfo(region);
CodeInfo code_info(region);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- ASSERT_EQ(4u, code_info.GetNumberOfStackMaps(encoding));
+ ASSERT_EQ(4u, code_info.GetNumberOfStackMaps());
- uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
+ uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(7u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
+ DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
// The Dex register location catalog contains:
// - six 1-byte short Dex register locations, and
// - one 5-byte large Dex register location.
@@ -193,18 +190,18 @@ TEST(StackMapTest, Test2) {
// First stack map.
{
- 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.stack_map.encoding));
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, 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());
+ ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
- ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask1));
+ ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask1));
- ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
+ ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
+ code_info.GetDexRegisterMapOf(stack_map, 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));
@@ -215,16 +212,16 @@ TEST(StackMapTest, Test2) {
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, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
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));
+ 0, number_of_dex_registers, code_info));
+ ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
0, number_of_dex_registers, number_of_catalog_entries);
@@ -241,29 +238,29 @@ TEST(StackMapTest, Test2) {
ASSERT_EQ(0, location0.GetValue());
ASSERT_EQ(-2, location1.GetValue());
- ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- ASSERT_EQ(2u, inline_info.GetDepth(encoding.inline_info.encoding));
- ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
- ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
- ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
- ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
+ ASSERT_TRUE(stack_map.HasInlineInfo());
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+ ASSERT_EQ(2u, inline_info.GetDepth());
+ ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(0));
+ ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(1));
+ ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(0));
+ ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(1));
}
// Second stack map.
{
- 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.stack_map.encoding));
- ASSERT_EQ(128u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0xFFu, code_info.GetRegisterMaskOf(encoding, 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());
+ ASSERT_EQ(128u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0xFFu, code_info.GetRegisterMaskOf(stack_map));
- ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask2));
+ ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask2));
- ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
+ ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
+ code_info.GetDexRegisterMapOf(stack_map, 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));
@@ -274,17 +271,17 @@ TEST(StackMapTest, Test2) {
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, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(18, dex_register_map.GetMachineRegister(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(3, dex_register_map.GetMachineRegister(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
0, number_of_dex_registers, number_of_catalog_entries);
@@ -301,23 +298,23 @@ TEST(StackMapTest, Test2) {
ASSERT_EQ(18, location0.GetValue());
ASSERT_EQ(3, location1.GetValue());
- ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
+ ASSERT_FALSE(stack_map.HasInlineInfo());
}
// Third stack map.
{
- StackMap stack_map = code_info.GetStackMapAt(2, encoding);
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(2u, encoding)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u, encoding)));
- ASSERT_EQ(2u, stack_map.GetDexPc(encoding.stack_map.encoding));
- ASSERT_EQ(192u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0xABu, code_info.GetRegisterMaskOf(encoding, stack_map));
+ StackMap stack_map = code_info.GetStackMapAt(2);
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(2u)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u)));
+ ASSERT_EQ(2u, stack_map.GetDexPc());
+ ASSERT_EQ(192u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0xABu, code_info.GetRegisterMaskOf(stack_map));
- ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask3));
+ ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask3));
- ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
+ ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
+ code_info.GetDexRegisterMapOf(stack_map, 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));
@@ -328,17 +325,17 @@ TEST(StackMapTest, Test2) {
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, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(6, dex_register_map.GetMachineRegister(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(8, dex_register_map.GetMachineRegister(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
0, number_of_dex_registers, number_of_catalog_entries);
@@ -355,23 +352,23 @@ TEST(StackMapTest, Test2) {
ASSERT_EQ(6, location0.GetValue());
ASSERT_EQ(8, location1.GetValue());
- ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
+ ASSERT_FALSE(stack_map.HasInlineInfo());
}
// Fourth stack map.
{
- StackMap stack_map = code_info.GetStackMapAt(3, encoding);
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(3u, encoding)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u, encoding)));
- ASSERT_EQ(3u, stack_map.GetDexPc(encoding.stack_map.encoding));
- ASSERT_EQ(256u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0xCDu, code_info.GetRegisterMaskOf(encoding, stack_map));
+ StackMap stack_map = code_info.GetStackMapAt(3);
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(3u)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u)));
+ ASSERT_EQ(3u, stack_map.GetDexPc());
+ ASSERT_EQ(256u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0xCDu, code_info.GetRegisterMaskOf(stack_map));
- ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask4));
+ ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask4));
- ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
+ ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
+ code_info.GetDexRegisterMapOf(stack_map, 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));
@@ -382,17 +379,17 @@ TEST(StackMapTest, Test2) {
ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationInternalKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(3, dex_register_map.GetMachineRegister(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(1, dex_register_map.GetMachineRegister(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
0, number_of_dex_registers, number_of_catalog_entries);
@@ -409,7 +406,7 @@ TEST(StackMapTest, Test2) {
ASSERT_EQ(3, location0.GetValue());
ASSERT_EQ(1, location1.GetValue());
- ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
+ ASSERT_FALSE(stack_map.HasInlineInfo());
}
}
@@ -440,12 +437,11 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
stream.FillInCodeInfo(region);
CodeInfo code_info(region);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
+ ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
- uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
+ uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(2u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
+ DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
// The Dex register location catalog contains:
// - one 1-byte short Dex register locations, and
// - one 5-byte large Dex register location.
@@ -454,17 +450,17 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
// First stack map.
{
- 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.stack_map.encoding));
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, 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());
+ ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
- ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask1));
+ ASSERT_TRUE(CheckStackMask(code_info, stack_map, sp_mask1));
- ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
- DexRegisterMap map(code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers));
+ ASSERT_TRUE(stack_map.HasDexRegisterMap());
+ DexRegisterMap map(code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers));
ASSERT_TRUE(map.IsDexRegisterLive(0));
ASSERT_TRUE(map.IsDexRegisterLive(1));
ASSERT_EQ(2u, map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
@@ -474,15 +470,15 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
size_t expected_map_size = 1u + 1u;
ASSERT_EQ(expected_map_size, map.Size());
- ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0, number_of_dex_registers, code_info, encoding));
+ ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kConstant,
- map.GetLocationKind(1, number_of_dex_registers, code_info, encoding));
+ map.GetLocationKind(1, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kInStack,
- map.GetLocationInternalKind(0, number_of_dex_registers, code_info, encoding));
+ map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kConstantLargeValue,
- map.GetLocationInternalKind(1, number_of_dex_registers, code_info, encoding));
- ASSERT_EQ(0, map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info, encoding));
- ASSERT_EQ(-2, map.GetConstant(1, number_of_dex_registers, code_info, encoding));
+ map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
+ ASSERT_EQ(0, map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info));
+ ASSERT_EQ(-2, map.GetConstant(1, number_of_dex_registers, code_info));
const size_t index0 =
map.GetLocationCatalogEntryIndex(0, number_of_dex_registers, number_of_catalog_entries);
@@ -501,10 +497,10 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
// Test that the inline info dex register map deduplicated to the same offset as the stack map
// one.
- ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- EXPECT_EQ(inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info.encoding, 0),
- stack_map.GetDexRegisterMapOffset(encoding.stack_map.encoding));
+ ASSERT_TRUE(stack_map.HasInlineInfo());
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+ EXPECT_EQ(inline_info.GetDexRegisterMapOffsetAtDepth(0),
+ stack_map.GetDexRegisterMapOffset());
}
}
@@ -527,27 +523,26 @@ TEST(StackMapTest, TestNonLiveDexRegisters) {
stream.FillInCodeInfo(region);
CodeInfo code_info(region);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
+ ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
- uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
+ uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(1u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
+ DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
// 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, 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.stack_map.encoding));
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, 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());
+ ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
- ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
+ ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
+ code_info.GetDexRegisterMapOf(stack_map, 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));
@@ -558,14 +553,14 @@ TEST(StackMapTest, TestNonLiveDexRegisters) {
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, encoding));
+ 0, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
- 1, number_of_dex_registers, code_info, encoding));
+ 1, number_of_dex_registers, code_info));
ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationInternalKind(
- 0, number_of_dex_registers, code_info, encoding));
+ 0, number_of_dex_registers, code_info));
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));
+ 1, number_of_dex_registers, code_info));
+ ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
0, number_of_dex_registers, number_of_catalog_entries);
@@ -582,7 +577,7 @@ TEST(StackMapTest, TestNonLiveDexRegisters) {
ASSERT_EQ(0, location0.GetValue());
ASSERT_EQ(-2, location1.GetValue());
- ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
+ ASSERT_FALSE(stack_map.HasInlineInfo());
}
// Generate a stack map whose dex register offset is
@@ -620,11 +615,10 @@ TEST(StackMapTest, DexRegisterMapOffsetOverflow) {
stream.FillInCodeInfo(region);
CodeInfo code_info(region);
- CodeInfoEncoding 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.
- uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
+ uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(2u, number_of_catalog_entries);
ASSERT_EQ(1u, DexRegisterMap::SingleEntrySizeInBits(number_of_catalog_entries));
@@ -635,21 +629,21 @@ 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, encoding);
+ StackMap stack_map0 = code_info.GetStackMapAt(0);
DexRegisterMap dex_register_map0 =
- code_info.GetDexRegisterMapOf(stack_map0, encoding, number_of_dex_registers);
+ code_info.GetDexRegisterMapOf(stack_map0, number_of_dex_registers);
ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers,
number_of_catalog_entries));
ASSERT_EQ(255u, dex_register_map0.Size());
- StackMap stack_map1 = code_info.GetStackMapAt(1, encoding);
- ASSERT_TRUE(stack_map1.HasDexRegisterMap(encoding.stack_map.encoding));
+ StackMap stack_map1 = code_info.GetStackMapAt(1);
+ ASSERT_TRUE(stack_map1.HasDexRegisterMap());
// ...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(encoding.stack_map.encoding),
- StackMap::kNoDexRegisterMap);
- ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(encoding.stack_map.encoding), 0xFFu);
+ ASSERT_NE(stack_map1.GetDexRegisterMapOffset(),
+ StackMap::kNoValue);
+ ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(), 0xFFu);
}
TEST(StackMapTest, TestShareDexRegisterMap) {
@@ -682,33 +676,32 @@ TEST(StackMapTest, TestShareDexRegisterMap) {
stream.FillInCodeInfo(region);
CodeInfo ci(region);
- CodeInfoEncoding encoding = ci.ExtractEncoding();
// Verify first stack map.
- 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));
+ 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));
// Verify second stack map.
- 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));
+ 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));
// Verify third stack map.
- 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));
+ 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));
// Verify dex register map offsets.
- ASSERT_EQ(sm0.GetDexRegisterMapOffset(encoding.stack_map.encoding),
- sm1.GetDexRegisterMapOffset(encoding.stack_map.encoding));
- ASSERT_NE(sm0.GetDexRegisterMapOffset(encoding.stack_map.encoding),
- sm2.GetDexRegisterMapOffset(encoding.stack_map.encoding));
- ASSERT_NE(sm1.GetDexRegisterMapOffset(encoding.stack_map.encoding),
- sm2.GetDexRegisterMapOffset(encoding.stack_map.encoding));
+ ASSERT_EQ(sm0.GetDexRegisterMapOffset(),
+ sm1.GetDexRegisterMapOffset());
+ ASSERT_NE(sm0.GetDexRegisterMapOffset(),
+ sm2.GetDexRegisterMapOffset());
+ ASSERT_NE(sm1.GetDexRegisterMapOffset(),
+ sm2.GetDexRegisterMapOffset());
}
TEST(StackMapTest, TestNoDexRegisterMap) {
@@ -732,33 +725,32 @@ TEST(StackMapTest, TestNoDexRegisterMap) {
stream.FillInCodeInfo(region);
CodeInfo code_info(region);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
+ ASSERT_EQ(2u, code_info.GetNumberOfStackMaps());
- uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
+ uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
ASSERT_EQ(0u, number_of_catalog_entries);
- DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
+ DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
ASSERT_EQ(0u, location_catalog.Size());
- 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.stack_map.encoding));
- ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
-
- ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
- ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
-
- stack_map = code_info.GetStackMapAt(1, encoding);
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1, encoding)));
- ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(68, encoding)));
- ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map.encoding));
- ASSERT_EQ(68u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
- ASSERT_EQ(0x4u, code_info.GetRegisterMaskOf(encoding, stack_map));
-
- ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
- ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
+ 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());
+ ASSERT_EQ(64u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(stack_map));
+
+ ASSERT_FALSE(stack_map.HasDexRegisterMap());
+ ASSERT_FALSE(stack_map.HasInlineInfo());
+
+ stack_map = code_info.GetStackMapAt(1);
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1)));
+ ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(68)));
+ ASSERT_EQ(1u, stack_map.GetDexPc());
+ ASSERT_EQ(68u, stack_map.GetNativePcOffset(kRuntimeISA));
+ ASSERT_EQ(0x4u, code_info.GetRegisterMaskOf(stack_map));
+
+ ASSERT_FALSE(stack_map.HasDexRegisterMap());
+ ASSERT_FALSE(stack_map.HasInlineInfo());
}
TEST(StackMapTest, InlineTest) {
@@ -835,100 +827,99 @@ TEST(StackMapTest, InlineTest) {
stream.FillInCodeInfo(region);
CodeInfo ci(region);
- CodeInfoEncoding encoding = ci.ExtractEncoding();
{
// Verify first stack map.
- StackMap sm0 = ci.GetStackMapAt(0, encoding);
-
- 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, encoding);
- ASSERT_EQ(2u, if0.GetDepth(encoding.inline_info.encoding));
- ASSERT_EQ(2u, if0.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
- ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
- ASSERT_EQ(3u, if0.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
- ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
-
- 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, 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));
+ StackMap sm0 = ci.GetStackMapAt(0);
+
+ 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));
+
+ InlineInfo if0 = ci.GetInlineInfoOf(sm0);
+ ASSERT_EQ(2u, if0.GetDepth());
+ ASSERT_EQ(2u, if0.GetDexPcAtDepth(0));
+ ASSERT_TRUE(if0.EncodesArtMethodAtDepth(0));
+ ASSERT_EQ(3u, if0.GetDexPcAtDepth(1));
+ ASSERT_TRUE(if0.EncodesArtMethodAtDepth(1));
+
+ DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, 1);
+ ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
+
+ 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));
}
{
// Verify second stack map.
- StackMap sm1 = ci.GetStackMapAt(1, encoding);
-
- 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, encoding);
- ASSERT_EQ(3u, if1.GetDepth(encoding.inline_info.encoding));
- ASSERT_EQ(2u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
- ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
- ASSERT_EQ(3u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
- ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
- ASSERT_EQ(5u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 2));
- ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 2));
-
- 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, 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(encoding.inline_info.encoding, 2));
+ StackMap sm1 = ci.GetStackMapAt(1);
+
+ 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));
+
+ InlineInfo if1 = ci.GetInlineInfoOf(sm1);
+ ASSERT_EQ(3u, if1.GetDepth());
+ ASSERT_EQ(2u, if1.GetDexPcAtDepth(0));
+ ASSERT_TRUE(if1.EncodesArtMethodAtDepth(0));
+ ASSERT_EQ(3u, if1.GetDexPcAtDepth(1));
+ ASSERT_TRUE(if1.EncodesArtMethodAtDepth(1));
+ ASSERT_EQ(5u, if1.GetDexPcAtDepth(2));
+ ASSERT_TRUE(if1.EncodesArtMethodAtDepth(2));
+
+ DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, 1);
+ ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
+
+ 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));
+
+ ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(2));
}
{
// Verify third stack map.
- StackMap sm2 = ci.GetStackMapAt(2, encoding);
+ StackMap sm2 = ci.GetStackMapAt(2);
- DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, encoding, 2);
+ DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, 2);
ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
- ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
- ASSERT_FALSE(sm2.HasInlineInfo(encoding.stack_map.encoding));
+ ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci));
+ ASSERT_FALSE(sm2.HasInlineInfo());
}
{
// Verify fourth stack map.
- StackMap sm3 = ci.GetStackMapAt(3, encoding);
+ StackMap sm3 = ci.GetStackMapAt(3);
- 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));
+ 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));
- InlineInfo if2 = ci.GetInlineInfoOf(sm3, encoding);
- ASSERT_EQ(3u, if2.GetDepth(encoding.inline_info.encoding));
- ASSERT_EQ(2u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
- ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
- ASSERT_EQ(5u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
- ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
- ASSERT_EQ(10u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 2));
- ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 2));
+ InlineInfo if2 = ci.GetInlineInfoOf(sm3);
+ ASSERT_EQ(3u, if2.GetDepth());
+ ASSERT_EQ(2u, if2.GetDexPcAtDepth(0));
+ ASSERT_TRUE(if2.EncodesArtMethodAtDepth(0));
+ ASSERT_EQ(5u, if2.GetDexPcAtDepth(1));
+ ASSERT_TRUE(if2.EncodesArtMethodAtDepth(1));
+ ASSERT_EQ(10u, if2.GetDexPcAtDepth(2));
+ ASSERT_TRUE(if2.EncodesArtMethodAtDepth(2));
- ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, 0));
+ ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(0));
- DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, encoding, 1);
- ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci, encoding));
+ DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, 1);
+ ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci));
- DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, encoding, 2);
+ DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, 2);
ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
- ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci, encoding));
+ ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci));
}
}
TEST(StackMapTest, CodeOffsetTest) {
- // Test minimum alignments, encoding, and decoding.
+ // Test minimum alignments, and decoding.
CodeOffset offset_thumb2 =
CodeOffset::FromOffset(kThumb2InstructionAlignment, InstructionSet::kThumb2);
CodeOffset offset_arm64 =
@@ -969,13 +960,12 @@ TEST(StackMapTest, TestDeduplicateStackMask) {
stream.FillInCodeInfo(region);
CodeInfo code_info(region);
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
+ ASSERT_EQ(2u, code_info.GetNumberOfStackMaps());
- StackMap stack_map1 = code_info.GetStackMapForNativePcOffset(4, encoding);
- StackMap stack_map2 = code_info.GetStackMapForNativePcOffset(8, encoding);
- EXPECT_EQ(stack_map1.GetStackMaskIndex(encoding.stack_map.encoding),
- stack_map2.GetStackMaskIndex(encoding.stack_map.encoding));
+ StackMap stack_map1 = code_info.GetStackMapForNativePcOffset(4);
+ StackMap stack_map2 = code_info.GetStackMapForNativePcOffset(8);
+ EXPECT_EQ(stack_map1.GetStackMaskIndex(),
+ stack_map2.GetStackMaskIndex());
}
TEST(StackMapTest, TestInvokeInfo) {
@@ -1007,26 +997,25 @@ TEST(StackMapTest, TestInvokeInfo) {
CodeInfo code_info(code_info_region);
MethodInfo method_info(method_info_region.begin());
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- ASSERT_EQ(3u, code_info.GetNumberOfStackMaps(encoding));
+ ASSERT_EQ(3u, code_info.GetNumberOfStackMaps());
- InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4, encoding));
- InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8, encoding));
- InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16, encoding));
- InvokeInfo invoke_invalid(code_info.GetInvokeInfoForNativePcOffset(12, encoding));
+ InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4));
+ InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8));
+ InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16));
+ InvokeInfo invoke_invalid(code_info.GetInvokeInfoForNativePcOffset(12));
EXPECT_FALSE(invoke_invalid.IsValid()); // No entry for that index.
EXPECT_TRUE(invoke1.IsValid());
EXPECT_TRUE(invoke2.IsValid());
EXPECT_TRUE(invoke3.IsValid());
- EXPECT_EQ(invoke1.GetInvokeType(encoding.invoke_info.encoding), kSuper);
- EXPECT_EQ(invoke1.GetMethodIndex(encoding.invoke_info.encoding, method_info), 1u);
- EXPECT_EQ(invoke1.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 4u);
- EXPECT_EQ(invoke2.GetInvokeType(encoding.invoke_info.encoding), kStatic);
- EXPECT_EQ(invoke2.GetMethodIndex(encoding.invoke_info.encoding, method_info), 3u);
- EXPECT_EQ(invoke2.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 8u);
- EXPECT_EQ(invoke3.GetInvokeType(encoding.invoke_info.encoding), kDirect);
- EXPECT_EQ(invoke3.GetMethodIndex(encoding.invoke_info.encoding, method_info), 65535u);
- EXPECT_EQ(invoke3.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 16u);
+ EXPECT_EQ(invoke1.GetInvokeType(), kSuper);
+ EXPECT_EQ(invoke1.GetMethodIndex(method_info), 1u);
+ EXPECT_EQ(invoke1.GetNativePcOffset(kRuntimeISA), 4u);
+ EXPECT_EQ(invoke2.GetInvokeType(), kStatic);
+ EXPECT_EQ(invoke2.GetMethodIndex(method_info), 3u);
+ EXPECT_EQ(invoke2.GetNativePcOffset(kRuntimeISA), 8u);
+ EXPECT_EQ(invoke3.GetInvokeType(), kDirect);
+ EXPECT_EQ(invoke3.GetMethodIndex(method_info), 65535u);
+ EXPECT_EQ(invoke3.GetNativePcOffset(kRuntimeISA), 16u);
}
} // namespace art
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 692c97f1c0..adf0ad6376 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -150,6 +150,7 @@ art_cc_test {
"base/bit_memory_region_test.cc",
"base/bit_string_test.cc",
"base/bit_struct_test.cc",
+ "base/bit_table_test.cc",
"base/bit_utils_test.cc",
"base/bit_vector_test.cc",
"base/file_utils_test.cc",
diff --git a/libartbase/base/bit_memory_region.h b/libartbase/base/bit_memory_region.h
index dd16957340..3f4d0ba55b 100644
--- a/libartbase/base/bit_memory_region.h
+++ b/libartbase/base/bit_memory_region.h
@@ -99,6 +99,13 @@ class BitMemoryRegion FINAL : public ValueObject {
return value & mask;
}
+ // Load bits starting at given `bit_offset`, and advance the `bit_offset`.
+ ALWAYS_INLINE uint32_t LoadBitsAndAdvance(size_t* bit_offset, size_t bit_length) const {
+ uint32_t result = LoadBits(*bit_offset, bit_length);
+ *bit_offset += bit_length;
+ return result;
+ }
+
// Store `bit_length` bits in `data` starting at given `bit_offset`.
// The least significant bit is stored in the smallest memory offset.
ALWAYS_INLINE void StoreBits(size_t bit_offset, uint32_t value, size_t bit_length) {
@@ -125,6 +132,12 @@ class BitMemoryRegion FINAL : public ValueObject {
DCHECK_EQ(value, LoadBits(bit_offset, bit_length));
}
+ // Store bits starting at given `bit_offset`, and advance the `bit_offset`.
+ ALWAYS_INLINE void StoreBitsAndAdvance(size_t* bit_offset, uint32_t value, size_t bit_length) {
+ StoreBits(*bit_offset, value, bit_length);
+ *bit_offset += bit_length;
+ }
+
ALWAYS_INLINE bool Equals(const BitMemoryRegion& other) const {
return data_ == other.data_ &&
bit_start_ == other.bit_start_ &&
diff --git a/libartbase/base/bit_table.h b/libartbase/base/bit_table.h
new file mode 100644
index 0000000000..24bdd13324
--- /dev/null
+++ b/libartbase/base/bit_table.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_LIBARTBASE_BASE_BIT_TABLE_H_
+#define ART_LIBARTBASE_BASE_BIT_TABLE_H_
+
+#include <vector>
+
+#include "base/bit_memory_region.h"
+#include "base/bit_utils.h"
+#include "base/memory_region.h"
+
+namespace art {
+
+constexpr uint32_t kVarintHeaderBits = 4;
+constexpr uint32_t kVarintSmallValue = 11; // Maximum value which is stored as-is.
+
+// Load variable-length bit-packed integer from `data` starting at `bit_offset`.
+// The first four bits determine the variable length of the encoded integer:
+// Values 0..11 represent the result as-is, with no further following bits.
+// Values 12..15 mean the result is in the next 8/16/24/32-bits respectively.
+ALWAYS_INLINE static inline uint32_t DecodeVarintBits(BitMemoryRegion region, size_t* bit_offset) {
+ uint32_t x = region.LoadBitsAndAdvance(bit_offset, kVarintHeaderBits);
+ if (x > kVarintSmallValue) {
+ x = region.LoadBitsAndAdvance(bit_offset, (x - kVarintSmallValue) * kBitsPerByte);
+ }
+ return x;
+}
+
+// Store variable-length bit-packed integer from `data` starting at `bit_offset`.
+template<typename Vector>
+ALWAYS_INLINE static inline void EncodeVarintBits(Vector* out, size_t* bit_offset, uint32_t value) {
+ if (value <= kVarintSmallValue) {
+ out->resize(BitsToBytesRoundUp(*bit_offset + kVarintHeaderBits));
+ BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
+ region.StoreBitsAndAdvance(bit_offset, value, kVarintHeaderBits);
+ } else {
+ uint32_t num_bits = RoundUp(MinimumBitsToStore(value), kBitsPerByte);
+ out->resize(BitsToBytesRoundUp(*bit_offset + kVarintHeaderBits + num_bits));
+ BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
+ uint32_t header = kVarintSmallValue + num_bits / kBitsPerByte;
+ region.StoreBitsAndAdvance(bit_offset, header, kVarintHeaderBits);
+ region.StoreBitsAndAdvance(bit_offset, value, num_bits);
+ }
+}
+
+template<uint32_t kNumColumns>
+class BitTable {
+ public:
+ class Accessor {
+ public:
+ static constexpr uint32_t kNoValue = std::numeric_limits<uint32_t>::max();
+
+ Accessor(const BitTable* table, uint32_t row) : table_(table), row_(row) {}
+
+ ALWAYS_INLINE uint32_t Row() const { return row_; }
+
+ ALWAYS_INLINE bool IsValid() const { return table_ != nullptr && row_ < table_->NumRows(); }
+
+ template<uint32_t Column>
+ ALWAYS_INLINE uint32_t Get() const {
+ static_assert(Column < kNumColumns, "Column out of bounds");
+ return table_->Get(row_, Column);
+ }
+
+ ALWAYS_INLINE bool Equals(const Accessor& other) {
+ return this->table_ == other.table_ && this->row_ == other.row_;
+ }
+
+ Accessor& operator++() {
+ row_++;
+ return *this;
+ }
+
+ protected:
+ const BitTable* table_;
+ uint32_t row_;
+ };
+
+ static constexpr uint32_t kValueBias = -1;
+
+ BitTable() {}
+ BitTable(void* data, size_t size, size_t* bit_offset = 0) {
+ Decode(BitMemoryRegion(MemoryRegion(data, size)), bit_offset);
+ }
+
+ ALWAYS_INLINE void Decode(BitMemoryRegion region, size_t* bit_offset) {
+ // Decode row count and column sizes from the table header.
+ num_rows_ = DecodeVarintBits(region, bit_offset);
+ if (num_rows_ != 0) {
+ column_offset_[0] = 0;
+ for (uint32_t i = 0; i < kNumColumns; i++) {
+ size_t column_end = column_offset_[i] + DecodeVarintBits(region, bit_offset);
+ column_offset_[i + 1] = column_end;
+ DCHECK_EQ(column_offset_[i + 1], column_end) << "Overflow";
+ }
+ }
+
+ // Record the region which contains the table data and skip past it.
+ table_data_ = region.Subregion(*bit_offset, num_rows_ * NumRowBits());
+ *bit_offset += table_data_.size_in_bits();
+ }
+
+ ALWAYS_INLINE uint32_t Get(uint32_t row, uint32_t column = 0) const {
+ DCHECK_LT(row, num_rows_);
+ DCHECK_LT(column, kNumColumns);
+ size_t offset = row * NumRowBits() + column_offset_[column];
+ return table_data_.LoadBits(offset, NumColumnBits(column)) + kValueBias;
+ }
+
+ size_t NumRows() const { return num_rows_; }
+
+ uint32_t NumRowBits() const { return column_offset_[kNumColumns]; }
+
+ constexpr size_t NumColumns() const { return kNumColumns; }
+
+ uint32_t NumColumnBits(uint32_t column) const {
+ return column_offset_[column + 1] - column_offset_[column];
+ }
+
+ size_t DataBitSize() const { return num_rows_ * column_offset_[kNumColumns]; }
+
+ protected:
+ BitMemoryRegion table_data_;
+ size_t num_rows_ = 0;
+
+ uint16_t column_offset_[kNumColumns + 1] = {};
+};
+
+template<uint32_t kNumColumns>
+constexpr uint32_t BitTable<kNumColumns>::Accessor::kNoValue;
+
+template<uint32_t kNumColumns>
+constexpr uint32_t BitTable<kNumColumns>::kValueBias;
+
+template<uint32_t kNumColumns, typename Alloc = std::allocator<uint32_t>>
+class BitTableBuilder {
+ public:
+ explicit BitTableBuilder(Alloc alloc = Alloc()) : buffer_(alloc) {}
+
+ template<typename ... T>
+ uint32_t AddRow(T ... values) {
+ constexpr size_t count = sizeof...(values);
+ static_assert(count == kNumColumns, "Incorrect argument count");
+ uint32_t data[count] = { values... };
+ buffer_.insert(buffer_.end(), data, data + count);
+ return num_rows_++;
+ }
+
+ ALWAYS_INLINE uint32_t Get(uint32_t row, uint32_t column) const {
+ return buffer_[row * kNumColumns + column];
+ }
+
+ template<typename Vector>
+ void Encode(Vector* out, size_t* bit_offset) {
+ constexpr uint32_t bias = BitTable<kNumColumns>::kValueBias;
+ size_t initial_bit_offset = *bit_offset;
+ // Measure data size.
+ uint32_t max_column_value[kNumColumns] = {};
+ for (uint32_t r = 0; r < num_rows_; r++) {
+ for (uint32_t c = 0; c < kNumColumns; c++) {
+ max_column_value[c] |= Get(r, c) - bias;
+ }
+ }
+ // Write table header.
+ uint32_t table_data_bits = 0;
+ uint32_t column_bits[kNumColumns] = {};
+ EncodeVarintBits(out, bit_offset, num_rows_);
+ if (num_rows_ != 0) {
+ for (uint32_t c = 0; c < kNumColumns; c++) {
+ column_bits[c] = MinimumBitsToStore(max_column_value[c]);
+ EncodeVarintBits(out, bit_offset, column_bits[c]);
+ table_data_bits += num_rows_ * column_bits[c];
+ }
+ }
+ // Write table data.
+ out->resize(BitsToBytesRoundUp(*bit_offset + table_data_bits));
+ BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
+ for (uint32_t r = 0; r < num_rows_; r++) {
+ for (uint32_t c = 0; c < kNumColumns; c++) {
+ region.StoreBitsAndAdvance(bit_offset, Get(r, c) - bias, column_bits[c]);
+ }
+ }
+ // Verify the written data.
+ if (kIsDebugBuild) {
+ BitTable<kNumColumns> table;
+ table.Decode(region, &initial_bit_offset);
+ DCHECK_EQ(this->num_rows_, table.NumRows());
+ for (uint32_t c = 0; c < kNumColumns; c++) {
+ DCHECK_EQ(column_bits[c], table.NumColumnBits(c));
+ }
+ for (uint32_t r = 0; r < num_rows_; r++) {
+ for (uint32_t c = 0; c < kNumColumns; c++) {
+ DCHECK_EQ(this->Get(r, c), table.Get(r, c)) << " (" << r << ", " << c << ")";
+ }
+ }
+ }
+ }
+
+ protected:
+ std::vector<uint32_t, Alloc> buffer_;
+ uint32_t num_rows_ = 0;
+};
+
+} // namespace art
+
+#endif // ART_LIBARTBASE_BASE_BIT_TABLE_H_
diff --git a/libartbase/base/bit_table_test.cc b/libartbase/base/bit_table_test.cc
new file mode 100644
index 0000000000..25bfcf095e
--- /dev/null
+++ b/libartbase/base/bit_table_test.cc
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bit_table.h"
+
+#include "gtest/gtest.h"
+
+namespace art {
+
+TEST(BitTableTest, TestVarint) {
+ for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
+ uint32_t values[] = { 0, 1, 11, 12, 15, 16, 255, 256, ~1u, ~0u };
+ for (uint32_t value : values) {
+ std::vector<uint8_t> buffer;
+ size_t encode_bit_offset = start_bit_offset;
+ EncodeVarintBits(&buffer, &encode_bit_offset, value);
+
+ size_t decode_bit_offset = start_bit_offset;
+ BitMemoryRegion region(MemoryRegion(buffer.data(), buffer.size()));
+ uint32_t result = DecodeVarintBits(region, &decode_bit_offset);
+ EXPECT_EQ(encode_bit_offset, decode_bit_offset);
+ EXPECT_EQ(value, result);
+ }
+ }
+}
+
+TEST(BitTableTest, TestEmptyTable) {
+ std::vector<uint8_t> buffer;
+ size_t encode_bit_offset = 0;
+ BitTableBuilder<1> builder;
+ builder.Encode(&buffer, &encode_bit_offset);
+
+ size_t decode_bit_offset = 0;
+ BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
+ EXPECT_EQ(encode_bit_offset, decode_bit_offset);
+ EXPECT_EQ(0u, table.NumRows());
+}
+
+TEST(BitTableTest, TestSingleColumnTable) {
+ constexpr uint32_t kNoValue = -1;
+ std::vector<uint8_t> buffer;
+ size_t encode_bit_offset = 0;
+ BitTableBuilder<1> builder;
+ builder.AddRow(42u);
+ builder.AddRow(kNoValue);
+ builder.AddRow(1000u);
+ builder.AddRow(kNoValue);
+ builder.Encode(&buffer, &encode_bit_offset);
+
+ size_t decode_bit_offset = 0;
+ BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
+ EXPECT_EQ(encode_bit_offset, decode_bit_offset);
+ EXPECT_EQ(4u, table.NumRows());
+ EXPECT_EQ(42u, table.Get(0));
+ EXPECT_EQ(kNoValue, table.Get(1));
+ EXPECT_EQ(1000u, table.Get(2));
+ EXPECT_EQ(kNoValue, table.Get(3));
+ EXPECT_EQ(10u, table.NumColumnBits(0));
+}
+
+TEST(BitTableTest, TestUnalignedTable) {
+ for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
+ std::vector<uint8_t> buffer;
+ size_t encode_bit_offset = start_bit_offset;
+ BitTableBuilder<1> builder;
+ builder.AddRow(42u);
+ builder.Encode(&buffer, &encode_bit_offset);
+
+ size_t decode_bit_offset = start_bit_offset;
+ BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
+ EXPECT_EQ(encode_bit_offset, decode_bit_offset) << " start_bit_offset=" << start_bit_offset;
+ EXPECT_EQ(1u, table.NumRows());
+ EXPECT_EQ(42u, table.Get(0));
+ }
+}
+
+TEST(BitTableTest, TestBigTable) {
+ constexpr uint32_t kNoValue = -1;
+ std::vector<uint8_t> buffer;
+ size_t encode_bit_offset = 0;
+ BitTableBuilder<4> builder;
+ builder.AddRow(42u, kNoValue, 0u, static_cast<uint32_t>(-2));
+ builder.AddRow(62u, kNoValue, 63u, static_cast<uint32_t>(-3));
+ builder.Encode(&buffer, &encode_bit_offset);
+
+ size_t decode_bit_offset = 0;
+ BitTable<4> table(buffer.data(), buffer.size(), &decode_bit_offset);
+ EXPECT_EQ(encode_bit_offset, decode_bit_offset);
+ EXPECT_EQ(2u, table.NumRows());
+ EXPECT_EQ(42u, table.Get(0, 0));
+ EXPECT_EQ(kNoValue, table.Get(0, 1));
+ EXPECT_EQ(0u, table.Get(0, 2));
+ EXPECT_EQ(static_cast<uint32_t>(-2), table.Get(0, 3));
+ EXPECT_EQ(62u, table.Get(1, 0));
+ EXPECT_EQ(kNoValue, table.Get(1, 1));
+ EXPECT_EQ(63u, table.Get(1, 2));
+ EXPECT_EQ(static_cast<uint32_t>(-3), table.Get(1, 3));
+ EXPECT_EQ(6u, table.NumColumnBits(0));
+ EXPECT_EQ(0u, table.NumColumnBits(1));
+ EXPECT_EQ(7u, table.NumColumnBits(2));
+ EXPECT_EQ(32u, table.NumColumnBits(3));
+}
+
+} // namespace art
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 44050ff8ed..5c20efa3f7 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -753,7 +753,7 @@ class OatDumper {
kByteKindQuickMethodHeader,
kByteKindCodeInfoLocationCatalog,
kByteKindCodeInfoDexRegisterMap,
- kByteKindCodeInfoEncoding,
+ kByteKindCodeInfo,
kByteKindCodeInfoInvokeInfo,
kByteKindCodeInfoStackMasks,
kByteKindCodeInfoRegisterMasks,
@@ -800,7 +800,7 @@ class OatDumper {
if (sum > 0) {
Dump(os, "Code ", bits[kByteKindCode], sum);
Dump(os, "QuickMethodHeader ", bits[kByteKindQuickMethodHeader], sum);
- Dump(os, "CodeInfoEncoding ", bits[kByteKindCodeInfoEncoding], sum);
+ Dump(os, "CodeInfo ", bits[kByteKindCodeInfo], sum);
Dump(os, "CodeInfoLocationCatalog ", bits[kByteKindCodeInfoLocationCatalog], sum);
Dump(os, "CodeInfoDexRegisterMap ", bits[kByteKindCodeInfoDexRegisterMap], sum);
Dump(os, "CodeInfoStackMasks ", bits[kByteKindCodeInfoStackMasks], sum);
@@ -819,7 +819,7 @@ class OatDumper {
stack_map_bits,
"stack map");
Dump(os,
- "StackMapDexPcEncoding ",
+ "StackMapDexPc ",
bits[kByteKindStackMapDexPc],
stack_map_bits,
"stack map");
@@ -1732,8 +1732,7 @@ class OatDumper {
public:
explicit StackMapsHelper(const uint8_t* raw_code_info, InstructionSet instruction_set)
: code_info_(raw_code_info),
- encoding_(code_info_.ExtractEncoding()),
- number_of_stack_maps_(code_info_.GetNumberOfStackMaps(encoding_)),
+ number_of_stack_maps_(code_info_.GetNumberOfStackMaps()),
indexes_(),
offset_(static_cast<uint32_t>(-1)),
stack_map_index_(0u),
@@ -1741,11 +1740,11 @@ class OatDumper {
if (number_of_stack_maps_ != 0u) {
// Check if native PCs are ordered.
bool ordered = true;
- StackMap last = code_info_.GetStackMapAt(0u, encoding_);
+ StackMap last = code_info_.GetStackMapAt(0u);
for (size_t i = 1; i != number_of_stack_maps_; ++i) {
- StackMap current = code_info_.GetStackMapAt(i, encoding_);
- if (last.GetNativePcOffset(encoding_.stack_map.encoding, instruction_set) >
- current.GetNativePcOffset(encoding_.stack_map.encoding, instruction_set)) {
+ StackMap current = code_info_.GetStackMapAt(i);
+ if (last.GetNativePcOffset(instruction_set) >
+ current.GetNativePcOffset(instruction_set)) {
ordered = false;
break;
}
@@ -1760,18 +1759,15 @@ class OatDumper {
std::sort(indexes_.begin(),
indexes_.end(),
[this](size_t lhs, size_t rhs) {
- StackMap left = code_info_.GetStackMapAt(lhs, encoding_);
- uint32_t left_pc = left.GetNativePcOffset(encoding_.stack_map.encoding,
- instruction_set_);
- StackMap right = code_info_.GetStackMapAt(rhs, encoding_);
- uint32_t right_pc = right.GetNativePcOffset(encoding_.stack_map.encoding,
- instruction_set_);
+ StackMap left = code_info_.GetStackMapAt(lhs);
+ uint32_t left_pc = left.GetNativePcOffset(instruction_set_);
+ StackMap right = code_info_.GetStackMapAt(rhs);
+ uint32_t right_pc = right.GetNativePcOffset(instruction_set_);
// If the PCs are the same, compare indexes to preserve the original order.
return (left_pc < right_pc) || (left_pc == right_pc && lhs < rhs);
});
}
- offset_ = GetStackMapAt(0).GetNativePcOffset(encoding_.stack_map.encoding,
- instruction_set_);
+ offset_ = GetStackMapAt(0).GetNativePcOffset(instruction_set_);
}
}
@@ -1779,10 +1775,6 @@ class OatDumper {
return code_info_;
}
- const CodeInfoEncoding& GetEncoding() const {
- return encoding_;
- }
-
uint32_t GetOffset() const {
return offset_;
}
@@ -1795,8 +1787,7 @@ class OatDumper {
++stack_map_index_;
offset_ = (stack_map_index_ == number_of_stack_maps_)
? static_cast<uint32_t>(-1)
- : GetStackMapAt(stack_map_index_).GetNativePcOffset(encoding_.stack_map.encoding,
- instruction_set_);
+ : GetStackMapAt(stack_map_index_).GetNativePcOffset(instruction_set_);
}
private:
@@ -1805,11 +1796,10 @@ class OatDumper {
i = indexes_[i];
}
DCHECK_LT(i, number_of_stack_maps_);
- return code_info_.GetStackMapAt(i, encoding_);
+ return code_info_.GetStackMapAt(i);
}
const CodeInfo code_info_;
- const CodeInfoEncoding encoding_;
const size_t number_of_stack_maps_;
dchecked_vector<size_t> indexes_; // Used if stack map native PCs are not ordered.
uint32_t offset_;
@@ -1835,79 +1825,75 @@ class OatDumper {
StackMapsHelper helper(oat_method.GetVmapTable(), instruction_set_);
MethodInfo method_info(oat_method.GetOatQuickMethodHeader()->GetOptimizedMethodInfo());
{
- CodeInfoEncoding encoding(helper.GetEncoding());
- StackMapEncoding stack_map_encoding(encoding.stack_map.encoding);
- const size_t num_stack_maps = encoding.stack_map.num_entries;
- if (stats_.AddBitsIfUnique(Stats::kByteKindCodeInfoEncoding,
- encoding.HeaderSize() * kBitsPerByte,
+ const CodeInfo code_info = helper.GetCodeInfo();
+ const BitTable<StackMap::kCount>& stack_maps = code_info.stack_maps_;
+ const size_t num_stack_maps = stack_maps.NumRows();
+ if (stats_.AddBitsIfUnique(Stats::kByteKindCodeInfo,
+ code_info.size_ * kBitsPerByte,
oat_method.GetVmapTable())) {
// Stack maps
stats_.AddBits(
Stats::kByteKindStackMapNativePc,
- stack_map_encoding.GetNativePcEncoding().BitSize() * num_stack_maps);
+ stack_maps.NumColumnBits(StackMap::kNativePcOffset) * num_stack_maps);
stats_.AddBits(
Stats::kByteKindStackMapDexPc,
- stack_map_encoding.GetDexPcEncoding().BitSize() * num_stack_maps);
+ stack_maps.NumColumnBits(StackMap::kDexPc) * num_stack_maps);
stats_.AddBits(
Stats::kByteKindStackMapDexRegisterMap,
- stack_map_encoding.GetDexRegisterMapEncoding().BitSize() * num_stack_maps);
+ stack_maps.NumColumnBits(StackMap::kDexRegisterMapOffset) * num_stack_maps);
stats_.AddBits(
Stats::kByteKindStackMapInlineInfoIndex,
- stack_map_encoding.GetInlineInfoEncoding().BitSize() * num_stack_maps);
+ stack_maps.NumColumnBits(StackMap::kInlineInfoIndex) * num_stack_maps);
stats_.AddBits(
Stats::kByteKindStackMapRegisterMaskIndex,
- stack_map_encoding.GetRegisterMaskIndexEncoding().BitSize() * num_stack_maps);
+ stack_maps.NumColumnBits(StackMap::kRegisterMaskIndex) * num_stack_maps);
stats_.AddBits(
Stats::kByteKindStackMapStackMaskIndex,
- stack_map_encoding.GetStackMaskIndexEncoding().BitSize() * num_stack_maps);
+ stack_maps.NumColumnBits(StackMap::kStackMaskIndex) * num_stack_maps);
// Stack masks
stats_.AddBits(
Stats::kByteKindCodeInfoStackMasks,
- encoding.stack_mask.encoding.BitSize() * encoding.stack_mask.num_entries);
+ code_info.stack_masks_.size_in_bits());
// Register masks
stats_.AddBits(
Stats::kByteKindCodeInfoRegisterMasks,
- encoding.register_mask.encoding.BitSize() * encoding.register_mask.num_entries);
+ code_info.register_masks_.DataBitSize());
// Invoke infos
- if (encoding.invoke_info.num_entries > 0u) {
- stats_.AddBits(
- Stats::kByteKindCodeInfoInvokeInfo,
- encoding.invoke_info.encoding.BitSize() * encoding.invoke_info.num_entries);
- }
+ stats_.AddBits(
+ Stats::kByteKindCodeInfoInvokeInfo,
+ code_info.invoke_infos_.DataBitSize());
// Location catalog
const size_t location_catalog_bytes =
- helper.GetCodeInfo().GetDexRegisterLocationCatalogSize(encoding);
+ helper.GetCodeInfo().GetDexRegisterLocationCatalogSize();
stats_.AddBits(Stats::kByteKindCodeInfoLocationCatalog,
kBitsPerByte * location_catalog_bytes);
// Dex register bytes.
const size_t dex_register_bytes =
- helper.GetCodeInfo().GetDexRegisterMapsSize(encoding,
- code_item_accessor.RegistersSize());
+ helper.GetCodeInfo().GetDexRegisterMapsSize(code_item_accessor.RegistersSize());
stats_.AddBits(
Stats::kByteKindCodeInfoDexRegisterMap,
kBitsPerByte * dex_register_bytes);
// Inline infos.
- const size_t num_inline_infos = encoding.inline_info.num_entries;
+ const BitTable<InlineInfo::kCount>& inline_infos = code_info.inline_infos_;
+ const size_t num_inline_infos = inline_infos.NumRows();
if (num_inline_infos > 0u) {
stats_.AddBits(
Stats::kByteKindInlineInfoMethodIndexIdx,
- encoding.inline_info.encoding.GetMethodIndexIdxEncoding().BitSize() *
- num_inline_infos);
+ inline_infos.NumColumnBits(InlineInfo::kMethodIndexIdx) * num_inline_infos);
stats_.AddBits(
Stats::kByteKindInlineInfoDexPc,
- encoding.inline_info.encoding.GetDexPcEncoding().BitSize() * num_inline_infos);
+ inline_infos.NumColumnBits(InlineInfo::kDexPc) * num_inline_infos);
stats_.AddBits(
Stats::kByteKindInlineInfoExtraData,
- encoding.inline_info.encoding.GetExtraDataEncoding().BitSize() * num_inline_infos);
+ inline_infos.NumColumnBits(InlineInfo::kExtraData) * num_inline_infos);
stats_.AddBits(
Stats::kByteKindInlineInfoDexRegisterMap,
- encoding.inline_info.encoding.GetDexRegisterMapEncoding().BitSize() *
- num_inline_infos);
+ inline_infos.NumColumnBits(InlineInfo::kDexRegisterMapOffset) * num_inline_infos);
stats_.AddBits(Stats::kByteKindInlineInfoIsLast, num_inline_infos);
}
}
@@ -1922,7 +1908,6 @@ class OatDumper {
DCHECK(stack_map.IsValid());
stack_map.Dump(vios,
helper.GetCodeInfo(),
- helper.GetEncoding(),
method_info,
oat_method.GetCodeOffset(),
code_item_accessor.RegistersSize(),
diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h
index b85730d25e..bbe89ca33c 100644
--- a/oatdump/oatdump_test.h
+++ b/oatdump/oatdump_test.h
@@ -162,7 +162,6 @@ class OatDumpTest : public CommonRuntimeTest {
// Code and dex code do not show up if list only.
expected_prefixes.push_back("DEX CODE:");
expected_prefixes.push_back("CODE:");
- expected_prefixes.push_back("CodeInfoEncoding");
expected_prefixes.push_back("CodeInfoInlineInfo");
}
if (mode == kModeArt) {
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index e2ad7fd83f..6917899bff 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -64,20 +64,19 @@ class CheckReferenceMapVisitor : public StackVisitor {
void CheckOptimizedMethod(int* registers, int number_of_references, uint32_t native_pc_offset)
REQUIRES_SHARED(Locks::mutator_lock_) {
ArtMethod* m = GetMethod();
- CodeInfo code_info = GetCurrentOatQuickMethodHeader()->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
+ CodeInfo code_info(GetCurrentOatQuickMethodHeader());
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
CodeItemDataAccessor accessor(m->DexInstructionData());
uint16_t number_of_dex_registers = accessor.RegistersSize();
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
- uint32_t register_mask = code_info.GetRegisterMaskOf(encoding, stack_map);
- BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
+ code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+ uint32_t register_mask = code_info.GetRegisterMaskOf(stack_map);
+ BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
for (int i = 0; i < number_of_references; ++i) {
int reg = registers[i];
CHECK_LT(reg, accessor.RegistersSize());
DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(
- reg, number_of_dex_registers, code_info, encoding);
+ reg, number_of_dex_registers, code_info);
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 d4e7492f00..f6b1c73230 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -47,7 +47,6 @@ namespace art {
inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
const MethodInfo& method_info,
const InlineInfo& inline_info,
- const InlineInfoEncoding& encoding,
uint8_t inlining_depth)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(!outer_method->IsObsolete());
@@ -57,12 +56,12 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
// suspended while executing it.
ScopedAssertNoThreadSuspension sants(__FUNCTION__);
- if (inline_info.EncodesArtMethodAtDepth(encoding, inlining_depth)) {
- return inline_info.GetArtMethodAtDepth(encoding, inlining_depth);
+ if (inline_info.EncodesArtMethodAtDepth(inlining_depth)) {
+ return inline_info.GetArtMethodAtDepth(inlining_depth);
}
- uint32_t method_index = inline_info.GetMethodIndexAtDepth(encoding, method_info, inlining_depth);
- if (inline_info.GetDexPcAtDepth(encoding, inlining_depth) == static_cast<uint32_t>(-1)) {
+ uint32_t method_index = inline_info.GetMethodIndexAtDepth(method_info, inlining_depth);
+ if (inline_info.GetDexPcAtDepth(inlining_depth) == static_cast<uint32_t>(-1)) {
// "charAt" special case. It is the only non-leaf method we inline across dex files.
ArtMethod* inlined_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt);
DCHECK_EQ(inlined_method->GetDexMethodIndex(), method_index);
@@ -73,9 +72,9 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
ArtMethod* method = outer_method;
for (uint32_t depth = 0, end = inlining_depth + 1u; depth != end; ++depth) {
- DCHECK(!inline_info.EncodesArtMethodAtDepth(encoding, depth));
- DCHECK_NE(inline_info.GetDexPcAtDepth(encoding, depth), static_cast<uint32_t>(-1));
- method_index = inline_info.GetMethodIndexAtDepth(encoding, method_info, depth);
+ DCHECK(!inline_info.EncodesArtMethodAtDepth(depth));
+ DCHECK_NE(inline_info.GetDexPcAtDepth(depth), static_cast<uint32_t>(-1));
+ method_index = inline_info.GetMethodIndexAtDepth(method_info, depth);
ArtMethod* inlined_method = class_linker->LookupResolvedMethod(method_index,
method->GetDexCache(),
method->GetClassLoader());
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 7fc8db375b..91faa40df9 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -201,18 +201,16 @@ static inline ArtMethod* DoGetCalleeSaveMethodCaller(ArtMethod* outer_method,
DCHECK(current_code != nullptr);
DCHECK(current_code->IsOptimized());
uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc);
- CodeInfo code_info = current_code->GetOptimizedCodeInfo();
+ CodeInfo code_info(current_code);
MethodInfo method_info = current_code->GetOptimizedMethodInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
DCHECK(stack_map.IsValid());
- if (stack_map.HasInlineInfo(encoding.stack_map.encoding)) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
+ if (stack_map.HasInlineInfo()) {
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
caller = GetResolvedMethod(outer_method,
method_info,
inline_info,
- encoding.inline_info.encoding,
- inline_info.GetDepth(encoding.inline_info.encoding) - 1);
+ inline_info.GetDepth() - 1);
}
}
if (kIsDebugBuild && do_caller_check) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 0a186f4dc5..e83bcd812b 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -356,16 +356,14 @@ class QuickArgumentVisitor {
uintptr_t outer_pc_offset = current_code->NativeQuickPcOffset(outer_pc);
if (current_code->IsOptimized()) {
- CodeInfo code_info = current_code->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset, encoding);
+ CodeInfo code_info(current_code);
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset);
DCHECK(stack_map.IsValid());
- if (stack_map.HasInlineInfo(encoding.stack_map.encoding)) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- return inline_info.GetDexPcAtDepth(encoding.inline_info.encoding,
- inline_info.GetDepth(encoding.inline_info.encoding)-1);
+ if (stack_map.HasInlineInfo()) {
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+ return inline_info.GetDexPcAtDepth(inline_info.GetDepth()-1);
} else {
- return stack_map.GetDexPc(encoding.stack_map.encoding);
+ return stack_map.GetDexPc();
}
} else {
return current_code->ToDexPc(*caller_sp, outer_pc);
@@ -385,13 +383,12 @@ class QuickArgumentVisitor {
return false;
}
uintptr_t outer_pc_offset = current_code->NativeQuickPcOffset(outer_pc);
- CodeInfo code_info = current_code->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
+ CodeInfo code_info(current_code);
MethodInfo method_info = current_code->GetOptimizedMethodInfo();
- InvokeInfo invoke(code_info.GetInvokeInfoForNativePcOffset(outer_pc_offset, encoding));
+ InvokeInfo invoke(code_info.GetInvokeInfoForNativePcOffset(outer_pc_offset));
if (invoke.IsValid()) {
- *invoke_type = static_cast<InvokeType>(invoke.GetInvokeType(encoding.invoke_info.encoding));
- *dex_method_index = invoke.GetMethodIndex(encoding.invoke_info.encoding, method_info);
+ *invoke_type = static_cast<InvokeType>(invoke.GetInvokeType());
+ *dex_method_index = invoke.GetMethodIndex(method_info);
return true;
}
return false;
@@ -1230,12 +1227,11 @@ static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutato
CHECK(current_code != nullptr);
CHECK(current_code->IsOptimized());
uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc);
- CodeInfo code_info = current_code->GetOptimizedCodeInfo();
+ CodeInfo code_info(current_code);
MethodInfo method_info = current_code->GetOptimizedMethodInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
CHECK(stack_map.IsValid());
- uint32_t dex_pc = stack_map.GetDexPc(encoding.stack_map.encoding);
+ uint32_t dex_pc = stack_map.GetDexPc();
// Log the outer method and its associated dex file and class table pointer which can be used
// to find out if the inlined methods were defined by other dex file(s) or class loader(s).
@@ -1249,20 +1245,17 @@ static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutato
LOG(FATAL_WITHOUT_ABORT) << " instruction: " << DumpInstruction(outer_method, dex_pc);
ArtMethod* caller = outer_method;
- if (stack_map.HasInlineInfo(encoding.stack_map.encoding)) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
- const InlineInfoEncoding& inline_info_encoding = encoding.inline_info.encoding;
- size_t depth = inline_info.GetDepth(inline_info_encoding);
+ if (stack_map.HasInlineInfo()) {
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+ size_t depth = inline_info.GetDepth();
for (size_t d = 0; d < depth; ++d) {
const char* tag = "";
- dex_pc = inline_info.GetDexPcAtDepth(inline_info_encoding, d);
- if (inline_info.EncodesArtMethodAtDepth(inline_info_encoding, d)) {
+ dex_pc = inline_info.GetDexPcAtDepth(d);
+ if (inline_info.EncodesArtMethodAtDepth(d)) {
tag = "encoded ";
- caller = inline_info.GetArtMethodAtDepth(inline_info_encoding, d);
+ caller = inline_info.GetArtMethodAtDepth(d);
} else {
- uint32_t method_index = inline_info.GetMethodIndexAtDepth(inline_info_encoding,
- method_info,
- d);
+ uint32_t method_index = inline_info.GetMethodIndexAtDepth(method_info, d);
if (dex_pc == static_cast<uint32_t>(-1)) {
tag = "special ";
CHECK_EQ(d + 1u, depth);
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 86e69f49a4..5d4b9e8cc9 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -473,11 +473,10 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
return false;
}
- CodeInfo code_info = osr_method->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
+ CodeInfo code_info(osr_method);
// Find stack map starting at the target dex_pc.
- StackMap stack_map = code_info.GetOsrStackMapForDexPc(dex_pc + dex_pc_offset, encoding);
+ StackMap stack_map = code_info.GetOsrStackMapForDexPc(dex_pc + dex_pc_offset);
if (!stack_map.IsValid()) {
// There is no OSR stack map for this dex pc offset. Just return to the interpreter in the
// hope that the next branch has one.
@@ -494,7 +493,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
// We found a stack map, now fill the frame with dex register values from the interpreter's
// shadow frame.
DexRegisterMap vreg_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs);
+ code_info.GetDexRegisterMapOf(stack_map, number_of_vregs);
frame_size = osr_method->GetFrameSizeInBytes();
@@ -516,7 +515,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
} else {
for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
DexRegisterLocation::Kind location =
- vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding);
+ vreg_map.GetLocationKind(vreg, number_of_vregs, code_info);
if (location == DexRegisterLocation::Kind::kNone) {
// Dex register is dead or uninitialized.
continue;
@@ -532,15 +531,14 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
int32_t vreg_value = shadow_frame->GetVReg(vreg);
int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg,
number_of_vregs,
- code_info,
- encoding);
+ code_info);
DCHECK_LT(slot_offset, static_cast<int32_t>(frame_size));
DCHECK_GT(slot_offset, 0);
(reinterpret_cast<int32_t*>(memory))[slot_offset / sizeof(int32_t)] = vreg_value;
}
}
- native_pc = stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA) +
+ native_pc = stack_map.GetNativePcOffset(kRuntimeISA) +
osr_method->GetEntryPoint();
VLOG(jit) << "Jumping to "
<< method_name
diff --git a/runtime/oat.h b/runtime/oat.h
index 6c683f1541..7b8f71a3f3 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@ class InstructionSetFeatures;
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- // Last oat version changed reason: compiler support const-method-handle
- static constexpr uint8_t kOatVersion[] = { '1', '4', '3', '\0' };
+ // Last oat version changed reason: Refactor stackmap encoding.
+ static constexpr uint8_t kOatVersion[] = { '1', '4', '4', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/oat_quick_method_header.cc b/runtime/oat_quick_method_header.cc
index 98238e5600..aed6bc57b3 100644
--- a/runtime/oat_quick_method_header.cc
+++ b/runtime/oat_quick_method_header.cc
@@ -19,6 +19,7 @@
#include "art_method.h"
#include "dex/dex_file_types.h"
#include "scoped_thread_state_change-inl.h"
+#include "stack_map.h"
#include "thread.h"
namespace art {
@@ -42,11 +43,10 @@ uint32_t OatQuickMethodHeader::ToDexPc(ArtMethod* method,
const void* entry_point = GetEntryPoint();
uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(entry_point);
if (IsOptimized()) {
- CodeInfo code_info = GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset, encoding);
+ CodeInfo code_info(this);
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset);
if (stack_map.IsValid()) {
- return stack_map.GetDexPc(encoding.stack_map.encoding);
+ return stack_map.GetDexPc();
}
} else {
DCHECK(method->IsNative());
@@ -71,18 +71,17 @@ uintptr_t OatQuickMethodHeader::ToNativeQuickPc(ArtMethod* method,
DCHECK(!method->IsNative());
DCHECK(IsOptimized());
// Search for the dex-to-pc mapping in stack maps.
- CodeInfo code_info = GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
+ CodeInfo code_info(this);
// All stack maps are stored in the same CodeItem section, safepoint stack
// maps first, then catch stack maps. We use `is_for_catch_handler` to select
// the order of iteration.
StackMap stack_map =
- LIKELY(is_for_catch_handler) ? code_info.GetCatchStackMapForDexPc(dex_pc, encoding)
- : code_info.GetStackMapForDexPc(dex_pc, encoding);
+ LIKELY(is_for_catch_handler) ? code_info.GetCatchStackMapForDexPc(dex_pc)
+ : code_info.GetStackMapForDexPc(dex_pc);
if (stack_map.IsValid()) {
return reinterpret_cast<uintptr_t>(entry_point) +
- stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA);
+ stack_map.GetNativePcOffset(kRuntimeISA);
}
if (abort_on_failure) {
ScopedObjectAccess soa(Thread::Current());
diff --git a/runtime/oat_quick_method_header.h b/runtime/oat_quick_method_header.h
index f0966b7bfa..d6762d6bc6 100644
--- a/runtime/oat_quick_method_header.h
+++ b/runtime/oat_quick_method_header.h
@@ -22,7 +22,6 @@
#include "base/utils.h"
#include "method_info.h"
#include "quick/quick_method_frame_info.h"
-#include "stack_map.h"
namespace art {
@@ -75,10 +74,6 @@ class PACKED(4) OatQuickMethodHeader {
return code_ - vmap_table_offset_;
}
- CodeInfo GetOptimizedCodeInfo() const {
- return CodeInfo(GetOptimizedCodeInfoPtr());
- }
-
const void* GetOptimizedMethodInfoPtr() const {
DCHECK(IsOptimized());
return reinterpret_cast<const void*>(code_ - method_info_offset_);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 077aa33925..c555fca23c 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -224,30 +224,29 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
CodeItemDataAccessor accessor(handler_method_->DexInstructionData());
const size_t number_of_vregs = accessor.RegistersSize();
- CodeInfo code_info = handler_method_header_->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
+ CodeInfo code_info(handler_method_header_);
// Find stack map of the catch block.
- StackMap catch_stack_map = code_info.GetCatchStackMapForDexPc(GetHandlerDexPc(), encoding);
+ StackMap catch_stack_map = code_info.GetCatchStackMapForDexPc(GetHandlerDexPc());
DCHECK(catch_stack_map.IsValid());
DexRegisterMap catch_vreg_map =
- code_info.GetDexRegisterMapOf(catch_stack_map, encoding, number_of_vregs);
+ code_info.GetDexRegisterMapOf(catch_stack_map, number_of_vregs);
if (!catch_vreg_map.IsValid()) {
return;
}
// Find stack map of the throwing instruction.
StackMap throw_stack_map =
- code_info.GetStackMapForNativePcOffset(stack_visitor->GetNativePcOffset(), encoding);
+ code_info.GetStackMapForNativePcOffset(stack_visitor->GetNativePcOffset());
DCHECK(throw_stack_map.IsValid());
DexRegisterMap throw_vreg_map =
- code_info.GetDexRegisterMapOf(throw_stack_map, encoding, number_of_vregs);
+ code_info.GetDexRegisterMapOf(throw_stack_map, number_of_vregs);
DCHECK(throw_vreg_map.IsValid());
// Copy values between them.
for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
DexRegisterLocation::Kind catch_location =
- catch_vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding);
+ catch_vreg_map.GetLocationKind(vreg, number_of_vregs, code_info);
if (catch_location == DexRegisterLocation::Kind::kNone) {
continue;
}
@@ -257,8 +256,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
uint32_t vreg_value;
VRegKind vreg_kind = ToVRegKind(throw_vreg_map.GetLocationKind(vreg,
number_of_vregs,
- code_info,
- encoding));
+ code_info));
bool get_vreg_success = stack_visitor->GetVReg(stack_visitor->GetMethod(),
vreg,
vreg_kind,
@@ -271,8 +269,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
// Copy value to the catch phi's stack slot.
int32_t slot_offset = catch_vreg_map.GetStackOffsetInBytes(vreg,
number_of_vregs,
- code_info,
- encoding);
+ code_info);
ArtMethod** frame_top = stack_visitor->GetCurrentQuickFrame();
uint8_t* slot_address = reinterpret_cast<uint8_t*>(frame_top) + slot_offset;
uint32_t* slot_ptr = reinterpret_cast<uint32_t*>(slot_address);
@@ -404,20 +401,18 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
const bool* updated_vregs)
REQUIRES_SHARED(Locks::mutator_lock_) {
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
- CodeInfo code_info = method_header->GetOptimizedCodeInfo();
+ CodeInfo code_info(method_header);
uintptr_t native_pc_offset = method_header->NativeQuickPcOffset(GetCurrentQuickFramePc());
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
CodeItemDataAccessor accessor(m->DexInstructionData());
const size_t number_of_vregs = accessor.RegistersSize();
- uint32_t register_mask = code_info.GetRegisterMaskOf(encoding, stack_map);
- BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
+ uint32_t register_mask = code_info.GetRegisterMaskOf(stack_map);
+ BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
DexRegisterMap vreg_map = IsInInlinedFrame()
? code_info.GetDexRegisterMapAtDepth(GetCurrentInliningDepth() - 1,
- code_info.GetInlineInfoOf(stack_map, encoding),
- encoding,
+ code_info.GetInlineInfoOf(stack_map),
number_of_vregs)
- : code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs);
+ : code_info.GetDexRegisterMapOf(stack_map, number_of_vregs);
if (!vreg_map.IsValid()) {
return;
@@ -430,7 +425,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
}
DexRegisterLocation::Kind location =
- vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding);
+ vreg_map.GetLocationKind(vreg, number_of_vregs, code_info);
static constexpr uint32_t kDeadValue = 0xEBADDE09;
uint32_t value = kDeadValue;
bool is_reference = false;
@@ -439,12 +434,11 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
case DexRegisterLocation::Kind::kInStack: {
const int32_t offset = vreg_map.GetStackOffsetInBytes(vreg,
number_of_vregs,
- code_info,
- encoding);
+ code_info);
const uint8_t* addr = reinterpret_cast<const uint8_t*>(GetCurrentQuickFrame()) + offset;
value = *reinterpret_cast<const uint32_t*>(addr);
uint32_t bit = (offset >> 2);
- if (bit < encoding.stack_mask.encoding.BitSize() && stack_mask.LoadBit(bit)) {
+ if (bit < code_info.GetNumberOfStackMaskBits() && stack_mask.LoadBit(bit)) {
is_reference = true;
}
break;
@@ -453,7 +447,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
case DexRegisterLocation::Kind::kInRegisterHigh:
case DexRegisterLocation::Kind::kInFpuRegister:
case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
- uint32_t reg = vreg_map.GetMachineRegister(vreg, number_of_vregs, code_info, encoding);
+ uint32_t reg = vreg_map.GetMachineRegister(vreg, number_of_vregs, code_info);
bool result = GetRegisterIfAccessible(reg, ToVRegKind(location), &value);
CHECK(result);
if (location == DexRegisterLocation::Kind::kInRegister) {
@@ -464,7 +458,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
break;
}
case DexRegisterLocation::Kind::kConstant: {
- value = vreg_map.GetConstant(vreg, number_of_vregs, code_info, encoding);
+ value = vreg_map.GetConstant(vreg, number_of_vregs, code_info);
if (value == 0) {
// Make it a reference for extra safety.
is_reference = true;
@@ -479,8 +473,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
<< "Unexpected location kind "
<< vreg_map.GetLocationInternalKind(vreg,
number_of_vregs,
- code_info,
- encoding);
+ code_info);
UNREACHABLE();
}
}
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 229238e0f7..740d870af3 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -75,15 +75,14 @@ StackVisitor::StackVisitor(Thread* thread,
}
}
-static InlineInfo GetCurrentInlineInfo(const OatQuickMethodHeader* method_header,
+static InlineInfo GetCurrentInlineInfo(CodeInfo& code_info,
+ const OatQuickMethodHeader* method_header,
uintptr_t cur_quick_frame_pc)
REQUIRES_SHARED(Locks::mutator_lock_) {
uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc);
- CodeInfo code_info = method_header->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
DCHECK(stack_map.IsValid());
- return code_info.GetInlineInfoOf(stack_map, encoding);
+ return code_info.GetInlineInfoOf(stack_map);
}
ArtMethod* StackVisitor::GetMethod() const {
@@ -92,16 +91,16 @@ ArtMethod* StackVisitor::GetMethod() const {
} else if (cur_quick_frame_ != nullptr) {
if (IsInInlinedFrame()) {
size_t depth_in_stack_map = current_inlining_depth_ - 1;
- InlineInfo inline_info = GetCurrentInlineInfo(GetCurrentOatQuickMethodHeader(),
- cur_quick_frame_pc_);
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
- CodeInfoEncoding encoding = method_header->GetOptimizedCodeInfo().ExtractEncoding();
+ CodeInfo code_info(method_header);
+ InlineInfo inline_info = GetCurrentInlineInfo(code_info,
+ method_header,
+ cur_quick_frame_pc_);
MethodInfo method_info = method_header->GetOptimizedMethodInfo();
DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames);
return GetResolvedMethod(*GetCurrentQuickFrame(),
method_info,
inline_info,
- encoding.inline_info.encoding,
depth_in_stack_map);
} else {
return *cur_quick_frame_;
@@ -115,11 +114,11 @@ uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const {
return cur_shadow_frame_->GetDexPC();
} else if (cur_quick_frame_ != nullptr) {
if (IsInInlinedFrame()) {
- size_t depth_in_stack_map = current_inlining_depth_ - 1;
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
- CodeInfoEncoding encoding = method_header->GetOptimizedCodeInfo().ExtractEncoding();
- return GetCurrentInlineInfo(GetCurrentOatQuickMethodHeader(), cur_quick_frame_pc_).
- GetDexPcAtDepth(encoding.inline_info.encoding, depth_in_stack_map);
+ CodeInfo code_info(method_header);
+ size_t depth_in_stack_map = current_inlining_depth_ - 1;
+ return GetCurrentInlineInfo(code_info, method_header, cur_quick_frame_pc_).
+ GetDexPcAtDepth(depth_in_stack_map);
} else if (cur_oat_quick_method_header_ == nullptr) {
return dex::kDexNoIndex;
} else {
@@ -229,32 +228,29 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin
uint16_t number_of_dex_registers = accessor.RegistersSize();
DCHECK_LT(vreg, number_of_dex_registers);
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
- CodeInfo code_info = method_header->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
+ CodeInfo code_info(method_header);
uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc_);
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
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, encoding),
- encoding,
+ code_info.GetInlineInfoOf(stack_map),
number_of_dex_registers)
- : code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
+ : code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
if (!dex_register_map.IsValid()) {
return false;
}
DexRegisterLocation::Kind location_kind =
- dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info, encoding);
+ dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info);
switch (location_kind) {
case DexRegisterLocation::Kind::kInStack: {
const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg,
number_of_dex_registers,
- code_info,
- encoding);
+ code_info);
const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset;
*val = *reinterpret_cast<const uint32_t*>(addr);
return true;
@@ -264,11 +260,11 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin
case DexRegisterLocation::Kind::kInFpuRegister:
case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
uint32_t reg =
- dex_register_map.GetMachineRegister(vreg, number_of_dex_registers, code_info, encoding);
+ dex_register_map.GetMachineRegister(vreg, number_of_dex_registers, code_info);
return GetRegisterIfAccessible(reg, kind, val);
}
case DexRegisterLocation::Kind::kConstant:
- *val = dex_register_map.GetConstant(vreg, number_of_dex_registers, code_info, encoding);
+ *val = dex_register_map.GetConstant(vreg, number_of_dex_registers, code_info);
return true;
case DexRegisterLocation::Kind::kNone:
return false;
@@ -277,8 +273,7 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin
<< "Unexpected location kind "
<< dex_register_map.GetLocationInternalKind(vreg,
number_of_dex_registers,
- code_info,
- encoding);
+ code_info);
UNREACHABLE();
}
}
@@ -830,15 +825,14 @@ void StackVisitor::WalkStack(bool include_transitions) {
if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames)
&& (cur_oat_quick_method_header_ != nullptr)
&& cur_oat_quick_method_header_->IsOptimized()) {
- CodeInfo code_info = cur_oat_quick_method_header_->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
+ CodeInfo code_info(cur_oat_quick_method_header_);
uint32_t native_pc_offset =
cur_oat_quick_method_header_->NativeQuickPcOffset(cur_quick_frame_pc_);
- StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
- if (stack_map.IsValid() && stack_map.HasInlineInfo(encoding.stack_map.encoding)) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+ if (stack_map.IsValid() && stack_map.HasInlineInfo()) {
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
DCHECK_EQ(current_inlining_depth_, 0u);
- for (current_inlining_depth_ = inline_info.GetDepth(encoding.inline_info.encoding);
+ for (current_inlining_depth_ = inline_info.GetDepth();
current_inlining_depth_ != 0;
--current_inlining_depth_) {
bool should_continue = VisitFrame();
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 9c7b6875cf..2b7e8dd748 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -25,8 +25,6 @@
namespace art {
constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
-constexpr uint32_t StackMap::kNoDexRegisterMap;
-constexpr uint32_t StackMap::kNoInlineInfo;
std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind) {
using Kind = DexRegisterLocation::Kind;
@@ -56,27 +54,25 @@ std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind&
DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(
uint16_t dex_register_number,
uint16_t number_of_dex_registers,
- const CodeInfo& code_info,
- const CodeInfoEncoding& enc) const {
+ const CodeInfo& code_info) const {
DexRegisterLocationCatalog dex_register_location_catalog =
- code_info.GetDexRegisterLocationCatalog(enc);
+ code_info.GetDexRegisterLocationCatalog();
size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
dex_register_number,
number_of_dex_registers,
- code_info.GetNumberOfLocationCatalogEntries(enc));
+ code_info.GetNumberOfLocationCatalogEntries());
return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
}
DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
uint16_t number_of_dex_registers,
- const CodeInfo& code_info,
- const CodeInfoEncoding& enc) const {
+ const CodeInfo& code_info) const {
DexRegisterLocationCatalog dex_register_location_catalog =
- code_info.GetDexRegisterLocationCatalog(enc);
+ code_info.GetDexRegisterLocationCatalog();
size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
dex_register_number,
number_of_dex_registers,
- code_info.GetNumberOfLocationCatalogEntries(enc));
+ code_info.GetNumberOfLocationCatalogEntries());
return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
}
@@ -90,27 +86,28 @@ static void DumpRegisterMapping(std::ostream& os,
<< " (" << location.GetValue() << ")" << suffix << '\n';
}
-void StackMapEncoding::Dump(VariableIndentationOutputStream* vios) const {
+void StackMap::DumpEncoding(const BitTable<6>& table,
+ VariableIndentationOutputStream* vios) {
vios->Stream()
<< "StackMapEncoding"
- << " (native_pc_bit_offset=" << static_cast<uint32_t>(kNativePcBitOffset)
- << ", dex_pc_bit_offset=" << static_cast<uint32_t>(dex_pc_bit_offset_)
- << ", dex_register_map_bit_offset=" << static_cast<uint32_t>(dex_register_map_bit_offset_)
- << ", inline_info_bit_offset=" << static_cast<uint32_t>(inline_info_bit_offset_)
- << ", register_mask_bit_offset=" << static_cast<uint32_t>(register_mask_index_bit_offset_)
- << ", stack_mask_index_bit_offset=" << static_cast<uint32_t>(stack_mask_index_bit_offset_)
- << ", total_bit_size=" << static_cast<uint32_t>(total_bit_size_)
+ << " (NativePcOffsetBits=" << table.NumColumnBits(kNativePcOffset)
+ << ", DexPcBits=" << table.NumColumnBits(kDexPc)
+ << ", DexRegisterMapOffsetBits=" << table.NumColumnBits(kDexRegisterMapOffset)
+ << ", InlineInfoIndexBits=" << table.NumColumnBits(kInlineInfoIndex)
+ << ", RegisterMaskIndexBits=" << table.NumColumnBits(kRegisterMaskIndex)
+ << ", StackMaskIndexBits=" << table.NumColumnBits(kStackMaskIndex)
<< ")\n";
}
-void InlineInfoEncoding::Dump(VariableIndentationOutputStream* vios) const {
+void InlineInfo::DumpEncoding(const BitTable<5>& table,
+ VariableIndentationOutputStream* vios) {
vios->Stream()
<< "InlineInfoEncoding"
- << " (method_index_bit_offset=" << static_cast<uint32_t>(kMethodIndexBitOffset)
- << ", dex_pc_bit_offset=" << static_cast<uint32_t>(dex_pc_bit_offset_)
- << ", extra_data_bit_offset=" << static_cast<uint32_t>(extra_data_bit_offset_)
- << ", dex_register_map_bit_offset=" << static_cast<uint32_t>(dex_register_map_bit_offset_)
- << ", total_bit_size=" << static_cast<uint32_t>(total_bit_size_)
+ << " (IsLastBits=" << table.NumColumnBits(kIsLast)
+ << ", MethodIndexIdxBits=" << table.NumColumnBits(kMethodIndexIdx)
+ << ", DexPcBits=" << table.NumColumnBits(kDexPc)
+ << ", ExtraDataBits=" << table.NumColumnBits(kExtraData)
+ << ", DexRegisterMapOffsetBits=" << table.NumColumnBits(kDexRegisterMapOffset)
<< ")\n";
}
@@ -120,26 +117,24 @@ void CodeInfo::Dump(VariableIndentationOutputStream* vios,
bool dump_stack_maps,
InstructionSet instruction_set,
const MethodInfo& method_info) const {
- CodeInfoEncoding encoding = ExtractEncoding();
- size_t number_of_stack_maps = GetNumberOfStackMaps(encoding);
+ size_t number_of_stack_maps = GetNumberOfStackMaps();
vios->Stream()
<< "Optimized CodeInfo (number_of_dex_registers=" << number_of_dex_registers
<< ", number_of_stack_maps=" << number_of_stack_maps
<< ")\n";
ScopedIndentation indent1(vios);
- encoding.stack_map.encoding.Dump(vios);
- if (HasInlineInfo(encoding)) {
- encoding.inline_info.encoding.Dump(vios);
+ StackMap::DumpEncoding(stack_maps_, vios);
+ if (HasInlineInfo()) {
+ InlineInfo::DumpEncoding(inline_infos_, vios);
}
// Display the Dex register location catalog.
- GetDexRegisterLocationCatalog(encoding).Dump(vios, *this);
+ GetDexRegisterLocationCatalog().Dump(vios, *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, encoding);
+ StackMap stack_map = GetStackMapAt(i);
stack_map.Dump(vios,
*this,
- encoding,
method_info,
code_offset,
number_of_dex_registers,
@@ -153,9 +148,8 @@ void CodeInfo::Dump(VariableIndentationOutputStream* vios,
void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info) {
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
- size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(encoding);
+ size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
+ size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize();
vios->Stream()
<< "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
<< ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
@@ -169,8 +163,7 @@ void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios,
void DexRegisterMap::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
uint16_t number_of_dex_registers) const {
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
+ size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
// TODO: Display the bit mask of live Dex registers.
for (size_t j = 0; j < number_of_dex_registers; ++j) {
if (IsDexRegisterLive(j)) {
@@ -178,8 +171,7 @@ void DexRegisterMap::Dump(VariableIndentationOutputStream* vios,
j, number_of_dex_registers, number_of_location_catalog_entries);
DexRegisterLocation location = GetDexRegisterLocation(j,
number_of_dex_registers,
- code_info,
- encoding);
+ code_info);
ScopedIndentation indent1(vios);
DumpRegisterMapping(
vios->Stream(), j, location, "v",
@@ -190,38 +182,35 @@ void DexRegisterMap::Dump(VariableIndentationOutputStream* vios,
void StackMap::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
- const CodeInfoEncoding& encoding,
const MethodInfo& method_info,
uint32_t code_offset,
uint16_t number_of_dex_registers,
InstructionSet instruction_set,
const std::string& header_suffix) const {
- StackMapEncoding stack_map_encoding = encoding.stack_map.encoding;
- const uint32_t pc_offset = GetNativePcOffset(stack_map_encoding, instruction_set);
+ const uint32_t pc_offset = GetNativePcOffset(instruction_set);
vios->Stream()
<< "StackMap" << header_suffix
<< std::hex
<< " [native_pc=0x" << code_offset + pc_offset << "]"
- << " [entry_size=0x" << encoding.stack_map.encoding.BitSize() << " bits]"
- << " (dex_pc=0x" << GetDexPc(stack_map_encoding)
+ << " (dex_pc=0x" << GetDexPc()
<< ", native_pc_offset=0x" << pc_offset
- << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(stack_map_encoding)
- << ", inline_info_offset=0x" << GetInlineInfoIndex(stack_map_encoding)
- << ", register_mask=0x" << code_info.GetRegisterMaskOf(encoding, *this)
+ << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset()
+ << ", inline_info_offset=0x" << GetInlineInfoIndex()
+ << ", register_mask=0x" << code_info.GetRegisterMaskOf(*this)
<< std::dec
<< ", stack_mask=0b";
- BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, *this);
- for (size_t i = 0, e = encoding.stack_mask.encoding.BitSize(); i < e; ++i) {
+ BitMemoryRegion stack_mask = code_info.GetStackMaskOf(*this);
+ for (size_t i = 0, e = code_info.GetNumberOfStackMaskBits(); i < e; ++i) {
vios->Stream() << stack_mask.LoadBit(e - i - 1);
}
vios->Stream() << ")\n";
- if (HasDexRegisterMap(stack_map_encoding)) {
+ if (HasDexRegisterMap()) {
DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
- *this, encoding, number_of_dex_registers);
+ *this, number_of_dex_registers);
dex_register_map.Dump(vios, code_info, number_of_dex_registers);
}
- if (HasInlineInfo(stack_map_encoding)) {
- InlineInfo inline_info = code_info.GetInlineInfoOf(*this, encoding);
+ if (HasInlineInfo()) {
+ InlineInfo inline_info = code_info.GetInlineInfoOf(*this);
// We do not know the length of the dex register maps of inlined frames
// at this level, so we just pass null to `InlineInfo::Dump` to tell
// it not to look at these maps.
@@ -233,29 +222,27 @@ void InlineInfo::Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
const MethodInfo& method_info,
uint16_t number_of_dex_registers[]) const {
- InlineInfoEncoding inline_info_encoding = code_info.ExtractEncoding().inline_info.encoding;
vios->Stream() << "InlineInfo with depth "
- << static_cast<uint32_t>(GetDepth(inline_info_encoding))
+ << static_cast<uint32_t>(GetDepth())
<< "\n";
- for (size_t i = 0; i < GetDepth(inline_info_encoding); ++i) {
+ for (size_t i = 0; i < GetDepth(); ++i) {
vios->Stream()
<< " At depth " << i
<< std::hex
- << " (dex_pc=0x" << GetDexPcAtDepth(inline_info_encoding, i);
- if (EncodesArtMethodAtDepth(inline_info_encoding, i)) {
+ << " (dex_pc=0x" << GetDexPcAtDepth(i);
+ if (EncodesArtMethodAtDepth(i)) {
ScopedObjectAccess soa(Thread::Current());
- vios->Stream() << ", method=" << GetArtMethodAtDepth(inline_info_encoding, i)->PrettyMethod();
+ vios->Stream() << ", method=" << GetArtMethodAtDepth(i)->PrettyMethod();
} else {
vios->Stream()
<< std::dec
- << ", method_index=" << GetMethodIndexAtDepth(inline_info_encoding, method_info, i);
+ << ", method_index=" << GetMethodIndexAtDepth(method_info, i);
}
vios->Stream() << ")\n";
- if (HasDexRegisterMapAtDepth(inline_info_encoding, i) && (number_of_dex_registers != nullptr)) {
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
+ if (HasDexRegisterMapAtDepth(i) && (number_of_dex_registers != nullptr)) {
DexRegisterMap dex_register_map =
- code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]);
+ code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]);
ScopedIndentation indent1(vios);
dex_register_map.Dump(vios, code_info, number_of_dex_registers[i]);
}
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index fb1867488e..91cecf0690 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -21,12 +21,14 @@
#include "arch/code_offset.h"
#include "base/bit_memory_region.h"
+#include "base/bit_table.h"
#include "base/bit_utils.h"
#include "base/bit_vector.h"
#include "base/leb128.h"
#include "base/memory_region.h"
#include "dex/dex_file_types.h"
#include "method_info.h"
+#include "oat_quick_method_header.h"
namespace art {
@@ -39,8 +41,6 @@ static constexpr ssize_t kFrameSlotSize = 4;
class ArtMethod;
class CodeInfo;
-class StackMapEncoding;
-struct CodeInfoEncoding;
/**
* Classes in the following file are wrapper on stack map information backed
@@ -454,30 +454,26 @@ 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 CodeInfoEncoding& enc) const {
+ const CodeInfo& code_info) const {
return DexRegisterLocation::ConvertToSurfaceKind(
- GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info, enc));
+ GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info));
}
// 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 CodeInfoEncoding& enc) const;
+ const CodeInfo& code_info) 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 CodeInfoEncoding& enc) const;
+ const CodeInfo& code_info) const;
int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
uint16_t number_of_dex_registers,
- const CodeInfo& code_info,
- const CodeInfoEncoding& enc) const {
+ const CodeInfo& code_info) const {
DexRegisterLocation location =
- GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
+ GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
// GetDexRegisterLocation returns the offset in bytes.
return location.GetValue();
@@ -485,20 +481,18 @@ class DexRegisterMap {
int32_t GetConstant(uint16_t dex_register_number,
uint16_t number_of_dex_registers,
- const CodeInfo& code_info,
- const CodeInfoEncoding& enc) const {
+ const CodeInfo& code_info) const {
DexRegisterLocation location =
- GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
+ GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
DCHECK_EQ(location.GetKind(), DexRegisterLocation::Kind::kConstant);
return location.GetValue();
}
int32_t GetMachineRegister(uint16_t dex_register_number,
uint16_t number_of_dex_registers,
- const CodeInfo& code_info,
- const CodeInfoEncoding& enc) const {
+ const CodeInfo& code_info) const {
DexRegisterLocation location =
- GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
+ GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister ||
location.GetInternalKind() == DexRegisterLocation::Kind::kInRegisterHigh ||
location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister ||
@@ -653,137 +647,6 @@ class DexRegisterMap {
friend class StackMapStream;
};
-// Represents bit range of bit-packed integer field.
-// We reuse the idea from ULEB128p1 to support encoding of -1 (aka 0xFFFFFFFF).
-// If min_value is set to -1, we implicitly subtract one from any loaded value,
-// and add one to any stored value. This is generalized to any negative values.
-// In other words, min_value acts as a base and the stored value is added to it.
-struct FieldEncoding {
- FieldEncoding(size_t start_offset, size_t end_offset, int32_t min_value = 0)
- : start_offset_(start_offset), end_offset_(end_offset), min_value_(min_value) {
- DCHECK_LE(start_offset_, end_offset_);
- DCHECK_LE(BitSize(), 32u);
- }
-
- ALWAYS_INLINE size_t BitSize() const { return end_offset_ - start_offset_; }
-
- template <typename Region>
- ALWAYS_INLINE int32_t Load(const Region& region) const {
- DCHECK_LE(end_offset_, region.size_in_bits());
- return static_cast<int32_t>(region.LoadBits(start_offset_, BitSize())) + min_value_;
- }
-
- template <typename Region>
- ALWAYS_INLINE void Store(Region region, int32_t value) const {
- region.StoreBits(start_offset_, static_cast<uint32_t>(value - min_value_), BitSize());
- DCHECK_EQ(Load(region), value);
- }
-
- private:
- size_t start_offset_;
- size_t end_offset_;
- int32_t min_value_;
-};
-
-class StackMapEncoding {
- public:
- StackMapEncoding()
- : dex_pc_bit_offset_(0),
- dex_register_map_bit_offset_(0),
- inline_info_bit_offset_(0),
- register_mask_index_bit_offset_(0),
- stack_mask_index_bit_offset_(0),
- total_bit_size_(0) {}
-
- // Set stack map bit layout based on given sizes.
- // Returns the size of stack map in bits.
- size_t SetFromSizes(size_t native_pc_max,
- size_t dex_pc_max,
- size_t dex_register_map_size,
- size_t number_of_inline_info,
- size_t number_of_register_masks,
- size_t number_of_stack_masks) {
- total_bit_size_ = 0;
- DCHECK_EQ(kNativePcBitOffset, total_bit_size_);
- total_bit_size_ += MinimumBitsToStore(native_pc_max);
-
- dex_pc_bit_offset_ = total_bit_size_;
- // Note: We're not encoding the dex pc if there is none. That's the case
- // for an intrinsified native method, such as String.charAt().
- if (dex_pc_max != dex::kDexNoIndex) {
- total_bit_size_ += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max);
- }
-
- // We also need +1 for kNoDexRegisterMap, but since the size is strictly
- // greater than any offset we might try to encode, we already implicitly have it.
- dex_register_map_bit_offset_ = total_bit_size_;
- total_bit_size_ += MinimumBitsToStore(dex_register_map_size);
-
- // We also need +1 for kNoInlineInfo, but since the inline_info_size is strictly
- // greater than the offset we might try to encode, we already implicitly have it.
- // If inline_info_size is zero, we can encode only kNoInlineInfo (in zero bits).
- inline_info_bit_offset_ = total_bit_size_;
- total_bit_size_ += MinimumBitsToStore(number_of_inline_info);
-
- register_mask_index_bit_offset_ = total_bit_size_;
- total_bit_size_ += MinimumBitsToStore(number_of_register_masks);
-
- stack_mask_index_bit_offset_ = total_bit_size_;
- total_bit_size_ += MinimumBitsToStore(number_of_stack_masks);
-
- return total_bit_size_;
- }
-
- ALWAYS_INLINE FieldEncoding GetNativePcEncoding() const {
- return FieldEncoding(kNativePcBitOffset, dex_pc_bit_offset_);
- }
- ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const {
- return FieldEncoding(dex_pc_bit_offset_, dex_register_map_bit_offset_, -1 /* min_value */);
- }
- ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const {
- return FieldEncoding(dex_register_map_bit_offset_, inline_info_bit_offset_, -1 /* min_value */);
- }
- ALWAYS_INLINE FieldEncoding GetInlineInfoEncoding() const {
- return FieldEncoding(inline_info_bit_offset_,
- register_mask_index_bit_offset_,
- -1 /* min_value */);
- }
- ALWAYS_INLINE FieldEncoding GetRegisterMaskIndexEncoding() const {
- return FieldEncoding(register_mask_index_bit_offset_, stack_mask_index_bit_offset_);
- }
- ALWAYS_INLINE FieldEncoding GetStackMaskIndexEncoding() const {
- return FieldEncoding(stack_mask_index_bit_offset_, total_bit_size_);
- }
- ALWAYS_INLINE size_t BitSize() const {
- return total_bit_size_;
- }
-
- // Encode the encoding into the vector.
- template<typename Vector>
- void Encode(Vector* dest) const {
- static_assert(alignof(StackMapEncoding) == 1, "Should not require alignment");
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
- dest->insert(dest->end(), ptr, ptr + sizeof(*this));
- }
-
- // Decode the encoding from a pointer, updates the pointer.
- void Decode(const uint8_t** ptr) {
- *this = *reinterpret_cast<const StackMapEncoding*>(*ptr);
- *ptr += sizeof(*this);
- }
-
- void Dump(VariableIndentationOutputStream* vios) const;
-
- private:
- static constexpr size_t kNativePcBitOffset = 0;
- uint8_t dex_pc_bit_offset_;
- uint8_t dex_register_map_bit_offset_;
- uint8_t inline_info_bit_offset_;
- uint8_t register_mask_index_bit_offset_;
- uint8_t stack_mask_index_bit_offset_;
- uint8_t total_bit_size_;
-};
-
/**
* A Stack Map holds compilation information for a specific PC necessary for:
* - Mapping it to a dex PC,
@@ -791,246 +654,101 @@ class StackMapEncoding {
* - Knowing which registers hold objects,
* - Knowing the inlining information,
* - Knowing the values of dex registers.
- *
- * The information is of the form:
- *
- * [native_pc_offset, dex_pc, dex_register_map_offset, inlining_info_index, register_mask_index,
- * stack_mask_index].
*/
-class StackMap {
+class StackMap : public BitTable<6>::Accessor {
public:
- StackMap() {}
- explicit StackMap(BitMemoryRegion region) : region_(region) {}
-
- ALWAYS_INLINE bool IsValid() const { return region_.IsValid(); }
-
- ALWAYS_INLINE uint32_t GetDexPc(const StackMapEncoding& encoding) const {
- return encoding.GetDexPcEncoding().Load(region_);
- }
+ enum Field {
+ kNativePcOffset,
+ kDexPc,
+ kDexRegisterMapOffset,
+ kInlineInfoIndex,
+ kRegisterMaskIndex,
+ kStackMaskIndex,
+ kCount,
+ };
- ALWAYS_INLINE void SetDexPc(const StackMapEncoding& encoding, uint32_t dex_pc) {
- encoding.GetDexPcEncoding().Store(region_, dex_pc);
- }
+ StackMap() : BitTable<kCount>::Accessor(nullptr, -1) {}
+ StackMap(const BitTable<kCount>* table, uint32_t row)
+ : BitTable<kCount>::Accessor(table, row) {}
- ALWAYS_INLINE uint32_t GetNativePcOffset(const StackMapEncoding& encoding,
- InstructionSet instruction_set) const {
- CodeOffset offset(
- CodeOffset::FromCompressedOffset(encoding.GetNativePcEncoding().Load(region_)));
+ ALWAYS_INLINE uint32_t GetNativePcOffset(InstructionSet instruction_set) const {
+ CodeOffset offset(CodeOffset::FromCompressedOffset(Get<kNativePcOffset>()));
return offset.Uint32Value(instruction_set);
}
- ALWAYS_INLINE void SetNativePcCodeOffset(const StackMapEncoding& encoding,
- CodeOffset native_pc_offset) {
- encoding.GetNativePcEncoding().Store(region_, native_pc_offset.CompressedValue());
- }
-
- ALWAYS_INLINE uint32_t GetDexRegisterMapOffset(const StackMapEncoding& encoding) const {
- return encoding.GetDexRegisterMapEncoding().Load(region_);
- }
-
- ALWAYS_INLINE void SetDexRegisterMapOffset(const StackMapEncoding& encoding, uint32_t offset) {
- encoding.GetDexRegisterMapEncoding().Store(region_, offset);
- }
-
- ALWAYS_INLINE uint32_t GetInlineInfoIndex(const StackMapEncoding& encoding) const {
- return encoding.GetInlineInfoEncoding().Load(region_);
- }
-
- ALWAYS_INLINE void SetInlineInfoIndex(const StackMapEncoding& encoding, uint32_t index) {
- encoding.GetInlineInfoEncoding().Store(region_, index);
- }
-
- ALWAYS_INLINE uint32_t GetRegisterMaskIndex(const StackMapEncoding& encoding) const {
- return encoding.GetRegisterMaskIndexEncoding().Load(region_);
- }
+ uint32_t GetDexPc() const { return Get<kDexPc>(); }
- ALWAYS_INLINE void SetRegisterMaskIndex(const StackMapEncoding& encoding, uint32_t mask) {
- encoding.GetRegisterMaskIndexEncoding().Store(region_, mask);
- }
+ uint32_t GetDexRegisterMapOffset() const { return Get<kDexRegisterMapOffset>(); }
+ bool HasDexRegisterMap() const { return GetDexRegisterMapOffset() != kNoValue; }
- ALWAYS_INLINE uint32_t GetStackMaskIndex(const StackMapEncoding& encoding) const {
- return encoding.GetStackMaskIndexEncoding().Load(region_);
- }
+ uint32_t GetInlineInfoIndex() const { return Get<kInlineInfoIndex>(); }
+ bool HasInlineInfo() const { return GetInlineInfoIndex() != kNoValue; }
- ALWAYS_INLINE void SetStackMaskIndex(const StackMapEncoding& encoding, uint32_t mask) {
- encoding.GetStackMaskIndexEncoding().Store(region_, mask);
- }
+ uint32_t GetRegisterMaskIndex() const { return Get<kRegisterMaskIndex>(); }
- ALWAYS_INLINE bool HasDexRegisterMap(const StackMapEncoding& encoding) const {
- return GetDexRegisterMapOffset(encoding) != kNoDexRegisterMap;
- }
-
- ALWAYS_INLINE bool HasInlineInfo(const StackMapEncoding& encoding) const {
- return GetInlineInfoIndex(encoding) != kNoInlineInfo;
- }
-
- ALWAYS_INLINE bool Equals(const StackMap& other) const {
- return region_.Equals(other.region_);
- }
+ uint32_t GetStackMaskIndex() const { return Get<kStackMaskIndex>(); }
+ static void DumpEncoding(const BitTable<6>& table, VariableIndentationOutputStream* vios);
void Dump(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
- const CodeInfoEncoding& encoding,
const MethodInfo& method_info,
uint32_t code_offset,
uint16_t number_of_dex_registers,
InstructionSet instruction_set,
const std::string& header_suffix = "") const;
-
- // 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 kFixedSize = 0;
-
- BitMemoryRegion region_;
-
- friend class StackMapStream;
-};
-
-class InlineInfoEncoding {
- public:
- void SetFromSizes(size_t method_index_idx_max,
- size_t dex_pc_max,
- size_t extra_data_max,
- size_t dex_register_map_size) {
- total_bit_size_ = kMethodIndexBitOffset;
- total_bit_size_ += MinimumBitsToStore(method_index_idx_max);
-
- dex_pc_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
- // Note: We're not encoding the dex pc if there is none. That's the case
- // for an intrinsified native method, such as String.charAt().
- if (dex_pc_max != dex::kDexNoIndex) {
- total_bit_size_ += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max);
- }
-
- extra_data_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
- total_bit_size_ += MinimumBitsToStore(extra_data_max);
-
- // We also need +1 for kNoDexRegisterMap, but since the size is strictly
- // greater than any offset we might try to encode, we already implicitly have it.
- dex_register_map_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
- total_bit_size_ += MinimumBitsToStore(dex_register_map_size);
- }
-
- ALWAYS_INLINE FieldEncoding GetMethodIndexIdxEncoding() const {
- return FieldEncoding(kMethodIndexBitOffset, dex_pc_bit_offset_);
- }
- ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const {
- return FieldEncoding(dex_pc_bit_offset_, extra_data_bit_offset_, -1 /* min_value */);
- }
- ALWAYS_INLINE FieldEncoding GetExtraDataEncoding() const {
- return FieldEncoding(extra_data_bit_offset_, dex_register_map_bit_offset_);
- }
- ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const {
- return FieldEncoding(dex_register_map_bit_offset_, total_bit_size_, -1 /* min_value */);
- }
- ALWAYS_INLINE size_t BitSize() const {
- return total_bit_size_;
- }
-
- void Dump(VariableIndentationOutputStream* vios) const;
-
- // Encode the encoding into the vector.
- template<typename Vector>
- void Encode(Vector* dest) const {
- static_assert(alignof(InlineInfoEncoding) == 1, "Should not require alignment");
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
- dest->insert(dest->end(), ptr, ptr + sizeof(*this));
- }
-
- // Decode the encoding from a pointer, updates the pointer.
- void Decode(const uint8_t** ptr) {
- *this = *reinterpret_cast<const InlineInfoEncoding*>(*ptr);
- *ptr += sizeof(*this);
- }
-
- private:
- static constexpr uint8_t kIsLastBitOffset = 0;
- static constexpr uint8_t kMethodIndexBitOffset = 1;
- uint8_t dex_pc_bit_offset_;
- uint8_t extra_data_bit_offset_;
- uint8_t dex_register_map_bit_offset_;
- uint8_t total_bit_size_;
};
/**
- * Inline information for a specific PC. The information is of the form:
- *
- * [is_last,
- * method_index (or ArtMethod high bits),
- * dex_pc,
- * extra_data (ArtMethod low bits or 1),
- * dex_register_map_offset]+.
+ * Inline information for a specific PC.
+ * The row referenced from the StackMap holds information at depth 0.
+ * Following rows hold information for further depths.
*/
-class InlineInfo {
+class InlineInfo : public BitTable<5>::Accessor {
public:
- explicit InlineInfo(BitMemoryRegion region) : region_(region) {}
-
- ALWAYS_INLINE uint32_t GetDepth(const InlineInfoEncoding& encoding) const {
- size_t depth = 0;
- while (!GetRegionAtDepth(encoding, depth++).LoadBit(0)) { } // Check is_last bit.
- return depth;
- }
-
- ALWAYS_INLINE void SetDepth(const InlineInfoEncoding& encoding, uint32_t depth) {
- DCHECK_GT(depth, 0u);
- for (size_t d = 0; d < depth; ++d) {
- GetRegionAtDepth(encoding, d).StoreBit(0, d == depth - 1); // Set is_last bit.
- }
- }
+ enum Field {
+ kIsLast, // Determines if there are further rows for further depths.
+ kMethodIndexIdx, // Method index or ArtMethod high bits.
+ kDexPc,
+ kExtraData, // ArtMethod low bits or 1.
+ kDexRegisterMapOffset,
+ kCount,
+ };
+ static constexpr uint32_t kLast = -1;
+ static constexpr uint32_t kMore = 0;
- ALWAYS_INLINE uint32_t GetMethodIndexIdxAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth) const {
- DCHECK(!EncodesArtMethodAtDepth(encoding, depth));
- return encoding.GetMethodIndexIdxEncoding().Load(GetRegionAtDepth(encoding, depth));
- }
+ InlineInfo(const BitTable<kCount>* table, uint32_t row)
+ : BitTable<kCount>::Accessor(table, row) {}
- ALWAYS_INLINE void SetMethodIndexIdxAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth,
- uint32_t index) {
- encoding.GetMethodIndexIdxEncoding().Store(GetRegionAtDepth(encoding, depth), index);
+ ALWAYS_INLINE InlineInfo AtDepth(uint32_t depth) const {
+ return InlineInfo(table_, this->row_ + depth);
}
-
- ALWAYS_INLINE uint32_t GetMethodIndexAtDepth(const InlineInfoEncoding& encoding,
- const MethodInfo& method_info,
- uint32_t depth) const {
- return method_info.GetMethodIndex(GetMethodIndexIdxAtDepth(encoding, depth));
+ uint32_t GetDepth() const {
+ size_t depth = 0;
+ while (AtDepth(depth++).Get<kIsLast>() == kMore) { }
+ return depth;
}
- ALWAYS_INLINE uint32_t GetDexPcAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth) const {
- return encoding.GetDexPcEncoding().Load(GetRegionAtDepth(encoding, depth));
+ uint32_t GetMethodIndexIdxAtDepth(uint32_t depth) const {
+ DCHECK(!EncodesArtMethodAtDepth(depth));
+ return AtDepth(depth).Get<kMethodIndexIdx>();
}
- ALWAYS_INLINE void SetDexPcAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth,
- uint32_t dex_pc) {
- encoding.GetDexPcEncoding().Store(GetRegionAtDepth(encoding, depth), dex_pc);
+ uint32_t GetMethodIndexAtDepth(const MethodInfo& method_info, uint32_t depth) const {
+ return method_info.GetMethodIndex(GetMethodIndexIdxAtDepth(depth));
}
- ALWAYS_INLINE bool EncodesArtMethodAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth) const {
- return (encoding.GetExtraDataEncoding().Load(GetRegionAtDepth(encoding, depth)) & 1) == 0;
+ uint32_t GetDexPcAtDepth(uint32_t depth) const {
+ return AtDepth(depth).Get<kDexPc>();
}
- ALWAYS_INLINE void SetExtraDataAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth,
- uint32_t extra_data) {
- encoding.GetExtraDataEncoding().Store(GetRegionAtDepth(encoding, depth), extra_data);
+ bool EncodesArtMethodAtDepth(uint32_t depth) const {
+ return (AtDepth(depth).Get<kExtraData>() & 1) == 0;
}
- ALWAYS_INLINE ArtMethod* GetArtMethodAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth) const {
- uint32_t low_bits = encoding.GetExtraDataEncoding().Load(GetRegionAtDepth(encoding, depth));
- uint32_t high_bits = encoding.GetMethodIndexIdxEncoding().Load(
- GetRegionAtDepth(encoding, depth));
+ ArtMethod* GetArtMethodAtDepth(uint32_t depth) const {
+ uint32_t low_bits = AtDepth(depth).Get<kExtraData>();
+ uint32_t high_bits = AtDepth(depth).Get<kMethodIndexIdx>();
if (high_bits == 0) {
return reinterpret_cast<ArtMethod*>(low_bits);
} else {
@@ -1040,411 +758,132 @@ class InlineInfo {
}
}
- ALWAYS_INLINE uint32_t GetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth) const {
- return encoding.GetDexRegisterMapEncoding().Load(GetRegionAtDepth(encoding, depth));
+ uint32_t GetDexRegisterMapOffsetAtDepth(uint32_t depth) const {
+ return AtDepth(depth).Get<kDexRegisterMapOffset>();
}
- ALWAYS_INLINE void SetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth,
- uint32_t offset) {
- encoding.GetDexRegisterMapEncoding().Store(GetRegionAtDepth(encoding, depth), offset);
- }
-
- ALWAYS_INLINE bool HasDexRegisterMapAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth) const {
- return GetDexRegisterMapOffsetAtDepth(encoding, depth) != StackMap::kNoDexRegisterMap;
+ bool HasDexRegisterMapAtDepth(uint32_t depth) const {
+ return GetDexRegisterMapOffsetAtDepth(depth) != StackMap::kNoValue;
}
+ static void DumpEncoding(const BitTable<5>& table, VariableIndentationOutputStream* vios);
void Dump(VariableIndentationOutputStream* vios,
const CodeInfo& info,
const MethodInfo& method_info,
uint16_t* number_of_dex_registers) const;
-
- private:
- ALWAYS_INLINE BitMemoryRegion GetRegionAtDepth(const InlineInfoEncoding& encoding,
- uint32_t depth) const {
- size_t entry_size = encoding.BitSize();
- DCHECK_GT(entry_size, 0u);
- return region_.Subregion(depth * entry_size, entry_size);
- }
-
- BitMemoryRegion region_;
-};
-
-// Bit sized region encoding, may be more than 255 bits.
-class BitRegionEncoding {
- public:
- uint32_t num_bits = 0;
-
- ALWAYS_INLINE size_t BitSize() const {
- return num_bits;
- }
-
- template<typename Vector>
- void Encode(Vector* dest) const {
- EncodeUnsignedLeb128(dest, num_bits); // Use leb in case num_bits is greater than 255.
- }
-
- void Decode(const uint8_t** ptr) {
- num_bits = DecodeUnsignedLeb128(ptr);
- }
-};
-
-// A table of bit sized encodings.
-template <typename Encoding>
-struct BitEncodingTable {
- static constexpr size_t kInvalidOffset = static_cast<size_t>(-1);
- // How the encoding is laid out (serialized).
- Encoding encoding;
-
- // Number of entries in the table (serialized).
- size_t num_entries;
-
- // Bit offset for the base of the table (computed).
- size_t bit_offset = kInvalidOffset;
-
- template<typename Vector>
- void Encode(Vector* dest) const {
- EncodeUnsignedLeb128(dest, num_entries);
- encoding.Encode(dest);
- }
-
- ALWAYS_INLINE void Decode(const uint8_t** ptr) {
- num_entries = DecodeUnsignedLeb128(ptr);
- encoding.Decode(ptr);
- }
-
- // Set the bit offset in the table and adds the space used by the table to offset.
- void UpdateBitOffset(size_t* offset) {
- DCHECK(offset != nullptr);
- bit_offset = *offset;
- *offset += encoding.BitSize() * num_entries;
- }
-
- // Return the bit region for the map at index i.
- ALWAYS_INLINE BitMemoryRegion BitRegion(MemoryRegion region, size_t index) const {
- DCHECK_NE(bit_offset, kInvalidOffset) << "Invalid table offset";
- DCHECK_LT(index, num_entries);
- const size_t map_size = encoding.BitSize();
- return BitMemoryRegion(region, bit_offset + index * map_size, map_size);
- }
-};
-
-// A byte sized table of possible variable sized encodings.
-struct ByteSizedTable {
- static constexpr size_t kInvalidOffset = static_cast<size_t>(-1);
-
- // Number of entries in the table (serialized).
- size_t num_entries = 0;
-
- // Number of bytes of the table (serialized).
- size_t num_bytes;
-
- // Bit offset for the base of the table (computed).
- size_t byte_offset = kInvalidOffset;
-
- template<typename Vector>
- void Encode(Vector* dest) const {
- EncodeUnsignedLeb128(dest, num_entries);
- EncodeUnsignedLeb128(dest, num_bytes);
- }
-
- ALWAYS_INLINE void Decode(const uint8_t** ptr) {
- num_entries = DecodeUnsignedLeb128(ptr);
- num_bytes = DecodeUnsignedLeb128(ptr);
- }
-
- // Set the bit offset of the table. Adds the total bit size of the table to offset.
- void UpdateBitOffset(size_t* offset) {
- DCHECK(offset != nullptr);
- DCHECK_ALIGNED(*offset, kBitsPerByte);
- byte_offset = *offset / kBitsPerByte;
- *offset += num_bytes * kBitsPerByte;
- }
};
-// Format is [native pc, invoke type, method index].
-class InvokeInfoEncoding {
+class InvokeInfo : public BitTable<3>::Accessor {
public:
- void SetFromSizes(size_t native_pc_max,
- size_t invoke_type_max,
- size_t method_index_max) {
- total_bit_size_ = 0;
- DCHECK_EQ(kNativePcBitOffset, total_bit_size_);
- total_bit_size_ += MinimumBitsToStore(native_pc_max);
- invoke_type_bit_offset_ = total_bit_size_;
- total_bit_size_ += MinimumBitsToStore(invoke_type_max);
- method_index_bit_offset_ = total_bit_size_;
- total_bit_size_ += MinimumBitsToStore(method_index_max);
- }
-
- ALWAYS_INLINE FieldEncoding GetNativePcEncoding() const {
- return FieldEncoding(kNativePcBitOffset, invoke_type_bit_offset_);
- }
-
- ALWAYS_INLINE FieldEncoding GetInvokeTypeEncoding() const {
- return FieldEncoding(invoke_type_bit_offset_, method_index_bit_offset_);
- }
-
- ALWAYS_INLINE FieldEncoding GetMethodIndexEncoding() const {
- return FieldEncoding(method_index_bit_offset_, total_bit_size_);
- }
-
- ALWAYS_INLINE size_t BitSize() const {
- return total_bit_size_;
- }
-
- template<typename Vector>
- void Encode(Vector* dest) const {
- static_assert(alignof(InvokeInfoEncoding) == 1, "Should not require alignment");
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
- dest->insert(dest->end(), ptr, ptr + sizeof(*this));
- }
-
- void Decode(const uint8_t** ptr) {
- *this = *reinterpret_cast<const InvokeInfoEncoding*>(*ptr);
- *ptr += sizeof(*this);
- }
+ enum Field {
+ kNativePcOffset,
+ kInvokeType,
+ kMethodIndexIdx,
+ kCount,
+ };
- private:
- static constexpr uint8_t kNativePcBitOffset = 0;
- uint8_t invoke_type_bit_offset_;
- uint8_t method_index_bit_offset_;
- uint8_t total_bit_size_;
-};
+ InvokeInfo(const BitTable<kCount>* table, uint32_t row)
+ : BitTable<kCount>::Accessor(table, row) {}
-class InvokeInfo {
- public:
- explicit InvokeInfo(BitMemoryRegion region) : region_(region) {}
-
- ALWAYS_INLINE uint32_t GetNativePcOffset(const InvokeInfoEncoding& encoding,
- InstructionSet instruction_set) const {
- CodeOffset offset(
- CodeOffset::FromCompressedOffset(encoding.GetNativePcEncoding().Load(region_)));
+ ALWAYS_INLINE uint32_t GetNativePcOffset(InstructionSet instruction_set) const {
+ CodeOffset offset(CodeOffset::FromCompressedOffset(Get<kNativePcOffset>()));
return offset.Uint32Value(instruction_set);
}
- ALWAYS_INLINE void SetNativePcCodeOffset(const InvokeInfoEncoding& encoding,
- CodeOffset native_pc_offset) {
- encoding.GetNativePcEncoding().Store(region_, native_pc_offset.CompressedValue());
- }
-
- ALWAYS_INLINE uint32_t GetInvokeType(const InvokeInfoEncoding& encoding) const {
- return encoding.GetInvokeTypeEncoding().Load(region_);
- }
-
- ALWAYS_INLINE void SetInvokeType(const InvokeInfoEncoding& encoding, uint32_t invoke_type) {
- encoding.GetInvokeTypeEncoding().Store(region_, invoke_type);
- }
-
- ALWAYS_INLINE uint32_t GetMethodIndexIdx(const InvokeInfoEncoding& encoding) const {
- return encoding.GetMethodIndexEncoding().Load(region_);
- }
-
- ALWAYS_INLINE void SetMethodIndexIdx(const InvokeInfoEncoding& encoding,
- uint32_t method_index_idx) {
- encoding.GetMethodIndexEncoding().Store(region_, method_index_idx);
- }
-
- ALWAYS_INLINE uint32_t GetMethodIndex(const InvokeInfoEncoding& encoding,
- MethodInfo method_info) const {
- return method_info.GetMethodIndex(GetMethodIndexIdx(encoding));
- }
-
- bool IsValid() const { return region_.IsValid(); }
-
- private:
- BitMemoryRegion region_;
-};
-
-// Most of the fields are encoded as ULEB128 to save space.
-struct CodeInfoEncoding {
- using SizeType = uint32_t;
-
- static constexpr SizeType kInvalidSize = std::numeric_limits<SizeType>::max();
-
- // Byte sized tables go first to avoid unnecessary alignment bits.
- ByteSizedTable dex_register_map;
- ByteSizedTable location_catalog;
- BitEncodingTable<StackMapEncoding> stack_map;
- BitEncodingTable<BitRegionEncoding> register_mask;
- BitEncodingTable<BitRegionEncoding> stack_mask;
- BitEncodingTable<InvokeInfoEncoding> invoke_info;
- BitEncodingTable<InlineInfoEncoding> inline_info;
-
- CodeInfoEncoding() {}
-
- explicit CodeInfoEncoding(const void* data) {
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
- dex_register_map.Decode(&ptr);
- location_catalog.Decode(&ptr);
- stack_map.Decode(&ptr);
- register_mask.Decode(&ptr);
- stack_mask.Decode(&ptr);
- invoke_info.Decode(&ptr);
- if (stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0) {
- inline_info.Decode(&ptr);
- } else {
- inline_info = BitEncodingTable<InlineInfoEncoding>();
- }
- cache_header_size =
- dchecked_integral_cast<SizeType>(ptr - reinterpret_cast<const uint8_t*>(data));
- ComputeTableOffsets();
- }
-
- // Compress is not const since it calculates cache_header_size. This is used by PrepareForFillIn.
- template<typename Vector>
- void Compress(Vector* dest) {
- dex_register_map.Encode(dest);
- location_catalog.Encode(dest);
- stack_map.Encode(dest);
- register_mask.Encode(dest);
- stack_mask.Encode(dest);
- invoke_info.Encode(dest);
- if (stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0) {
- inline_info.Encode(dest);
- }
- cache_header_size = dest->size();
- }
-
- ALWAYS_INLINE void ComputeTableOffsets() {
- // Skip the header.
- size_t bit_offset = HeaderSize() * kBitsPerByte;
- // The byte tables must be aligned so they must go first.
- dex_register_map.UpdateBitOffset(&bit_offset);
- location_catalog.UpdateBitOffset(&bit_offset);
- // Other tables don't require alignment.
- stack_map.UpdateBitOffset(&bit_offset);
- register_mask.UpdateBitOffset(&bit_offset);
- stack_mask.UpdateBitOffset(&bit_offset);
- invoke_info.UpdateBitOffset(&bit_offset);
- inline_info.UpdateBitOffset(&bit_offset);
- cache_non_header_size = RoundUp(bit_offset, kBitsPerByte) / kBitsPerByte - HeaderSize();
- }
+ uint32_t GetInvokeType() const { return Get<kInvokeType>(); }
- ALWAYS_INLINE size_t HeaderSize() const {
- DCHECK_NE(cache_header_size, kInvalidSize) << "Uninitialized";
- return cache_header_size;
- }
+ uint32_t GetMethodIndexIdx() const { return Get<kMethodIndexIdx>(); }
- ALWAYS_INLINE size_t NonHeaderSize() const {
- DCHECK_NE(cache_non_header_size, kInvalidSize) << "Uninitialized";
- return cache_non_header_size;
+ uint32_t GetMethodIndex(MethodInfo method_info) const {
+ return method_info.GetMethodIndex(GetMethodIndexIdx());
}
-
- private:
- // Computed fields (not serialized).
- // Header size in bytes, cached to avoid needing to re-decoding the encoding in HeaderSize.
- SizeType cache_header_size = kInvalidSize;
- // Non header size in bytes, cached to avoid needing to re-decoding the encoding in NonHeaderSize.
- SizeType cache_non_header_size = kInvalidSize;
};
/**
* Wrapper around all compiler information collected for a method.
* The information is of the form:
*
- * [CodeInfoEncoding, DexRegisterMap+, DexLocationCatalog+, StackMap+, RegisterMask+, StackMask+,
- * InlineInfo*]
- *
- * where CodeInfoEncoding is of the form:
+ * [BitTable<Header>, BitTable<StackMap>, BitTable<RegisterMask>, BitTable<InlineInfo>,
+ * BitTable<InvokeInfo>, BitTable<StackMask>, DexRegisterMap, DexLocationCatalog]
*
- * [ByteSizedTable(dex_register_map), ByteSizedTable(location_catalog),
- * BitEncodingTable<StackMapEncoding>, BitEncodingTable<BitRegionEncoding>,
- * BitEncodingTable<BitRegionEncoding>, BitEncodingTable<InlineInfoEncoding>]
*/
class CodeInfo {
public:
- explicit CodeInfo(MemoryRegion region) : region_(region) {
- }
-
explicit CodeInfo(const void* data) {
- CodeInfoEncoding encoding = CodeInfoEncoding(data);
- region_ = MemoryRegion(const_cast<void*>(data),
- encoding.HeaderSize() + encoding.NonHeaderSize());
+ Decode(reinterpret_cast<const uint8_t*>(data));
}
- CodeInfoEncoding ExtractEncoding() const {
- CodeInfoEncoding encoding(region_.begin());
- AssertValidStackMap(encoding);
- return encoding;
+ explicit CodeInfo(MemoryRegion region) : CodeInfo(region.begin()) {
+ DCHECK_EQ(size_, region.size());
}
- bool HasInlineInfo(const CodeInfoEncoding& encoding) const {
- return encoding.stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0;
+ explicit CodeInfo(const OatQuickMethodHeader* header)
+ : CodeInfo(header->GetOptimizedCodeInfoPtr()) {
}
- DexRegisterLocationCatalog GetDexRegisterLocationCatalog(const CodeInfoEncoding& encoding) const {
- return DexRegisterLocationCatalog(region_.Subregion(encoding.location_catalog.byte_offset,
- encoding.location_catalog.num_bytes));
+ size_t Size() const {
+ return size_;
}
- ALWAYS_INLINE size_t GetNumberOfStackMaskBits(const CodeInfoEncoding& encoding) const {
- return encoding.stack_mask.encoding.BitSize();
+ bool HasInlineInfo() const {
+ return stack_maps_.NumColumnBits(StackMap::kInlineInfoIndex) != 0;
}
- ALWAYS_INLINE StackMap GetStackMapAt(size_t index, const CodeInfoEncoding& encoding) const {
- return StackMap(encoding.stack_map.BitRegion(region_, index));
+ DexRegisterLocationCatalog GetDexRegisterLocationCatalog() const {
+ return DexRegisterLocationCatalog(location_catalog_);
}
- BitMemoryRegion GetStackMask(size_t index, const CodeInfoEncoding& encoding) const {
- return encoding.stack_mask.BitRegion(region_, index);
+ ALWAYS_INLINE size_t GetNumberOfStackMaskBits() const {
+ return stack_mask_bits_;
}
- BitMemoryRegion GetStackMaskOf(const CodeInfoEncoding& encoding,
- const StackMap& stack_map) const {
- return GetStackMask(stack_map.GetStackMaskIndex(encoding.stack_map.encoding), encoding);
+ ALWAYS_INLINE StackMap GetStackMapAt(size_t index) const {
+ return StackMap(&stack_maps_, index);
}
- BitMemoryRegion GetRegisterMask(size_t index, const CodeInfoEncoding& encoding) const {
- return encoding.register_mask.BitRegion(region_, index);
+ BitMemoryRegion GetStackMask(size_t index) const {
+ return stack_masks_.Subregion(index * stack_mask_bits_, stack_mask_bits_);
}
- uint32_t GetRegisterMaskOf(const CodeInfoEncoding& encoding, const StackMap& stack_map) const {
- size_t index = stack_map.GetRegisterMaskIndex(encoding.stack_map.encoding);
- return GetRegisterMask(index, encoding).LoadBits(0u, encoding.register_mask.encoding.BitSize());
+ BitMemoryRegion GetStackMaskOf(const StackMap& stack_map) const {
+ return GetStackMask(stack_map.GetStackMaskIndex());
}
- uint32_t GetNumberOfLocationCatalogEntries(const CodeInfoEncoding& encoding) const {
- return encoding.location_catalog.num_entries;
+ uint32_t GetRegisterMaskOf(const StackMap& stack_map) const {
+ return register_masks_.Get(stack_map.GetRegisterMaskIndex());
}
- uint32_t GetDexRegisterLocationCatalogSize(const CodeInfoEncoding& encoding) const {
- return encoding.location_catalog.num_bytes;
+ uint32_t GetNumberOfLocationCatalogEntries() const {
+ return location_catalog_entries_;
}
- uint32_t GetNumberOfStackMaps(const CodeInfoEncoding& encoding) const {
- return encoding.stack_map.num_entries;
+ uint32_t GetDexRegisterLocationCatalogSize() const {
+ return location_catalog_.size();
}
- // Get the size of all the stack maps of this CodeInfo object, in bits. Not byte aligned.
- ALWAYS_INLINE size_t GetStackMapsSizeInBits(const CodeInfoEncoding& encoding) const {
- return encoding.stack_map.encoding.BitSize() * GetNumberOfStackMaps(encoding);
+ uint32_t GetNumberOfStackMaps() const {
+ return stack_maps_.NumRows();
}
- InvokeInfo GetInvokeInfo(const CodeInfoEncoding& encoding, size_t index) const {
- return InvokeInfo(encoding.invoke_info.BitRegion(region_, index));
+ InvokeInfo GetInvokeInfo(size_t index) const {
+ return InvokeInfo(&invoke_infos_, index);
}
DexRegisterMap GetDexRegisterMapOf(StackMap stack_map,
- const CodeInfoEncoding& encoding,
size_t number_of_dex_registers) const {
- if (!stack_map.HasDexRegisterMap(encoding.stack_map.encoding)) {
+ if (!stack_map.HasDexRegisterMap()) {
return DexRegisterMap();
}
- const uint32_t offset = encoding.dex_register_map.byte_offset +
- stack_map.GetDexRegisterMapOffset(encoding.stack_map.encoding);
- size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers);
- return DexRegisterMap(region_.Subregion(offset, size));
+ const uint32_t offset = stack_map.GetDexRegisterMapOffset();
+ size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
+ return DexRegisterMap(dex_register_maps_.Subregion(offset, size));
}
- size_t GetDexRegisterMapsSize(const CodeInfoEncoding& encoding,
- uint32_t number_of_dex_registers) const {
+ size_t GetDexRegisterMapsSize(uint32_t number_of_dex_registers) const {
size_t total = 0;
- for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) {
- StackMap stack_map = GetStackMapAt(i, encoding);
- DexRegisterMap map(GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers));
+ for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
+ StackMap stack_map = GetStackMapAt(i);
+ DexRegisterMap map(GetDexRegisterMapOf(stack_map, number_of_dex_registers));
total += map.Size();
}
return total;
@@ -1453,38 +892,30 @@ class CodeInfo {
// Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`.
DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
InlineInfo inline_info,
- const CodeInfoEncoding& encoding,
uint32_t number_of_dex_registers) const {
- if (!inline_info.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, depth)) {
+ if (!inline_info.HasDexRegisterMapAtDepth(depth)) {
return DexRegisterMap();
} else {
- uint32_t offset = encoding.dex_register_map.byte_offset +
- inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info.encoding, depth);
- size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers);
- return DexRegisterMap(region_.Subregion(offset, size));
+ uint32_t offset = inline_info.GetDexRegisterMapOffsetAtDepth(depth);
+ size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
+ return DexRegisterMap(dex_register_maps_.Subregion(offset, size));
}
}
- InlineInfo GetInlineInfo(size_t index, const CodeInfoEncoding& encoding) const {
- // Since we do not know the depth, we just return the whole remaining map. The caller may
- // access the inline info for arbitrary depths. To return the precise inline info we would need
- // to count the depth before returning.
- // TODO: Clean this up.
- const size_t bit_offset = encoding.inline_info.bit_offset +
- index * encoding.inline_info.encoding.BitSize();
- return InlineInfo(BitMemoryRegion(region_, bit_offset, region_.size_in_bits() - bit_offset));
+ InlineInfo GetInlineInfo(size_t index) const {
+ return InlineInfo(&inline_infos_, index);
}
- InlineInfo GetInlineInfoOf(StackMap stack_map, const CodeInfoEncoding& encoding) const {
- DCHECK(stack_map.HasInlineInfo(encoding.stack_map.encoding));
- uint32_t index = stack_map.GetInlineInfoIndex(encoding.stack_map.encoding);
- return GetInlineInfo(index, encoding);
+ InlineInfo GetInlineInfoOf(StackMap stack_map) const {
+ DCHECK(stack_map.HasInlineInfo());
+ uint32_t index = stack_map.GetInlineInfoIndex();
+ return GetInlineInfo(index);
}
- StackMap GetStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
- for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) {
- StackMap stack_map = GetStackMapAt(i, encoding);
- if (stack_map.GetDexPc(encoding.stack_map.encoding) == 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) {
return stack_map;
}
}
@@ -1493,40 +924,39 @@ class CodeInfo {
// Searches the stack map list backwards because catch stack maps are stored
// at the end.
- StackMap GetCatchStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
- for (size_t i = GetNumberOfStackMaps(encoding); i > 0; --i) {
- StackMap stack_map = GetStackMapAt(i - 1, encoding);
- if (stack_map.GetDexPc(encoding.stack_map.encoding) == dex_pc) {
+ 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) {
return stack_map;
}
}
return StackMap();
}
- StackMap GetOsrStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
- size_t e = GetNumberOfStackMaps(encoding);
+ 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.
- const StackMapEncoding& stack_map_encoding = encoding.stack_map.encoding;
for (size_t i = 0; i < e - 1; ++i) {
- StackMap stack_map = GetStackMapAt(i, encoding);
- if (stack_map.GetDexPc(stack_map_encoding) == dex_pc) {
- StackMap other = GetStackMapAt(i + 1, encoding);
- if (other.GetDexPc(stack_map_encoding) == dex_pc &&
- other.GetNativePcOffset(stack_map_encoding, kRuntimeISA) ==
- stack_map.GetNativePcOffset(stack_map_encoding, kRuntimeISA)) {
- DCHECK_EQ(other.GetDexRegisterMapOffset(stack_map_encoding),
- stack_map.GetDexRegisterMapOffset(stack_map_encoding));
- DCHECK(!stack_map.HasInlineInfo(stack_map_encoding));
+ 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)) {
+ DCHECK_EQ(other.GetDexRegisterMapOffset(),
+ stack_map.GetDexRegisterMapOffset());
+ DCHECK(!stack_map.HasInlineInfo());
if (i < e - 2) {
// Make sure there are not three identical stack maps following each other.
DCHECK_NE(
- stack_map.GetNativePcOffset(stack_map_encoding, kRuntimeISA),
- GetStackMapAt(i + 2, encoding).GetNativePcOffset(stack_map_encoding, kRuntimeISA));
+ stack_map.GetNativePcOffset(kRuntimeISA),
+ GetStackMapAt(i + 2).GetNativePcOffset(kRuntimeISA));
}
return stack_map;
}
@@ -1535,30 +965,27 @@ class CodeInfo {
return StackMap();
}
- StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset,
- const CodeInfoEncoding& encoding) const {
+ StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) 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(encoding); i < e; ++i) {
- StackMap stack_map = GetStackMapAt(i, encoding);
- if (stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA) ==
- native_pc_offset) {
+ 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;
}
}
return StackMap();
}
- InvokeInfo GetInvokeInfoForNativePcOffset(uint32_t native_pc_offset,
- const CodeInfoEncoding& encoding) {
- for (size_t index = 0; index < encoding.invoke_info.num_entries; index++) {
- InvokeInfo item = GetInvokeInfo(encoding, index);
- if (item.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA) == native_pc_offset) {
+ InvokeInfo GetInvokeInfoForNativePcOffset(uint32_t native_pc_offset) {
+ for (size_t index = 0; index < invoke_infos_.NumRows(); index++) {
+ InvokeInfo item = GetInvokeInfo(index);
+ if (item.GetNativePcOffset(kRuntimeISA) == native_pc_offset) {
return item;
}
}
- return InvokeInfo(BitMemoryRegion());
+ return InvokeInfo(&invoke_infos_, -1);
}
// Dump this CodeInfo object on `os`. `code_offset` is the (absolute)
@@ -1573,23 +1000,10 @@ class CodeInfo {
InstructionSet instruction_set,
const MethodInfo& method_info) const;
- // Check that the code info has valid stack map and abort if it does not.
- void AssertValidStackMap(const CodeInfoEncoding& encoding) const {
- if (region_.size() != 0 && region_.size_in_bits() < GetStackMapsSizeInBits(encoding)) {
- LOG(FATAL) << region_.size() << "\n"
- << encoding.HeaderSize() << "\n"
- << encoding.NonHeaderSize() << "\n"
- << encoding.location_catalog.num_entries << "\n"
- << encoding.stack_map.num_entries << "\n"
- << encoding.stack_map.encoding.BitSize();
- }
- }
-
private:
// Compute the size of the Dex register map associated to the stack map at
// `dex_register_map_offset_in_code_info`.
- size_t ComputeDexRegisterMapSizeOf(const CodeInfoEncoding& encoding,
- uint32_t dex_register_map_offset_in_code_info,
+ size_t ComputeDexRegisterMapSizeOf(uint32_t dex_register_map_offset,
uint16_t number_of_dex_registers) const {
// Offset where the actual mapping data starts within art::DexRegisterMap.
size_t location_mapping_data_offset_in_dex_register_map =
@@ -1597,12 +1011,12 @@ class CodeInfo {
// Create a temporary art::DexRegisterMap to be able to call
// art::DexRegisterMap::GetNumberOfLiveDexRegisters and
DexRegisterMap dex_register_map_without_locations(
- MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info,
- location_mapping_data_offset_in_dex_register_map)));
+ MemoryRegion(dex_register_maps_.Subregion(dex_register_map_offset,
+ location_mapping_data_offset_in_dex_register_map)));
size_t number_of_live_dex_registers =
dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
size_t location_mapping_data_size_in_bits =
- DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries(encoding))
+ DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries())
* number_of_live_dex_registers;
size_t location_mapping_data_size_in_bytes =
RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
@@ -1611,37 +1025,42 @@ class CodeInfo {
return dex_register_map_size;
}
- // Compute the size of a Dex register location catalog starting at offset `origin`
- // in `region_` and containing `number_of_dex_locations` entries.
- size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin,
- uint32_t number_of_dex_locations) const {
- // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or
- // art::DexRegisterLocationCatalog::FindLocationOffset, but the
- // DexRegisterLocationCatalog is not yet built. Try to factor common code.
- size_t offset = origin + DexRegisterLocationCatalog::kFixedSize;
-
- // Skip the first `number_of_dex_locations - 1` entries.
- for (uint16_t i = 0; i < number_of_dex_locations; ++i) {
- // Read the first next byte and inspect its first 3 bits to decide
- // whether it is a short or a large location.
- DexRegisterLocationCatalog::ShortLocation first_byte =
- region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset);
- DexRegisterLocation::Kind kind =
- DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte);
- if (DexRegisterLocation::IsShortLocationKind(kind)) {
- // Short location. Skip the current byte.
- offset += DexRegisterLocationCatalog::SingleShortEntrySize();
- } else {
- // Large location. Skip the 5 next bytes.
- offset += DexRegisterLocationCatalog::SingleLargeEntrySize();
- }
- }
- size_t size = offset - origin;
- return size;
- }
-
- MemoryRegion region_;
- friend class StackMapStream;
+ MemoryRegion DecodeMemoryRegion(MemoryRegion& region, size_t* bit_offset) {
+ size_t length = DecodeVarintBits(BitMemoryRegion(region), bit_offset);
+ size_t offset = BitsToBytesRoundUp(*bit_offset);;
+ *bit_offset = (offset + length) * kBitsPerByte;
+ return region.Subregion(offset, length);
+ }
+
+ void Decode(const uint8_t* data) {
+ size_t non_header_size = DecodeUnsignedLeb128(&data);
+ MemoryRegion region(const_cast<uint8_t*>(data), non_header_size);
+ BitMemoryRegion bit_region(region);
+ size_t bit_offset = 0;
+ size_ = UnsignedLeb128Size(non_header_size) + non_header_size;
+ dex_register_maps_ = DecodeMemoryRegion(region, &bit_offset);
+ location_catalog_entries_ = DecodeVarintBits(bit_region, &bit_offset);
+ location_catalog_ = DecodeMemoryRegion(region, &bit_offset);
+ stack_maps_.Decode(bit_region, &bit_offset);
+ invoke_infos_.Decode(bit_region, &bit_offset);
+ inline_infos_.Decode(bit_region, &bit_offset);
+ register_masks_.Decode(bit_region, &bit_offset);
+ stack_mask_bits_ = DecodeVarintBits(bit_region, &bit_offset);
+ stack_masks_ = bit_region.Subregion(bit_offset, non_header_size * kBitsPerByte - bit_offset);
+ }
+
+ size_t size_;
+ MemoryRegion dex_register_maps_;
+ uint32_t location_catalog_entries_;
+ MemoryRegion location_catalog_;
+ BitTable<StackMap::Field::kCount> stack_maps_;
+ BitTable<InvokeInfo::Field::kCount> invoke_infos_;
+ BitTable<InlineInfo::Field::kCount> inline_infos_;
+ BitTable<1> register_masks_;
+ uint32_t stack_mask_bits_ = 0;
+ BitMemoryRegion stack_masks_;
+
+ friend class OatDumper;
};
#undef ELEMENT_BYTE_OFFSET_AFTER
diff --git a/runtime/thread.cc b/runtime/thread.cc
index eada24d257..81ed722fcc 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3559,16 +3559,15 @@ class ReferenceMapVisitor : public StackVisitor {
StackReference<mirror::Object>* vreg_base = reinterpret_cast<StackReference<mirror::Object>*>(
reinterpret_cast<uintptr_t>(cur_quick_frame));
uintptr_t native_pc_offset = method_header->NativeQuickPcOffset(GetCurrentQuickFramePc());
- CodeInfo code_info = method_header->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = code_info.ExtractEncoding();
- StackMap map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
+ CodeInfo code_info(method_header);
+ StackMap map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
DCHECK(map.IsValid());
- T vreg_info(m, code_info, encoding, map, visitor_);
+ T vreg_info(m, code_info, map, visitor_);
// Visit stack entries that hold pointers.
- const size_t number_of_bits = code_info.GetNumberOfStackMaskBits(encoding);
- BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, map);
+ const size_t number_of_bits = code_info.GetNumberOfStackMaskBits();
+ BitMemoryRegion stack_mask = code_info.GetStackMaskOf(map);
for (size_t i = 0; i < number_of_bits; ++i) {
if (stack_mask.LoadBit(i)) {
StackReference<mirror::Object>* ref_addr = vreg_base + i;
@@ -3583,7 +3582,7 @@ class ReferenceMapVisitor : public StackVisitor {
}
}
// Visit callee-save registers that hold pointers.
- uint32_t register_mask = code_info.GetRegisterMaskOf(encoding, map);
+ uint32_t register_mask = code_info.GetRegisterMaskOf(map);
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));
@@ -3631,7 +3630,6 @@ class ReferenceMapVisitor : public StackVisitor {
struct UndefinedVRegInfo {
UndefinedVRegInfo(ArtMethod* method ATTRIBUTE_UNUSED,
const CodeInfo& code_info ATTRIBUTE_UNUSED,
- const CodeInfoEncoding& encoding ATTRIBUTE_UNUSED,
const StackMap& map ATTRIBUTE_UNUSED,
RootVisitor& _visitor)
: visitor(_visitor) {
@@ -3662,14 +3660,11 @@ class ReferenceMapVisitor : public StackVisitor {
struct StackMapVRegInfo {
StackMapVRegInfo(ArtMethod* method,
const CodeInfo& _code_info,
- const CodeInfoEncoding& _encoding,
const StackMap& map,
RootVisitor& _visitor)
: number_of_dex_registers(method->DexInstructionData().RegistersSize()),
code_info(_code_info),
- encoding(_encoding),
dex_register_map(code_info.GetDexRegisterMapOf(map,
- encoding,
number_of_dex_registers)),
visitor(_visitor) {
}
@@ -3684,7 +3679,7 @@ class ReferenceMapVisitor : public StackVisitor {
bool found = false;
for (size_t dex_reg = 0; dex_reg != number_of_dex_registers; ++dex_reg) {
DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(
- dex_reg, number_of_dex_registers, code_info, encoding);
+ dex_reg, number_of_dex_registers, code_info);
if (location.GetKind() == kind && static_cast<size_t>(location.GetValue()) == index) {
visitor(ref, dex_reg, stack_visitor);
found = true;
@@ -3718,7 +3713,6 @@ class ReferenceMapVisitor : public StackVisitor {
size_t number_of_dex_registers;
const CodeInfo& code_info;
- const CodeInfoEncoding& encoding;
DexRegisterMap dex_register_map;
RootVisitor& visitor;
};
diff --git a/test/566-polymorphic-inlining/polymorphic_inline.cc b/test/566-polymorphic-inlining/polymorphic_inline.cc
index e2b8aa037f..7c1507fb5c 100644
--- a/test/566-polymorphic-inlining/polymorphic_inline.cc
+++ b/test/566-polymorphic-inlining/polymorphic_inline.cc
@@ -48,9 +48,8 @@ static void do_checks(jclass cls, const char* method_name) {
}
}
- CodeInfo info = header->GetOptimizedCodeInfo();
- CodeInfoEncoding encoding = info.ExtractEncoding();
- CHECK(info.HasInlineInfo(encoding));
+ CodeInfo info(header);
+ CHECK(info.HasInlineInfo());
}
static void allocate_profiling_info(jclass cls, const char* method_name) {
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 7d2cae829e..493582fa48 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -651,12 +651,6 @@
"description": ["Requires zip, which isn't available on device"]
},
{
- "tests": "712-varhandle-invocations",
- "variant": "speed-profile & debug & gcstress & target",
- "bug": "b/73275005",
- "description": ["Time out"]
- },
- {
"tests": ["1941-dispose-stress", "522-checker-regression-monitor-exit"],
"variant": "jvm",
"bug": "b/73888836",
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index d376cad9da..eebc09278a 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -360,7 +360,9 @@ echo "Killing stalled dalvikvm processes..."
if [[ $mode == "host" ]]; then
pkill -9 -f /bin/dalvikvm
else
- adb shell pkill -9 -f /bin/dalvikvm
+ # Tests may run on older Android versions where pkill requires "-l SIGNAL"
+ # rather than "-SIGNAL".
+ adb shell pkill -l 9 -f /bin/dalvikvm
fi
echo "Done."