From 42deda8a5ee207706df37d7cb56d2a48e94073f0 Mon Sep 17 00:00:00 2001 From: David Srbecky Date: Fri, 10 Aug 2018 11:23:27 +0100 Subject: Add helper method to iterate over BitTable fields in CodeInfo. Avoid the repetitive code patterns and simplify code. Test: test-art-host-gtest-stack_map_test Test: checked output of oatdump Change-Id: I2354bc652837eb34efeecf4de56a027384544034 --- runtime/stack_map.cc | 246 ++++++++++++++++++++++----------------------------- 1 file changed, 106 insertions(+), 140 deletions(-) (limited to 'runtime/stack_map.cc') diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc index 689904a983..62dec15c57 100644 --- a/runtime/stack_map.cc +++ b/runtime/stack_map.cc @@ -31,93 +31,67 @@ CodeInfo::CodeInfo(const OatQuickMethodHeader* header, DecodeFlags flags) : CodeInfo(header->GetOptimizedCodeInfoPtr(), flags) { } +// Returns true if the decoded table was deduped. template -ALWAYS_INLINE static void DecodeTable(BitTable& table, - BitMemoryReader& reader, - const uint8_t* reader_data) { - if (reader.ReadBit() /* is_deduped */) { +ALWAYS_INLINE static bool DecodeTable(BitTable& table, BitMemoryReader& reader) { + bool is_deduped = reader.ReadBit(); + if (is_deduped) { ssize_t bit_offset = reader.NumberOfReadBits() - reader.ReadVarint(); - BitMemoryReader reader2(reader_data, bit_offset); // The offset is negative. + BitMemoryReader reader2(reader.data(), bit_offset); // The offset is negative. table.Decode(reader2); } else { table.Decode(reader); } + return is_deduped; } void CodeInfo::Decode(const uint8_t* data, DecodeFlags flags) { BitMemoryReader reader(data); - packed_frame_size_ = reader.ReadVarint(); - core_spill_mask_ = reader.ReadVarint(); - fp_spill_mask_ = reader.ReadVarint(); - number_of_dex_registers_ = reader.ReadVarint(); - DecodeTable(stack_maps_, reader, data); - DecodeTable(register_masks_, reader, data); - DecodeTable(stack_masks_, reader, data); - if (flags & DecodeFlags::GcMasksOnly) { - return; - } - DecodeTable(inline_infos_, reader, data); - DecodeTable(method_infos_, reader, data); - if (flags & DecodeFlags::InlineInfoOnly) { - return; - } - DecodeTable(dex_register_masks_, reader, data); - DecodeTable(dex_register_maps_, reader, data); - DecodeTable(dex_register_catalog_, reader, data); + ForEachHeaderField([this, &reader](auto member_pointer) { + this->*member_pointer = reader.ReadVarint(); + }); + ForEachBitTableField([this, &reader](auto member_pointer) { + DecodeTable(this->*member_pointer, reader); + }, flags); size_in_bits_ = reader.NumberOfReadBits(); } -template -ALWAYS_INLINE void CodeInfo::Deduper::DedupeTable(BitMemoryReader& reader) { - bool is_deduped = reader.ReadBit(); - DCHECK(!is_deduped); - size_t bit_table_start = reader.NumberOfReadBits(); - BitTable bit_table(reader); - BitMemoryRegion region = reader.GetReadRegion().Subregion(bit_table_start); - auto it = dedupe_map_.insert(std::make_pair(region, /* placeholder */ 0)); - if (it.second /* new bit table */ || region.size_in_bits() < 32) { - writer_.WriteBit(false); // Is not deduped. - it.first->second = writer_.NumberOfWrittenBits(); - writer_.WriteRegion(region); - } else { - writer_.WriteBit(true); // Is deduped. - size_t bit_offset = writer_.NumberOfWrittenBits(); - writer_.WriteVarint(bit_offset - it.first->second); - } -} - -size_t CodeInfo::Deduper::Dedupe(const uint8_t* code_info) { +size_t CodeInfo::Deduper::Dedupe(const uint8_t* code_info_data) { writer_.ByteAlign(); size_t deduped_offset = writer_.NumberOfWrittenBits() / kBitsPerByte; - BitMemoryReader reader(code_info); - writer_.WriteVarint(reader.ReadVarint()); // packed_frame_size_. - writer_.WriteVarint(reader.ReadVarint()); // core_spill_mask_. - writer_.WriteVarint(reader.ReadVarint()); // fp_spill_mask_. - writer_.WriteVarint(reader.ReadVarint()); // number_of_dex_registers_. - DedupeTable(reader); - DedupeTable(reader); - DedupeTable(reader); - DedupeTable(reader); - DedupeTable(reader); - DedupeTable(reader); - DedupeTable(reader); - DedupeTable(reader); + BitMemoryReader reader(code_info_data); + CodeInfo code_info; // Temporary storage for decoded data. + ForEachHeaderField([this, &reader, &code_info](auto member_pointer) { + code_info.*member_pointer = reader.ReadVarint(); + writer_.WriteVarint(code_info.*member_pointer); + }); + ForEachBitTableField([this, &reader, &code_info](auto member_pointer) { + bool is_deduped = reader.ReadBit(); + DCHECK(!is_deduped); + size_t bit_table_start = reader.NumberOfReadBits(); + (code_info.*member_pointer).Decode(reader); + BitMemoryRegion region = reader.GetReadRegion().Subregion(bit_table_start); + auto it = dedupe_map_.insert(std::make_pair(region, /* placeholder */ 0)); + if (it.second /* new bit table */ || region.size_in_bits() < 32) { + writer_.WriteBit(false); // Is not deduped. + it.first->second = writer_.NumberOfWrittenBits(); + writer_.WriteRegion(region); + } else { + writer_.WriteBit(true); // Is deduped. + size_t bit_offset = writer_.NumberOfWrittenBits(); + writer_.WriteVarint(bit_offset - it.first->second); + } + }); if (kIsDebugBuild) { - CodeInfo old_code_info(code_info); + CodeInfo old_code_info(code_info_data); CodeInfo new_code_info(writer_.data() + deduped_offset); - DCHECK_EQ(old_code_info.packed_frame_size_, new_code_info.packed_frame_size_); - DCHECK_EQ(old_code_info.core_spill_mask_, new_code_info.core_spill_mask_); - DCHECK_EQ(old_code_info.fp_spill_mask_, new_code_info.fp_spill_mask_); - DCHECK_EQ(old_code_info.number_of_dex_registers_, new_code_info.number_of_dex_registers_); - DCHECK(old_code_info.stack_maps_.Equals(new_code_info.stack_maps_)); - DCHECK(old_code_info.register_masks_.Equals(new_code_info.register_masks_)); - DCHECK(old_code_info.stack_masks_.Equals(new_code_info.stack_masks_)); - DCHECK(old_code_info.inline_infos_.Equals(new_code_info.inline_infos_)); - DCHECK(old_code_info.method_infos_.Equals(new_code_info.method_infos_)); - DCHECK(old_code_info.dex_register_masks_.Equals(new_code_info.dex_register_masks_)); - DCHECK(old_code_info.dex_register_maps_.Equals(new_code_info.dex_register_maps_)); - DCHECK(old_code_info.dex_register_catalog_.Equals(new_code_info.dex_register_catalog_)); + ForEachHeaderField([&old_code_info, &new_code_info](auto member_pointer) { + DCHECK_EQ(old_code_info.*member_pointer, new_code_info.*member_pointer); + }); + ForEachBitTableField([&old_code_info, &new_code_info](auto member_pointer) { + DCHECK((old_code_info.*member_pointer).Equals(new_code_info.*member_pointer)); + }); } return deduped_offset; @@ -207,33 +181,32 @@ void CodeInfo::DecodeDexRegisterMap(uint32_t stack_map_index, } } -template -static void AddTableSizeStats(const char* table_name, - const BitTable& table, - /*out*/ Stats* parent) { - Stats* table_stats = parent->Child(table_name); - table_stats->AddBits(table.BitSize()); - table_stats->Child("Header")->AddBits(table.HeaderBitSize()); - const char* const* column_names = GetBitTableColumnNames(); - for (size_t c = 0; c < table.NumColumns(); c++) { - if (table.NumColumnBits(c) > 0) { - Stats* column_stats = table_stats->Child(column_names[c]); - column_stats->AddBits(table.NumRows() * table.NumColumnBits(c), table.NumRows()); +// Decode the CodeInfo while collecting size statistics. +void CodeInfo::CollectSizeStats(const uint8_t* code_info_data, /*out*/ Stats* parent) { + Stats* codeinfo_stats = parent->Child("CodeInfo"); + BitMemoryReader reader(code_info_data); + ForEachHeaderField([&reader](auto) { reader.ReadVarint(); }); + codeinfo_stats->Child("Header")->AddBits(reader.NumberOfReadBits()); + CodeInfo code_info; // Temporary storage for decoded tables. + ForEachBitTableField([codeinfo_stats, &reader, &code_info](auto member_pointer) { + auto& table = code_info.*member_pointer; + size_t bit_offset = reader.NumberOfReadBits(); + bool deduped = DecodeTable(table, reader); + if (deduped) { + codeinfo_stats->Child("DedupeOffset")->AddBits(reader.NumberOfReadBits() - bit_offset); + } else { + Stats* table_stats = codeinfo_stats->Child(table.GetName()); + table_stats->AddBits(reader.NumberOfReadBits() - bit_offset); + const char* const* column_names = table.GetColumnNames(); + for (size_t c = 0; c < table.NumColumns(); c++) { + if (table.NumColumnBits(c) > 0) { + Stats* column_stats = table_stats->Child(column_names[c]); + column_stats->AddBits(table.NumRows() * table.NumColumnBits(c), table.NumRows()); + } + } } - } -} - -void CodeInfo::AddSizeStats(/*out*/ Stats* parent) const { - Stats* stats = parent->Child("CodeInfo"); - stats->AddBytes(Size()); - AddTableSizeStats("StackMaps", stack_maps_, stats); - AddTableSizeStats("RegisterMasks", register_masks_, stats); - AddTableSizeStats("StackMasks", stack_masks_, stats); - AddTableSizeStats("InlineInfos", inline_infos_, stats); - AddTableSizeStats("MethodInfo", method_infos_, stats); - AddTableSizeStats("DexRegisterMasks", dex_register_masks_, stats); - AddTableSizeStats("DexRegisterMaps", dex_register_maps_, stats); - AddTableSizeStats("DexRegisterCatalog", dex_register_catalog_, stats); + }); + codeinfo_stats->AddBytes(BitsToBytesRoundUp(reader.NumberOfReadBits())); } void DexRegisterMap::Dump(VariableIndentationOutputStream* vios) const { @@ -249,56 +222,49 @@ void DexRegisterMap::Dump(VariableIndentationOutputStream* vios) const { } } -template -static void DumpTable(VariableIndentationOutputStream* vios, - const char* table_name, - const BitTable& table, - bool verbose, - bool is_mask = false) { - if (table.NumRows() != 0) { - vios->Stream() << table_name << " BitSize=" << table.BitSize(); - vios->Stream() << " Rows=" << table.NumRows() << " Bits={"; - const char* const* column_names = GetBitTableColumnNames(); - for (size_t c = 0; c < table.NumColumns(); c++) { - vios->Stream() << (c != 0 ? " " : ""); - vios->Stream() << column_names[c] << "=" << table.NumColumnBits(c); - } - vios->Stream() << "}\n"; - if (verbose) { - ScopedIndentation indent1(vios); - for (size_t r = 0; r < table.NumRows(); r++) { - vios->Stream() << "[" << std::right << std::setw(3) << r << "]={"; - for (size_t c = 0; c < table.NumColumns(); c++) { - vios->Stream() << (c != 0 ? " " : ""); - if (is_mask) { - BitMemoryRegion bits = table.GetBitMemoryRegion(r, c); - for (size_t b = 0, e = bits.size_in_bits(); b < e; b++) { - vios->Stream() << bits.LoadBit(e - b - 1); - } - } else { - vios->Stream() << std::right << std::setw(8) << static_cast(table.Get(r, c)); - } - } - vios->Stream() << "}\n"; - } - } - } -} - void CodeInfo::Dump(VariableIndentationOutputStream* vios, uint32_t code_offset, bool verbose, InstructionSet instruction_set) const { - vios->Stream() << "CodeInfo\n"; + vios->Stream() << "CodeInfo BitSize=" << size_in_bits_ + << " FrameSize:" << packed_frame_size_ * kStackAlignment + << " CoreSpillMask:" << std::hex << core_spill_mask_ + << " FpSpillMask:" << std::hex << fp_spill_mask_ + << " NumberOfDexRegisters:" << std::dec << number_of_dex_registers_ + << "\n"; ScopedIndentation indent1(vios); - DumpTable(vios, "StackMaps", stack_maps_, verbose); - DumpTable(vios, "RegisterMasks", register_masks_, verbose); - DumpTable(vios, "StackMasks", stack_masks_, verbose, true /* is_mask */); - DumpTable(vios, "InlineInfos", inline_infos_, verbose); - DumpTable(vios, "MethodInfo", method_infos_, verbose); - DumpTable(vios, "DexRegisterMasks", dex_register_masks_, verbose, true /* is_mask */); - DumpTable(vios, "DexRegisterMaps", dex_register_maps_, verbose); - DumpTable(vios, "DexRegisterCatalog", dex_register_catalog_, verbose); + ForEachBitTableField([this, &vios, verbose](auto member_pointer) { + const auto& table = this->*member_pointer; + if (table.NumRows() != 0) { + vios->Stream() << table.GetName() << " BitSize=" << table.DataBitSize(); + vios->Stream() << " Rows=" << table.NumRows() << " Bits={"; + const char* const* column_names = table.GetColumnNames(); + for (size_t c = 0; c < table.NumColumns(); c++) { + vios->Stream() << (c != 0 ? " " : ""); + vios->Stream() << column_names[c] << "=" << table.NumColumnBits(c); + } + vios->Stream() << "}\n"; + if (verbose) { + ScopedIndentation indent1(vios); + for (size_t r = 0; r < table.NumRows(); r++) { + vios->Stream() << "[" << std::right << std::setw(3) << r << "]={"; + for (size_t c = 0; c < table.NumColumns(); c++) { + vios->Stream() << (c != 0 ? " " : ""); + if (&table == static_cast(&stack_masks_) || + &table == static_cast(&dex_register_masks_)) { + BitMemoryRegion bits = table.GetBitMemoryRegion(r, c); + for (size_t b = 0, e = bits.size_in_bits(); b < e; b++) { + vios->Stream() << bits.LoadBit(e - b - 1); + } + } else { + vios->Stream() << std::right << std::setw(8) << static_cast(table.Get(r, c)); + } + } + vios->Stream() << "}\n"; + } + } + } + }); // Display stack maps along with (live) Dex register maps. if (verbose) { -- cgit v1.2.3-59-g8ed1b