@@ -160,8 +160,19 @@ class Remangler {
160
160
161
161
static const size_t MaxNumWords = 26 ;
162
162
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.
163
174
std::unordered_map<SubstitutionEntry, unsigned ,
164
- SubstitutionEntry::Hasher> Substitutions ;
175
+ SubstitutionEntry::Hasher> OverflowSubstitutions ;
165
176
166
177
SubstitutionMerging SubstMerging;
167
178
@@ -180,6 +191,24 @@ class Remangler {
180
191
Words.push_back (word, Factory);
181
192
}
182
193
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
+
183
212
StringRef getBufferStr () const { return Buffer.getStringRef (); }
184
213
185
214
void resetBuffer (size_t toPos) { Buffer.resetSize (toPos); }
@@ -343,11 +372,10 @@ bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
343
372
// Go ahead and initialize the substitution entry.
344
373
entry.setNode (node, treatAsIdentifier);
345
374
346
- auto it = Substitutions. find (entry);
347
- if (it == Substitutions. end () )
375
+ int Idx = findSubstitution (entry);
376
+ if (Idx < 0 )
348
377
return false ;
349
378
350
- unsigned Idx = it->second ;
351
379
if (Idx >= 26 ) {
352
380
Buffer << ' A' ;
353
381
mangleIndex (Idx - 26 );
@@ -361,17 +389,16 @@ bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
361
389
}
362
390
363
391
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 ;
371
398
}
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});
375
402
assert (result.second );
376
403
(void ) result;
377
404
}
0 commit comments