summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/GdbIndex.cpp63
-rw-r--r--lld/ELF/GdbIndex.h8
-rw-r--r--lld/ELF/SyntheticSections.cpp1
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.
OpenPOWER on IntegriCloud