Skip to content

Commit 9050be6

Browse files
committed
Remangler: Implement the hash map for substitutions in the spirit of llvm's SmallPtrSet.
This avoids malloc calls in the common case. Only if there are more than 16 substitutions in the fixed-sized array, the overflow goes into a std::unordered_map. SR-10028 rdar://problem/48575729
1 parent de51f8c commit 9050be6

File tree

1 file changed

+41
-14
lines changed

1 file changed

+41
-14
lines changed

lib/Demangling/Remangler.cpp

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,19 @@ class Remangler {
160160

161161
static const size_t MaxNumWords = 26;
162162

163+
// An efficient hash-map implementation in the spirit of llvm's SmallPtrSet:
164+
// The first 16 substitutions are stored in an inline-allocated array to avoid
165+
// malloc calls in the common case.
166+
// Lookup is still reasonable fast because there are max 16 elements in the
167+
// array.
168+
static const size_t InlineSubstCapacity = 16;
169+
SubstitutionEntry InlineSubstitutions[InlineSubstCapacity];
170+
size_t NumInlineSubsts = 0;
171+
172+
// The "overflow" for InlineSubstitutions. Only if InlineSubstitutions is
173+
// full, new substitutions are stored in OverflowSubstitutions.
163174
std::unordered_map<SubstitutionEntry, unsigned,
164-
SubstitutionEntry::Hasher> Substitutions;
175+
SubstitutionEntry::Hasher> OverflowSubstitutions;
165176

166177
SubstitutionMerging SubstMerging;
167178

@@ -180,6 +191,24 @@ class Remangler {
180191
Words.push_back(word, Factory);
181192
}
182193

194+
// Find a substitution and return its index.
195+
// Returns -1 if no substitution is found.
196+
int findSubstitution(const SubstitutionEntry &entry) {
197+
// First search in InlineSubstitutions.
198+
SubstitutionEntry *result
199+
= std::find(InlineSubstitutions, InlineSubstitutions + NumInlineSubsts,
200+
entry);
201+
if (result != InlineSubstitutions + NumInlineSubsts)
202+
return result - InlineSubstitutions;
203+
204+
// Then search in OverflowSubstitutions.
205+
auto it = OverflowSubstitutions.find(entry);
206+
if (it == OverflowSubstitutions.end())
207+
return -1;
208+
209+
return it->second;
210+
}
211+
183212
StringRef getBufferStr() const { return Buffer.getStringRef(); }
184213

185214
void resetBuffer(size_t toPos) { Buffer.resetSize(toPos); }
@@ -343,11 +372,10 @@ bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
343372
// Go ahead and initialize the substitution entry.
344373
entry.setNode(node, treatAsIdentifier);
345374

346-
auto it = Substitutions.find(entry);
347-
if (it == Substitutions.end())
375+
int Idx = findSubstitution(entry);
376+
if (Idx < 0)
348377
return false;
349378

350-
unsigned Idx = it->second;
351379
if (Idx >= 26) {
352380
Buffer << 'A';
353381
mangleIndex(Idx - 26);
@@ -361,17 +389,16 @@ bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
361389
}
362390

363391
void Remangler::addSubstitution(const SubstitutionEntry &entry) {
364-
unsigned Idx = Substitutions.size();
365-
#if false
366-
llvm::outs() << "add subst ";
367-
if (Idx < 26) {
368-
llvm::outs() << char('A' + Idx);
369-
} else {
370-
llvm::outs() << Idx;
392+
assert(findSubstitution(entry) < 0);
393+
if (NumInlineSubsts < InlineSubstCapacity) {
394+
// There is still free space in NumInlineSubsts.
395+
assert(OverflowSubstitutions.empty());
396+
InlineSubstitutions[NumInlineSubsts++] = entry;
397+
return;
371398
}
372-
llvm::outs() << " at pos " << getBufferStr().size() << '\n';
373-
#endif
374-
auto result = Substitutions.insert({entry, Idx});
399+
// We have to add the entry to OverflowSubstitutions.
400+
unsigned Idx = OverflowSubstitutions.size() + InlineSubstCapacity;
401+
auto result = OverflowSubstitutions.insert({entry, Idx});
375402
assert(result.second);
376403
(void) result;
377404
}

0 commit comments

Comments
 (0)