diff options
| -rw-r--r-- | oatdump/oatdump.cc | 181 | ||||
| -rw-r--r-- | oatdump/oatdump_test.cc | 1 | ||||
| -rw-r--r-- | runtime/stack_map.cc | 1 | ||||
| -rw-r--r-- | runtime/stack_map.h | 11 |
4 files changed, 188 insertions, 6 deletions
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 3cf900ed44..3f5243498b 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -529,6 +529,12 @@ class OatDumper { } } + { + os << "OAT FILE STATS:\n"; + VariableIndentationOutputStream vios(&os); + stats_.Dump(vios); + } + os << std::flush; return success; } @@ -574,6 +580,116 @@ class OatDumper { return nullptr; } + struct Stats { + enum ByteKind { + kByteKindCode, + kByteKindQuickMethodHeader, + kByteKindCodeInfoLocationCatalog, + kByteKindCodeInfoDexRegisterMap, + kByteKindCodeInfoInlineInfo, + kByteKindCodeInfoEncoding, + kByteKindCodeInfoOther, + kByteKindStackMapNativePc, + kByteKindStackMapDexPc, + kByteKindStackMapDexRegisterMap, + kByteKindStackMapInlineInfo, + kByteKindStackMapRegisterMask, + kByteKindStackMapMask, + kByteKindStackMapOther, + kByteKindCount, + kByteKindStackMapFirst = kByteKindCodeInfoOther, + kByteKindStackMapLast = kByteKindStackMapOther, + }; + int64_t bits[kByteKindCount] = {}; + // Since code has deduplication, seen tracks already seen pointers to avoid double counting + // deduplicated code and tables. + std::unordered_set<const void*> seen; + + // Returns true if it was newly added. + bool AddBitsIfUnique(ByteKind kind, int64_t count, const void* address) { + if (seen.insert(address).second == true) { + // True means the address was not already in the set. + AddBits(kind, count); + return true; + } + return false; + } + + void AddBits(ByteKind kind, int64_t count) { + bits[kind] += count; + } + + void Dump(VariableIndentationOutputStream& os) { + const int64_t sum = std::accumulate(bits, bits + kByteKindCount, 0u); + os.Stream() << "Dumping cumulative use of " << sum / kBitsPerByte << " accounted bytes\n"; + if (sum > 0) { + const int64_t stack_map_bits = std::accumulate(bits + kByteKindStackMapFirst, + bits + kByteKindStackMapLast + 1, + 0u); + Dump(os, "Code ", bits[kByteKindCode], sum); + Dump(os, "QuickMethodHeader ", bits[kByteKindQuickMethodHeader], sum); + Dump(os, "CodeInfoEncoding ", bits[kByteKindCodeInfoEncoding], sum); + Dump(os, "CodeInfoLocationCatalog ", bits[kByteKindCodeInfoLocationCatalog], sum); + Dump(os, "CodeInfoDexRegisterMap ", bits[kByteKindCodeInfoDexRegisterMap], sum); + Dump(os, "CodeInfoInlineInfo ", bits[kByteKindCodeInfoInlineInfo], sum); + Dump(os, "CodeInfoStackMap ", stack_map_bits, sum); + { + ScopedIndentation indent1(&os); + Dump(os, + "StackMapNativePc ", + bits[kByteKindStackMapNativePc], + stack_map_bits, + "stack map"); + Dump(os, + "StackMapDexPcEncoding ", + bits[kByteKindStackMapDexPc], + stack_map_bits, + "stack map"); + Dump(os, + "StackMapDexRegisterMap ", + bits[kByteKindStackMapDexRegisterMap], + stack_map_bits, + "stack map"); + Dump(os, + "StackMapInlineInfo ", + bits[kByteKindStackMapInlineInfo], + stack_map_bits, + "stack map"); + Dump(os, + "StackMapRegisterMaskEncoding ", + bits[kByteKindStackMapRegisterMask], + stack_map_bits, + "stack map"); + Dump(os, + "StackMapMask ", + bits[kByteKindStackMapMask], + stack_map_bits, + "stack map"); + Dump(os, + "StackMapOther ", + bits[kByteKindStackMapOther], + stack_map_bits, + "stack map"); + } + } + os.Stream() << "\n" << std::flush; + } + + private: + void Dump(VariableIndentationOutputStream& os, + const char* name, + int64_t size, + int64_t total, + const char* sum_of = "total") { + const double percent = (static_cast<double>(size) / static_cast<double>(total)) * 100; + os.Stream() << StringPrintf("%s = %8" PRId64 " (%2.0f%% of %s)\n", + name, + size / kBitsPerByte, + percent, + sum_of); + } + }; + private: void AddAllOffsets() { // We don't know the length of the code for each method, but we need to know where to stop @@ -1046,7 +1162,9 @@ class OatDumper { vios->Stream() << "OatQuickMethodHeader "; uint32_t method_header_offset = oat_method.GetOatQuickMethodHeaderOffset(); const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader(); - + stats_.AddBitsIfUnique(Stats::kByteKindQuickMethodHeader, + sizeof(*method_header) * kBitsPerByte, + method_header); if (options_.absolute_addresses_) { vios->Stream() << StringPrintf("%p ", method_header); } @@ -1118,6 +1236,7 @@ class OatDumper { const void* code = oat_method.GetQuickCode(); uint32_t aligned_code_begin = AlignCodeOffset(code_offset); uint64_t aligned_code_end = aligned_code_begin + code_size; + stats_.AddBitsIfUnique(Stats::kByteKindCode, code_size * kBitsPerByte, code); if (options_.absolute_addresses_) { vios->Stream() << StringPrintf("%p ", code); @@ -1431,6 +1550,60 @@ class OatDumper { } else if (!bad_input && IsMethodGeneratedByOptimizingCompiler(oat_method, code_item)) { // The optimizing compiler outputs its CodeInfo data in the vmap table. StackMapsHelper helper(oat_method.GetVmapTable(), instruction_set_); + { + CodeInfoEncoding encoding(helper.GetEncoding()); + StackMapEncoding stack_map_encoding(encoding.stack_map_encoding); + // helper.GetCodeInfo().GetStackMapAt(0, encoding).; + const size_t num_stack_maps = encoding.number_of_stack_maps; + std::vector<uint8_t> size_vector; + encoding.Compress(&size_vector); + if (stats_.AddBitsIfUnique(Stats::kByteKindCodeInfoEncoding, + size_vector.size() * kBitsPerByte, + oat_method.GetVmapTable())) { + stats_.AddBits( + Stats::kByteKindStackMapNativePc, + stack_map_encoding.GetNativePcEncoding().BitSize() * num_stack_maps); + stats_.AddBits( + Stats::kByteKindStackMapDexPc, + stack_map_encoding.GetDexPcEncoding().BitSize() * num_stack_maps); + stats_.AddBits( + Stats::kByteKindStackMapDexRegisterMap, + stack_map_encoding.GetDexRegisterMapEncoding().BitSize() * num_stack_maps); + stats_.AddBits( + Stats::kByteKindStackMapInlineInfo, + stack_map_encoding.GetInlineInfoEncoding().BitSize() * num_stack_maps); + stats_.AddBits( + Stats::kByteKindStackMapRegisterMask, + stack_map_encoding.GetRegisterMaskEncoding().BitSize() * num_stack_maps); + const size_t stack_mask_bits = encoding.stack_map_size_in_bytes * kBitsPerByte - + stack_map_encoding.GetStackMaskBitOffset(); + stats_.AddBits( + Stats::kByteKindStackMapMask, + stack_mask_bits * num_stack_maps); + const size_t stack_map_bits = + stack_map_encoding.GetStackMaskBitOffset() + stack_mask_bits; + stats_.AddBits( + Stats::kByteKindStackMapOther, + (encoding.stack_map_size_in_bytes * kBitsPerByte - stack_map_bits) * num_stack_maps); + const size_t stack_map_bytes = helper.GetCodeInfo().GetStackMapsSize(encoding); + const size_t location_catalog_bytes = + helper.GetCodeInfo().GetDexRegisterLocationCatalogSize(encoding); + stats_.AddBits(Stats::kByteKindCodeInfoLocationCatalog, + kBitsPerByte * location_catalog_bytes); + const size_t dex_register_bytes = + helper.GetCodeInfo().GetDexRegisterMapsSize(encoding, code_item->registers_size_); + stats_.AddBits( + Stats::kByteKindCodeInfoDexRegisterMap, + kBitsPerByte * dex_register_bytes); + const size_t inline_info_bytes = + encoding.non_header_size - + stack_map_bytes - + location_catalog_bytes - + dex_register_bytes; + stats_.AddBits(Stats::kByteKindCodeInfoInlineInfo, + inline_info_bytes * kBitsPerByte); + } + } const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code); size_t offset = 0; while (offset < code_size) { @@ -1468,6 +1641,7 @@ class OatDumper { const InstructionSet instruction_set_; std::set<uintptr_t> offsets_; Disassembler* disassembler_; + Stats stats_; }; class ImageDumper { @@ -2140,7 +2314,6 @@ class ImageDumper { size_t managed_code_bytes; size_t managed_code_bytes_ignoring_deduplication; - size_t managed_to_native_code_bytes; size_t native_to_managed_code_bytes; size_t class_initializer_code_bytes; size_t large_initializer_code_bytes; @@ -2169,7 +2342,6 @@ class ImageDumper { alignment_bytes(0), managed_code_bytes(0), managed_code_bytes_ignoring_deduplication(0), - managed_to_native_code_bytes(0), native_to_managed_code_bytes(0), class_initializer_code_bytes(0), large_initializer_code_bytes(0), @@ -2367,7 +2539,6 @@ class ImageDumper { os << StringPrintf("oat_file_bytes = %8zd\n" "managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n" - "managed_to_native_code_bytes = %8zd (%2.0f%% of oat file bytes)\n" "native_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n\n" "class_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n" "large_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n" @@ -2375,8 +2546,6 @@ class ImageDumper { oat_file_bytes, managed_code_bytes, PercentOfOatBytes(managed_code_bytes), - managed_to_native_code_bytes, - PercentOfOatBytes(managed_to_native_code_bytes), native_to_managed_code_bytes, PercentOfOatBytes(native_to_managed_code_bytes), class_initializer_code_bytes, diff --git a/oatdump/oatdump_test.cc b/oatdump/oatdump_test.cc index e77d03bae7..ba57d1860c 100644 --- a/oatdump/oatdump_test.cc +++ b/oatdump/oatdump_test.cc @@ -102,6 +102,7 @@ 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"); } if (mode == kModeArt) { exec_argv.push_back("--image=" + core_art_location_); diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc index 3c92b86208..690b069c8e 100644 --- a/runtime/stack_map.cc +++ b/runtime/stack_map.cc @@ -198,6 +198,7 @@ void StackMap::Dump(VariableIndentationOutputStream* vios, << "StackMap" << header_suffix << std::hex << " [native_pc=0x" << code_offset + pc_offset << "]" + << " [entry_size=0x" << encoding.stack_map_size_in_bytes << "]" << " (dex_pc=0x" << GetDexPc(stack_map_encoding) << ", native_pc_offset=0x" << pc_offset << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(stack_map_encoding) diff --git a/runtime/stack_map.h b/runtime/stack_map.h index 28c4b88fb0..cd9a3f04cf 100644 --- a/runtime/stack_map.h +++ b/runtime/stack_map.h @@ -1182,6 +1182,17 @@ class CodeInfo { } } + size_t GetDexRegisterMapsSize(const CodeInfoEncoding& encoding, + 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)); + total += map.Size(); + } + return total; + } + // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`. DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth, InlineInfo inline_info, |