Change the order of functions in .debug_frame to save space.
Order the methods to help the compression of mini-debug-info.
This reduces the overhead of mini-debug-info from 3% to 2.5%.
Also remove oat_patches from the mini-debug-info since it is
does not make sense there.
Change-Id: I5077f664c3b01f07047b251489d2e9b05c8c9379
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index 012a71f..50f0ddb 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -16,6 +16,7 @@
#include "elf_writer_debug.h"
+#include <algorithm>
#include <unordered_set>
#include <vector>
#include <cstdio>
@@ -227,7 +228,8 @@
template<typename ElfTypes>
void WriteCFISection(ElfBuilder<ElfTypes>* builder,
const ArrayRef<const MethodDebugInfo>& method_infos,
- CFIFormat format) {
+ CFIFormat format,
+ bool write_oat_patches) {
CHECK(format == DW_DEBUG_FRAME_FORMAT || format == DW_EH_FRAME_FORMAT);
typedef typename ElfTypes::Addr Elf_Addr;
@@ -243,6 +245,24 @@
patch_locations.reserve(method_infos.size());
}
+ // The methods can be written any order.
+ // Let's therefore sort them in the lexicographical order of the opcodes.
+ // This has no effect on its own. However, if the final .debug_frame section is
+ // compressed it reduces the size since similar opcodes sequences are grouped.
+ std::vector<const MethodDebugInfo*> sorted_method_infos;
+ sorted_method_infos.reserve(method_infos.size());
+ for (size_t i = 0; i < method_infos.size(); i++) {
+ sorted_method_infos.push_back(&method_infos[i]);
+ }
+ std::sort(
+ sorted_method_infos.begin(),
+ sorted_method_infos.end(),
+ [](const MethodDebugInfo* lhs, const MethodDebugInfo* rhs) {
+ ArrayRef<const uint8_t> l = lhs->compiled_method_->GetCFIInfo();
+ ArrayRef<const uint8_t> r = rhs->compiled_method_->GetCFIInfo();
+ return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
+ });
+
// Write .eh_frame/.debug_frame section.
auto* cfi_section = (format == DW_DEBUG_FRAME_FORMAT
? builder->GetDebugFrame()
@@ -261,11 +281,11 @@
cfi_section->WriteFully(buffer.data(), buffer.size());
buffer_address += buffer.size();
buffer.clear();
- for (const MethodDebugInfo& mi : method_infos) {
- if (!mi.deduped_) { // Only one FDE per unique address.
- ArrayRef<const uint8_t> opcodes = mi.compiled_method_->GetCFIInfo();
+ for (const MethodDebugInfo* mi : sorted_method_infos) {
+ if (!mi->deduped_) { // Only one FDE per unique address.
+ ArrayRef<const uint8_t> opcodes = mi->compiled_method_->GetCFIInfo();
if (!opcodes.empty()) {
- const Elf_Addr code_address = text_address + mi.low_pc_;
+ const Elf_Addr code_address = text_address + mi->low_pc_;
if (format == DW_EH_FRAME_FORMAT) {
binary_search_table.push_back(
dchecked_integral_cast<uint32_t>(code_address));
@@ -273,7 +293,7 @@
dchecked_integral_cast<uint32_t>(buffer_address));
}
WriteFDE(is64bit, cfi_address, cie_address,
- code_address, mi.high_pc_ - mi.low_pc_,
+ code_address, mi->high_pc_ - mi->low_pc_,
opcodes, format, buffer_address, &buffer,
&patch_locations);
cfi_section->WriteFully(buffer.data(), buffer.size());
@@ -314,8 +334,10 @@
header_section->WriteFully(binary_search_table.data(), binary_search_table.size());
header_section->End();
} else {
- builder->WritePatches(".debug_frame.oat_patches",
- ArrayRef<const uintptr_t>(patch_locations));
+ if (write_oat_patches) {
+ builder->WritePatches(".debug_frame.oat_patches",
+ ArrayRef<const uintptr_t>(patch_locations));
+ }
}
}
@@ -1418,7 +1440,7 @@
// Add methods to .symtab.
WriteDebugSymbols(builder, method_infos, true /* with_signature */);
// Generate CFI (stack unwinding information).
- WriteCFISection(builder, method_infos, cfi_format);
+ WriteCFISection(builder, method_infos, cfi_format, true /* write_oat_patches */);
// Write DWARF .debug_* sections.
WriteDebugSections(builder, method_infos);
}
@@ -1484,7 +1506,7 @@
builder->SetVirtualAddress(parent_builder->GetText()->GetAddress());
builder->GetText()->WriteNoBitsSection(parent_builder->GetText()->GetSize());
WriteDebugSymbols(builder.get(), method_infos, false /* with_signature */);
- WriteCFISection(builder.get(), method_infos, DW_DEBUG_FRAME_FORMAT);
+ WriteCFISection(builder.get(), method_infos, DW_DEBUG_FRAME_FORMAT, false /* write_oat_paches */);
builder->End();
CHECK(builder->Good());
std::vector<uint8_t> compressed_buffer;