[AccelTable] Pre-compute entry pool offsets for DW_IDX_parent. NFC (#188915)
After PR #150846 changed MCFragment to use fixed 16KB blocks, large
sections like .debug_names produce thousands of fragments. The
DW_IDX_parent emission called emitLabelDifference(ParentSymbol,
EntryPool, 4) per entry, which fell through to
attemptToFoldSymbolOffsetDifference's O(n) fragment walk when symbols
were in different fragments. This caused O(entries * fragments)
quadratic behavior, regressing dsymutil on large binaries like clang.
Fix by pre-computing byte offsets from EntryPool for each entry in a
first pass, then emitting emitInt32(offset) directly for DW_IDX_parent
instead of symbol differences. This also eliminates per-entry MCSymbol
allocation that was only needed for parent references.
Fix #188376
(cherry picked from commit 0f63c0a3a5)
This commit is contained in:
parent
561944ebcb
commit
cc87fcfeef
1 changed files with 50 additions and 23 deletions
|
|
@ -21,6 +21,7 @@
|
|||
#include "llvm/CodeGen/DIE.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetLoweringObjectFile.h"
|
||||
#include <cstddef>
|
||||
|
|
@ -225,8 +226,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
|
|||
void emitAbbrevs() const;
|
||||
void emitEntry(
|
||||
const DWARF5AccelTableData &Entry,
|
||||
const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
|
||||
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols);
|
||||
const DenseMap<OffsetAndUnitID, uint64_t> &DIEOffsetToAccelEntryOffset);
|
||||
uint64_t getEntrySize(const DWARF5AccelTableData &Entry) const;
|
||||
void emitData();
|
||||
|
||||
public:
|
||||
|
|
@ -523,8 +524,7 @@ void Dwarf5AccelTableWriter::emitAbbrevs() const {
|
|||
|
||||
void Dwarf5AccelTableWriter::emitEntry(
|
||||
const DWARF5AccelTableData &Entry,
|
||||
const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
|
||||
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols) {
|
||||
const DenseMap<OffsetAndUnitID, uint64_t> &DIEOffsetToAccelEntryOffset) {
|
||||
unsigned AbbrevIndex = Entry.getAbbrevNumber() - 1;
|
||||
assert(AbbrevIndex < AbbreviationsVector.size() &&
|
||||
"Entry abbrev index is outside of abbreviations vector range.");
|
||||
|
|
@ -533,16 +533,6 @@ void Dwarf5AccelTableWriter::emitEntry(
|
|||
getIndexForEntry(Entry);
|
||||
std::optional<OffsetAndUnitID> MaybeParentOffset =
|
||||
Entry.getParentDieOffsetAndUnitID();
|
||||
auto EntrySymbolIt =
|
||||
DIEOffsetToAccelEntryLabel.find(Entry.getDieOffsetAndUnitID());
|
||||
assert(EntrySymbolIt != DIEOffsetToAccelEntryLabel.end());
|
||||
MCSymbol *EntrySymbol = EntrySymbolIt->getSecond();
|
||||
|
||||
// Emit the label for this Entry, so that IDX_parents may refer to it.
|
||||
// Note: a DIE may have multiple accelerator Entries; this check avoids
|
||||
// creating/emitting multiple labels for the same DIE.
|
||||
if (EmittedAccelEntrySymbols.insert(EntrySymbol).second)
|
||||
Asm->OutStreamer->emitLabel(EntrySymbol);
|
||||
|
||||
Asm->emitULEB128(Entry.getAbbrevNumber(), "Abbreviation code");
|
||||
|
||||
|
|
@ -563,9 +553,9 @@ void Dwarf5AccelTableWriter::emitEntry(
|
|||
case dwarf::DW_IDX_parent: {
|
||||
if (AttrEnc.Form == dwarf::Form::DW_FORM_flag_present)
|
||||
break;
|
||||
auto ParentSymbolIt = DIEOffsetToAccelEntryLabel.find(*MaybeParentOffset);
|
||||
assert(ParentSymbolIt != DIEOffsetToAccelEntryLabel.end());
|
||||
Asm->emitLabelDifference(ParentSymbolIt->getSecond(), EntryPool, 4);
|
||||
auto It = DIEOffsetToAccelEntryOffset.find(*MaybeParentOffset);
|
||||
assert(It != DIEOffsetToAccelEntryOffset.end());
|
||||
Asm->emitInt32(It->second);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -574,20 +564,57 @@ void Dwarf5AccelTableWriter::emitEntry(
|
|||
}
|
||||
}
|
||||
|
||||
void Dwarf5AccelTableWriter::emitData() {
|
||||
DenseMap<OffsetAndUnitID, MCSymbol *> DIEOffsetToAccelEntryLabel;
|
||||
uint64_t
|
||||
Dwarf5AccelTableWriter::getEntrySize(const DWARF5AccelTableData &Entry) const {
|
||||
unsigned AbbrevIndex = Entry.getAbbrevNumber() - 1;
|
||||
assert(AbbrevIndex < AbbreviationsVector.size());
|
||||
DebugNamesAbbrev *Abbrev = AbbreviationsVector[AbbrevIndex];
|
||||
uint64_t Size = getULEB128Size(Entry.getAbbrevNumber());
|
||||
std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
|
||||
getIndexForEntry(Entry);
|
||||
for (const auto &AttrEnc : Abbrev->getAttributes()) {
|
||||
switch (AttrEnc.Index) {
|
||||
case dwarf::DW_IDX_compile_unit:
|
||||
case dwarf::DW_IDX_type_unit:
|
||||
Size += DIEInteger(EntryRet->Index)
|
||||
.sizeOf(Asm->getDwarfFormParams(), AttrEnc.Form);
|
||||
break;
|
||||
case dwarf::DW_IDX_die_offset:
|
||||
Size += 4;
|
||||
break;
|
||||
case dwarf::DW_IDX_parent:
|
||||
if (AttrEnc.Form != dwarf::Form::DW_FORM_flag_present)
|
||||
Size += 4;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unexpected index attribute!");
|
||||
}
|
||||
}
|
||||
return Size;
|
||||
}
|
||||
|
||||
for (OffsetAndUnitID Offset : IndexedOffsets)
|
||||
DIEOffsetToAccelEntryLabel.insert({Offset, Asm->createTempSymbol("")});
|
||||
void Dwarf5AccelTableWriter::emitData() {
|
||||
// Pre-compute entry pool offsets for DW_IDX_parent references.
|
||||
DenseMap<OffsetAndUnitID, uint64_t> DIEOffsetToAccelEntryOffset;
|
||||
uint64_t Offset = 0;
|
||||
for (auto &Bucket : Contents.getBuckets()) {
|
||||
for (auto *Hash : Bucket) {
|
||||
for (const auto *Value : Hash->getValues<DWARF5AccelTableData *>()) {
|
||||
DIEOffsetToAccelEntryOffset.try_emplace(Value->getDieOffsetAndUnitID(),
|
||||
Offset);
|
||||
Offset += getEntrySize(*Value);
|
||||
}
|
||||
Offset += 1; // End of list
|
||||
}
|
||||
}
|
||||
|
||||
Asm->OutStreamer->emitLabel(EntryPool);
|
||||
DenseSet<MCSymbol *> EmittedAccelEntrySymbols;
|
||||
for (auto &Bucket : Contents.getBuckets()) {
|
||||
for (auto *Hash : Bucket) {
|
||||
// Remember to emit the label for our offset.
|
||||
Asm->OutStreamer->emitLabel(Hash->Sym);
|
||||
for (const auto *Value : Hash->getValues<DWARF5AccelTableData *>())
|
||||
emitEntry(*Value, DIEOffsetToAccelEntryLabel, EmittedAccelEntrySymbols);
|
||||
emitEntry(*Value, DIEOffsetToAccelEntryOffset);
|
||||
Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
|
||||
Asm->emitInt8(0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue