diff options
-rw-r--r-- | lld/ELF/GdbIndex.cpp | 63 | ||||
-rw-r--r-- | lld/ELF/GdbIndex.h | 8 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.cpp | 1 |
3 files changed, 27 insertions, 45 deletions
diff --git a/lld/ELF/GdbIndex.cpp b/lld/ELF/GdbIndex.cpp index 4a79aee8981..592a9acada5 100644 --- a/lld/ELF/GdbIndex.cpp +++ b/lld/ELF/GdbIndex.cpp @@ -59,6 +59,7 @@ //===----------------------------------------------------------------------===// #include "GdbIndex.h" +#include "Memory.h" #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" #include "llvm/Object/ELFObjectFile.h" @@ -106,48 +107,32 @@ GdbIndexBuilder<ELFT>::readPubNamesAndTypes() { } std::pair<bool, GdbSymbol *> GdbHashTab::add(uint32_t Hash, size_t Offset) { - if (Size * 4 / 3 >= Table.size()) - expand(); - - GdbSymbol **Slot = findSlot(Hash, Offset); - bool New = false; - if (*Slot == nullptr) { - ++Size; - *Slot = new (Alloc) GdbSymbol(Hash, Offset); - New = true; - } - return {New, *Slot}; + GdbSymbol *&Sym = Map[{Hash, Offset}]; + if (Sym) + return {false, Sym}; + ++Size; + Sym = make<GdbSymbol>(Hash, Offset); + return {true, Sym}; } -void GdbHashTab::expand() { - if (Table.empty()) { - Table.resize(InitialSize); - return; - } - std::vector<GdbSymbol *> NewTable(Table.size() * 2); - NewTable.swap(Table); - - for (GdbSymbol *Sym : NewTable) { - if (!Sym) - continue; - GdbSymbol **Slot = findSlot(Sym->NameHash, Sym->NameOffset); - *Slot = Sym; - } -} +void GdbHashTab::finalizeContents() { + Table.resize(std::max(1024UL, NextPowerOf2(Map.size() * 4 / 3))); + + for (auto &P : Map) { + GdbSymbol *Sym = P.second; + + uint32_t I = Sym->NameHash & (Table.size() - 1); + uint32_t Step = ((Sym->NameHash * 17) & (Table.size() - 1)) | 1; + + for (;;) { + if (Table[I]) { + I = (I + Step) & (Table.size() - 1); + continue; + } -// Methods finds a slot for symbol with given hash. The step size used to find -// the next candidate slot when handling a hash collision is specified in -// .gdb_index section format. The hash value for a table entry is computed by -// applying an iterative hash function to the symbol's name. -GdbSymbol **GdbHashTab::findSlot(uint32_t Hash, size_t Offset) { - uint32_t Index = Hash & (Table.size() - 1); - uint32_t Step = ((Hash * 17) & (Table.size() - 1)) | 1; - - for (;;) { - GdbSymbol *S = Table[Index]; - if (!S || ((S->NameOffset == Offset) && (S->NameHash == Hash))) - return &Table[Index]; - Index = (Index + Step) & (Table.size() - 1); + Table[I] = Sym; + break; + } } } diff --git a/lld/ELF/GdbIndex.h b/lld/ELF/GdbIndex.h index e0b3fd167dc..eec573099ef 100644 --- a/lld/ELF/GdbIndex.h +++ b/lld/ELF/GdbIndex.h @@ -75,22 +75,18 @@ class GdbHashTab final { public: std::pair<bool, GdbSymbol *> add(uint32_t Hash, size_t Offset); + void finalizeContents(); size_t getCapacity() { return Table.size(); } GdbSymbol *getSymbol(size_t I) { return Table[I]; } private: - void expand(); - GdbSymbol **findSlot(uint32_t Hash, size_t Offset); - llvm::BumpPtrAllocator Alloc; + llvm::DenseMap<std::pair<uint32_t, size_t>, GdbSymbol *> Map; std::vector<GdbSymbol *> Table; // Size keeps the amount of filled entries in Table. size_t Size = 0; - - // Initial size must be a power of 2. - static const int32_t InitialSize = 1024; }; } // namespace elf diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 97d6a7ce982..e9516759458 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1749,6 +1749,7 @@ template <class ELFT> void GdbIndexSection<ELFT>::finalizeContents() { Finalized = true; parseDebugSections(); + SymbolTable.finalizeContents(); // GdbIndex header consist from version fields // and 5 more fields with different kinds of offsets. |