Skip to content

Commit 8404c73

Browse files
committed
Demangler: support stack allocation for the Demangler's allocator
The demangler can be initialized with a preallocated memory on the stack. Only in case of an overflow, the bump pointer allocator mallocs new memory. Also, support that a new instance of a demangler can "borrow" the free memory from an existing demangler. This is useful because in the runtime the demangler is invoked recursively. With this feature, all the nested demanglers can share a single stack allocated space.
1 parent b04ebcf commit 8404c73

File tree

5 files changed

+87
-19
lines changed

5 files changed

+87
-19
lines changed

Diff for: include/swift/Demangling/Demangle.h

+12-7
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,10 @@ void mangleIdentifier(const char *data, size_t length,
474474

475475
/// Remangle a demangled parse tree.
476476
///
477-
/// This should always round-trip perfectly with demangleSymbolAsNode.
478-
std::string mangleNode(NodePointer root);
477+
/// If \p BorrowFrom is specified, the initial bump pointer memory is
478+
/// borrowed from the free memory of BorrowFrom.
479+
std::string mangleNode(NodePointer root,
480+
NodeFactory *BorrowFrom = nullptr);
479481

480482
using SymbolicResolver =
481483
llvm::function_ref<Demangle::NodePointer (SymbolicReferenceKind,
@@ -484,14 +486,17 @@ using SymbolicResolver =
484486
/// Remangle a demangled parse tree, using a callback to resolve
485487
/// symbolic references.
486488
///
487-
/// This should always round-trip perfectly with demangleSymbolAsNode.
488-
std::string mangleNode(NodePointer root, SymbolicResolver resolver);
489+
/// If \p BorrowFrom is specified, the initial bump pointer memory is
490+
/// borrowed from the free memory of BorrowFrom.
491+
std::string mangleNode(NodePointer root, SymbolicResolver resolver,
492+
NodeFactory *BorrowFrom = nullptr);
489493

490494
/// Remangle in the old mangling scheme.
491495
///
492-
/// This is only used for objc-runtime names and should be removed as soon as
493-
/// we switch to the new mangling for those names as well.
494-
std::string mangleNodeOld(NodePointer root);
496+
/// This is only used for objc-runtime names.
497+
/// If \p BorrowFrom is specified, the initial bump pointer memory is
498+
/// borrowed from the free memory of BorrowFrom.
499+
std::string mangleNodeOld(NodePointer root, NodeFactory *BorrowFrom = nullptr);
495500

496501
/// Transform the node structure to a string.
497502
///

Diff for: include/swift/Demangling/Demangler.h

+56-3
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,13 @@ class NodeFactory {
6969
}
7070

7171
static void freeSlabs(Slab *slab);
72-
72+
73+
/// If not null, the NodeFactory from which this factory borrowed free memory.
74+
NodeFactory *BorrowedFrom = nullptr;
75+
76+
/// True if some other NodeFactory borrowed free memory from this factory.
77+
bool isBorrowed = false;
78+
7379
#ifdef NODE_FACTORY_DEBUGGING
7480
size_t allocatedMemory = 0;
7581
static int nestingLevel;
@@ -84,20 +90,54 @@ class NodeFactory {
8490
nestingLevel++;
8591
#endif
8692
}
87-
93+
94+
/// Provide pre-allocated memory, e.g. memory on the stack.
95+
///
96+
/// Only if this memory overflows, the factory begins to malloc.
97+
void providePreallocatedMemory(char *Memory, size_t Size) {
98+
#ifdef NODE_FACTORY_DEBUGGING
99+
std::cerr << indent() << "++ provide preallocated memory, size = "
100+
<< Size << '\n';
101+
#endif
102+
assert(!CurPtr && !End && !CurrentSlab);
103+
CurPtr = Memory;
104+
End = CurPtr + Size;
105+
}
106+
107+
/// Borrow free memory from another factory \p BorrowFrom.
108+
///
109+
/// While this factory is alive, no allocations can be done in the
110+
/// \p BorrowFrom factory.
111+
void providePreallocatedMemory(NodeFactory &BorrowFrom) {
112+
assert(!CurPtr && !End && !CurrentSlab);
113+
assert(!BorrowFrom.isBorrowed && !BorrowedFrom);
114+
BorrowFrom.isBorrowed = true;
115+
BorrowedFrom = &BorrowFrom;
116+
CurPtr = BorrowFrom.CurPtr;
117+
End = BorrowFrom.End;
118+
#ifdef NODE_FACTORY_DEBUGGING
119+
std::cerr << indent() << "++ borrow memory, size = "
120+
<< (End - CurPtr) << '\n';
121+
#endif
122+
}
123+
88124
virtual ~NodeFactory() {
89125
freeSlabs(CurrentSlab);
90126
#ifdef NODE_FACTORY_DEBUGGING
91127
nestingLevel--;
92128
std::cerr << indent() << "## Delete NodeFactory: allocated memory = "
93129
<< allocatedMemory << '\n';
94130
#endif
131+
if (BorrowedFrom) {
132+
BorrowedFrom->isBorrowed = false;
133+
}
95134
}
96135

97136
virtual void clear();
98137

99138
/// Allocates an object of type T or an array of objects of type T.
100139
template<typename T> T *Allocate(size_t NumObjects = 1) {
140+
assert(!isBorrowed);
101141
size_t ObjectSize = NumObjects * sizeof(T);
102142
CurPtr = align(CurPtr, alignof(T));
103143
#ifdef NODE_FACTORY_DEBUGGING
@@ -144,6 +184,7 @@ class NodeFactory {
144184
/// enlarged by a bigger value.
145185
template<typename T> void Reallocate(T *&Objects, uint32_t &Capacity,
146186
size_t MinGrowth) {
187+
assert(!isBorrowed);
147188
size_t OldAllocSize = Capacity * sizeof(T);
148189
size_t AdditionalAlloc = MinGrowth * sizeof(T);
149190

@@ -547,7 +588,19 @@ class Demangler : public NodeFactory {
547588
/// Demangler or with a call of clear().
548589
NodePointer demangleType(StringRef MangledName);
549590
};
550-
591+
592+
/// A demangler which uses stack space for its initial memory.
593+
///
594+
/// The \p Size paramter specifies the size of the stack space.
595+
template <size_t Size> class StackAllocatedDemangler : public Demangler {
596+
char StackSpace[Size];
597+
598+
public:
599+
StackAllocatedDemangler() {
600+
providePreallocatedMemory(StackSpace, Size);
601+
}
602+
};
603+
551604
NodePointer demangleOldSymbolAsNode(StringRef MangledName,
552605
NodeFactory &Factory);
553606
} // end namespace Demangle

Diff for: lib/Demangling/Demangler.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ void NodeFactory::freeSlabs(Slab *slab) {
408408
}
409409

410410
void NodeFactory::clear() {
411+
assert(!isBorrowed);
411412
if (CurrentSlab) {
412413
#ifdef NODE_FACTORY_DEBUGGING
413414
std::cerr << indent() << "## clear: allocated memory = " << allocatedMemory << "\n";

Diff for: lib/Demangling/OldRemangler.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,11 @@ namespace {
214214
std::unordered_map<SubstitutionEntry, unsigned,
215215
SubstitutionEntry::Hasher> Substitutions;
216216
public:
217-
Remangler(DemanglerPrinter &out) : Out(out) {}
217+
Remangler(DemanglerPrinter &out,
218+
NodeFactory *BorrowFrom) : Out(out) {
219+
if (BorrowFrom)
220+
Factory.providePreallocatedMemory(*BorrowFrom);
221+
}
218222

219223
class EntityContext {
220224
bool AsContext = false;
@@ -2282,10 +2286,10 @@ void Remangler::mangleSugaredParen(Node *node) {
22822286
}
22832287

22842288
/// The top-level interface to the remangler.
2285-
std::string Demangle::mangleNodeOld(NodePointer node) {
2289+
std::string Demangle::mangleNodeOld(NodePointer node, NodeFactory *BorrowFrom) {
22862290
if (!node) return "";
22872291

22882292
DemanglerPrinter printer;
2289-
Remangler(printer).mangle(node);
2293+
Remangler(printer, BorrowFrom).mangle(node);
22902294
return std::move(printer).str();
22912295
}

Diff for: lib/Demangling/Remangler.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,12 @@ class Remangler {
311311
#include "swift/Demangling/DemangleNodes.def"
312312

313313
public:
314-
Remangler(DemanglerPrinter &Buffer,
315-
SymbolicResolver Resolver) : Buffer(Buffer), Resolver(Resolver) {}
314+
Remangler(DemanglerPrinter &Buffer, SymbolicResolver Resolver,
315+
NodeFactory *BorrowFrom)
316+
: Buffer(Buffer), Resolver(Resolver) {
317+
if (BorrowFrom)
318+
Factory.providePreallocatedMemory(*BorrowFrom);
319+
}
316320

317321
void mangle(Node *node) {
318322
switch (node->getKind()) {
@@ -2334,19 +2338,20 @@ void Remangler::mangleSugaredParen(Node *node) {
23342338
} // anonymous namespace
23352339

23362340
/// The top-level interface to the remangler.
2337-
std::string Demangle::mangleNode(NodePointer node) {
2341+
std::string Demangle::mangleNode(NodePointer node, NodeFactory *BorrowFrom) {
23382342
return mangleNode(node, [](SymbolicReferenceKind, const void *) -> NodePointer {
23392343
unreachable("should not try to mangle a symbolic reference; "
23402344
"resolve it to a non-symbolic demangling tree instead");
2341-
});
2345+
}, BorrowFrom);
23422346
}
23432347

23442348
std::string
2345-
Demangle::mangleNode(NodePointer node, SymbolicResolver resolver) {
2349+
Demangle::mangleNode(NodePointer node, SymbolicResolver resolver,
2350+
NodeFactory *BorrowFrom) {
23462351
if (!node) return "";
23472352

23482353
DemanglerPrinter printer;
2349-
Remangler(printer, resolver).mangle(node);
2354+
Remangler(printer, resolver, BorrowFrom).mangle(node);
23502355

23512356
return std::move(printer).str();
23522357
}

0 commit comments

Comments
 (0)