diff options
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." |