Skip to content

Commit d7fd45d

Browse files
committed
Remangler: Use a bump-pointer allocated string instead of std::string
Done by replacing DemanglerPrinter with a bump-pointer allocated CharVector buffer. This avoids malloc calls. SR-10028 rdar://problem/48575729
1 parent a60086f commit d7fd45d

File tree

7 files changed

+109
-34
lines changed

7 files changed

+109
-34
lines changed

include/swift/Demangling/Demangle.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -490,23 +490,23 @@ void mangleIdentifier(const char *data, size_t length,
490490
bool usePunycode = true);
491491

492492
/// Remangle a demangled parse tree.
493-
///
494-
/// If \p BorrowFrom is specified, the initial bump pointer memory is
495-
/// borrowed from the free memory of BorrowFrom.
496-
std::string mangleNode(NodePointer root,
497-
NodeFactory *BorrowFrom = nullptr);
493+
std::string mangleNode(NodePointer root);
498494

499495
using SymbolicResolver =
500496
llvm::function_ref<Demangle::NodePointer (SymbolicReferenceKind,
501497
const void *)>;
502498

499+
/// Remangle a demangled parse tree, using a callback to resolve
500+
/// symbolic references.
501+
std::string mangleNode(NodePointer root, SymbolicResolver resolver);
502+
503503
/// Remangle a demangled parse tree, using a callback to resolve
504504
/// symbolic references.
505505
///
506-
/// If \p BorrowFrom is specified, the initial bump pointer memory is
507-
/// borrowed from the free memory of BorrowFrom.
508-
std::string mangleNode(NodePointer root, SymbolicResolver resolver,
509-
NodeFactory *BorrowFrom = nullptr);
506+
/// The returned string is owned by \p Factory. This means \p Factory must stay
507+
/// alive as long as the returned string is used.
508+
llvm::StringRef mangleNode(NodePointer root, SymbolicResolver resolver,
509+
NodeFactory &Factory);
510510

511511
/// Remangle in the old mangling scheme.
512512
///

include/swift/Demangling/Demangler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,11 @@ template<typename T> class Vector {
303303

304304
T &back() { return (*this)[NumElems - 1]; }
305305

306+
void resetSize(size_t toPos) {
307+
assert(toPos <= NumElems);
308+
NumElems = toPos;
309+
}
310+
306311
void push_back(const T &NewElem, NodeFactory &Factory) {
307312
if (NumElems >= Capacity)
308313
Factory.Reallocate(Elems, Capacity, /*Growth*/ 1);
@@ -331,6 +336,9 @@ class CharVector : public Vector<char> {
331336
// Append an integer as readable number.
332337
void append(int Number, NodeFactory &Factory);
333338

339+
// Append an unsigned 64 bit integer as readable number.
340+
void append(unsigned long long Number, NodeFactory &Factory);
341+
334342
StringRef str() const {
335343
return StringRef(Elems, NumElems);
336344
}

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,12 @@ class TypeRefBuilder {
210210

211211
Optional<std::string>
212212
createTypeDecl(Node *node, bool &typeAlias) {
213-
return Demangle::mangleNode(node, &Dem);
213+
return Demangle::mangleNode(node);
214214
}
215215

216216
BuiltProtocolDecl
217217
createProtocolDecl(Node *node) {
218-
return std::make_pair(Demangle::mangleNode(node, &Dem), false);
218+
return std::make_pair(Demangle::mangleNode(node), false);
219219
}
220220

221221
BuiltProtocolDecl

lib/Demangling/Demangler.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,14 +465,23 @@ void CharVector::append(StringRef Rhs, NodeFactory &Factory) {
465465
}
466466

467467
void CharVector::append(int Number, NodeFactory &Factory) {
468-
const int MaxIntPrintSize = 8;
468+
const int MaxIntPrintSize = 11;
469469
if (NumElems + MaxIntPrintSize > Capacity)
470470
Factory.Reallocate(Elems, Capacity, /*Growth*/ MaxIntPrintSize);
471471
int Length = snprintf(Elems + NumElems, MaxIntPrintSize, "%d", Number);
472472
assert(Length > 0 && Length < MaxIntPrintSize);
473473
NumElems += Length;
474474
}
475475

476+
void CharVector::append(unsigned long long Number, NodeFactory &Factory) {
477+
const int MaxPrintSize = 21;
478+
if (NumElems + MaxPrintSize > Capacity)
479+
Factory.Reallocate(Elems, Capacity, /*Growth*/ MaxPrintSize);
480+
int Length = snprintf(Elems + NumElems, MaxPrintSize, "%llu", Number);
481+
assert(Length > 0 && Length < MaxPrintSize);
482+
NumElems += Length;
483+
}
484+
476485
//////////////////////////////////
477486
// Demangler member functions //
478487
//////////////////////////////////

lib/Demangling/Remangler.cpp

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,55 @@ bool SubstitutionEntry::deepEquals(Node *lhs, Node *rhs) const {
146146
return true;
147147
}
148148

149+
/// The output string of the Demangler.
150+
///
151+
/// It's allocating the string with the provided Factory.
152+
struct RemanglerBuffer {
153+
CharVector Stream;
154+
NodeFactory &Factory;
155+
156+
RemanglerBuffer(NodeFactory &Factory) : Factory(Factory) {
157+
Stream.init(Factory, 32);
158+
}
159+
160+
RemanglerBuffer &operator<<(char c) & {
161+
Stream.push_back(c, Factory);
162+
return *this;
163+
}
164+
165+
RemanglerBuffer &operator<<(llvm::StringRef Value) & {
166+
Stream.append(Value, Factory);
167+
return *this;
168+
}
169+
170+
RemanglerBuffer &operator<<(int n) & {
171+
Stream.append(n, Factory);
172+
return *this;
173+
}
174+
175+
RemanglerBuffer &operator<<(unsigned n) & {
176+
Stream.append((unsigned long long)n, Factory);
177+
return *this;
178+
}
179+
180+
RemanglerBuffer &operator<<(unsigned long n) & {
181+
Stream.append((unsigned long long)n, Factory);
182+
return *this;
183+
}
184+
185+
RemanglerBuffer &operator<<(unsigned long long n) & {
186+
Stream.append(n, Factory);
187+
return *this;
188+
}
189+
};
190+
149191
class Remangler {
150192
template <typename Mangler>
151193
friend void Mangle::mangleIdentifier(Mangler &M, StringRef ident);
152194
friend class Mangle::SubstitutionMerging;
153195

154196
const bool UsePunycode = true;
155197

156-
DemanglerPrinter &Buffer;
157-
158198
Vector<SubstitutionWord> Words;
159199
Vector<WordReplacement> SubstWordsInIdent;
160200

@@ -178,7 +218,9 @@ class Remangler {
178218

179219
// We have to cons up temporary nodes sometimes when remangling
180220
// nested generics. This factory owns them.
181-
NodeFactory Factory;
221+
NodeFactory &Factory;
222+
223+
RemanglerBuffer Buffer;
182224

183225
// A callback for resolving symbolic references.
184226
SymbolicResolver Resolver;
@@ -209,9 +251,9 @@ class Remangler {
209251
return it->second;
210252
}
211253

212-
StringRef getBufferStr() const { return Buffer.getStringRef(); }
254+
StringRef getBufferStr() const { return Buffer.Stream.str(); }
213255

214-
void resetBuffer(size_t toPos) { Buffer.resetSize(toPos); }
256+
void resetBuffer(size_t toPos) { Buffer.Stream.resetSize(toPos); }
215257

216258
template <typename Mangler>
217259
friend void mangleIdentifier(Mangler &M, StringRef ident);
@@ -348,12 +390,8 @@ class Remangler {
348390
#include "swift/Demangling/DemangleNodes.def"
349391

350392
public:
351-
Remangler(DemanglerPrinter &Buffer, SymbolicResolver Resolver,
352-
NodeFactory *BorrowFrom)
353-
: Buffer(Buffer), Resolver(Resolver) {
354-
if (BorrowFrom)
355-
Factory.providePreallocatedMemory(*BorrowFrom);
356-
}
393+
Remangler(SymbolicResolver Resolver, NodeFactory &Factory)
394+
: Factory(Factory), Buffer(Factory), Resolver(Resolver) { }
357395

358396
void mangle(Node *node) {
359397
switch (node->getKind()) {
@@ -362,6 +400,14 @@ class Remangler {
362400
}
363401
unreachable("bad demangling tree node");
364402
}
403+
404+
StringRef strRef() {
405+
return Buffer.Stream.str();
406+
}
407+
408+
std::string str() {
409+
return strRef().str();
410+
}
365411
};
366412

367413
bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
@@ -2373,22 +2419,34 @@ void Remangler::mangleSugaredParen(Node *node) {
23732419
} // anonymous namespace
23742420

23752421
/// The top-level interface to the remangler.
2376-
std::string Demangle::mangleNode(NodePointer node, NodeFactory *BorrowFrom) {
2422+
std::string Demangle::mangleNode(NodePointer node) {
23772423
return mangleNode(node, [](SymbolicReferenceKind, const void *) -> NodePointer {
23782424
unreachable("should not try to mangle a symbolic reference; "
23792425
"resolve it to a non-symbolic demangling tree instead");
2380-
}, BorrowFrom);
2426+
});
23812427
}
23822428

23832429
std::string
2384-
Demangle::mangleNode(NodePointer node, SymbolicResolver resolver,
2385-
NodeFactory *BorrowFrom) {
2430+
Demangle::mangleNode(NodePointer node, SymbolicResolver resolver) {
23862431
if (!node) return "";
23872432

2388-
DemanglerPrinter printer;
2389-
Remangler(printer, resolver, BorrowFrom).mangle(node);
2433+
NodeFactory Factory;
2434+
Remangler remangler(resolver, Factory);
2435+
remangler.mangle(node);
2436+
2437+
return remangler.str();
2438+
}
2439+
2440+
llvm::StringRef
2441+
Demangle::mangleNode(NodePointer node, SymbolicResolver resolver,
2442+
NodeFactory &Factory) {
2443+
if (!node)
2444+
return StringRef();
2445+
2446+
Remangler remangler(resolver, Factory);
2447+
remangler.mangle(node);
23902448

2391-
return std::move(printer).str();
2449+
return remangler.strRef();
23922450
}
23932451

23942452
bool Demangle::isSpecialized(Node *node) {

stdlib/public/Reflection/TypeRefBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static std::string normalizeReflectionName(Demangler &dem, StringRef reflectionN
5656

5757
// Remangle the reflection name to resolve symbolic references.
5858
if (auto node = dem.demangleType(reflectionName)) {
59-
return mangleNode(node, &dem);
59+
return mangleNode(node);
6060
}
6161

6262
// Fall back to the raw string.

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,8 @@ _findNominalTypeDescriptor(Demangle::NodePointer node,
593593
return cast<TypeContextDescriptor>(
594594
(const ContextDescriptor *)symbolicNode->getIndex());
595595

596-
auto mangledName =
597-
Demangle::mangleNode(node, ExpandResolvedSymbolicReferences(Dem), &Dem);
596+
StringRef mangledName =
597+
Demangle::mangleNode(node, ExpandResolvedSymbolicReferences(Dem), Dem);
598598

599599
// Look for an existing entry.
600600
// Find the bucket for the metadata entry.
@@ -724,7 +724,7 @@ _findProtocolDescriptor(NodePointer node,
724724
(const ContextDescriptor *)symbolicNode->getIndex());
725725

726726
mangledName =
727-
Demangle::mangleNode(node, ExpandResolvedSymbolicReferences(Dem), &Dem);
727+
Demangle::mangleNode(node, ExpandResolvedSymbolicReferences(Dem), Dem).str();
728728

729729
// Look for an existing entry.
730730
// Find the bucket for the metadata entry.

0 commit comments

Comments
 (0)