Skip to content

Commit 4fa5182

Browse files
authored
Merge pull request swiftlang#4428 from rjmccall/structural-type-metadata-caches
Metadata cache optimizations
2 parents 97ba30a + b7bd752 commit 4fa5182

File tree

4 files changed

+547
-424
lines changed

4 files changed

+547
-424
lines changed

include/swift/Runtime/Concurrent.h

+37-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <stdio.h>
2020
#endif
2121

22+
namespace swift {
23+
2224
/// This is a node in a concurrent linked list.
2325
template <class ElemTy> struct ConcurrentListNode {
2426
ConcurrentListNode(ElemTy Elem) : Payload(Elem), Next(nullptr) {}
@@ -123,6 +125,29 @@ template <class ElemTy> struct ConcurrentList {
123125
std::atomic<ConcurrentListNode<ElemTy> *> First;
124126
};
125127

128+
template <class T, bool Delete> class AtomicMaybeOwningPointer;
129+
130+
template <class T>
131+
class AtomicMaybeOwningPointer<T, false> {
132+
public:
133+
std::atomic<T*> Value;
134+
constexpr AtomicMaybeOwningPointer(T *value) : Value(value) {}
135+
};
136+
137+
template <class T>
138+
class AtomicMaybeOwningPointer<T, true> {
139+
public:
140+
std::atomic<T*> Value;
141+
constexpr AtomicMaybeOwningPointer(T *value) : Value(value) {}
142+
143+
~AtomicMaybeOwningPointer() {
144+
// This can use relaxed memory order because the client has to ensure
145+
// that all accesses are safely completed and their effects fully
146+
// visible before destruction occurs anyway.
147+
::delete Value.load(std::memory_order_relaxed);
148+
}
149+
};
150+
126151
/// A concurrent map that is implemented using a binary tree. It supports
127152
/// concurrent insertions but does not support removals or rebalancing of
128153
/// the tree.
@@ -140,7 +165,8 @@ template <class ElemTy> struct ConcurrentList {
140165
/// /// where KeyTy is the type of the first argument to getOrInsert and
141166
/// /// ArgTys is the type of the remaining arguments.
142167
/// static size_t getExtraAllocationSize(KeyTy key, ArgTys...)
143-
template <class EntryTy> class ConcurrentMap {
168+
template <class EntryTy, bool ProvideDestructor = true>
169+
class ConcurrentMap {
144170
struct Node {
145171
std::atomic<Node*> Left;
146172
std::atomic<Node*> Right;
@@ -182,7 +208,7 @@ template <class EntryTy> class ConcurrentMap {
182208
};
183209

184210
/// The root of the tree.
185-
std::atomic<Node*> Root;
211+
AtomicMaybeOwningPointer<Node, ProvideDestructor> Root;
186212

187213
/// This member stores the address of the last node that was found by the
188214
/// search procedure. We cache the last search to accelerate code that
@@ -195,13 +221,14 @@ template <class EntryTy> class ConcurrentMap {
195221
ConcurrentMap(const ConcurrentMap &) = delete;
196222
ConcurrentMap &operator=(const ConcurrentMap &) = delete;
197223

198-
~ConcurrentMap() {
199-
::delete Root.load(std::memory_order_relaxed);
200-
}
224+
// ConcurrentMap<T, false> must have a trivial destructor.
225+
~ConcurrentMap() = default;
226+
227+
public:
201228

202229
#ifndef NDEBUG
203230
void dump() const {
204-
auto R = Root.load(std::memory_order_acquire);
231+
auto R = Root.Value.load(std::memory_order_acquire);
205232
printf("digraph g {\n"
206233
"graph [ rankdir = \"TB\"];\n"
207234
"node [ fontsize = \"16\" ];\n"
@@ -225,7 +252,7 @@ template <class EntryTy> class ConcurrentMap {
225252
}
226253

227254
// Search the tree, starting from the root.
228-
Node *node = Root.load(std::memory_order_acquire);
255+
Node *node = Root.Value.load(std::memory_order_acquire);
229256
while (node) {
230257
int comparisonResult = node->Payload.compareWithKey(key);
231258
if (comparisonResult == 0) {
@@ -258,7 +285,7 @@ template <class EntryTy> class ConcurrentMap {
258285
Node *newNode = nullptr;
259286

260287
// Start from the root.
261-
auto edge = &Root;
288+
auto edge = &Root.Value;
262289

263290
while (true) {
264291
// Load the edge.
@@ -313,4 +340,6 @@ template <class EntryTy> class ConcurrentMap {
313340
}
314341
};
315342

343+
} // end namespace swift
344+
316345
#endif // SWIFT_RUNTIME_CONCURRENTUTILS_H

stdlib/public/runtime/Demangle.cpp

+27-2
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,35 @@ Demangle::NodePointer swift::_swift_buildDemanglingForMetadata(const Metadata *t
209209
}
210210
case MetadataKind::Tuple: {
211211
auto tuple = static_cast<const TupleTypeMetadata *>(type);
212+
const char *labels = tuple->Labels;
212213
auto tupleNode = NodeFactory::create(Node::Kind::NonVariadicTuple);
213214
for (unsigned i = 0, e = tuple->NumElements; i < e; ++i) {
214-
auto elt = _swift_buildDemanglingForMetadata(tuple->getElement(i).Type);
215-
tupleNode->addChild(elt);
215+
auto elt = NodeFactory::create(Node::Kind::TupleElement);
216+
217+
// Add a label child if applicable:
218+
if (labels) {
219+
// Look for the next space in the labels string.
220+
if (const char *space = strchr(labels, ' ')) {
221+
// If there is one, and the label isn't empty, add a label child.
222+
if (labels != space) {
223+
auto eltName =
224+
NodeFactory::create(Node::Kind::TupleElementName,
225+
std::string(labels, space));
226+
elt->addChild(std::move(eltName));
227+
}
228+
229+
// Skip past the space.
230+
labels = space + 1;
231+
}
232+
}
233+
234+
// Add the element type child.
235+
auto eltType =
236+
_swift_buildDemanglingForMetadata(tuple->getElement(i).Type);
237+
elt->addChild(std::move(eltType));
238+
239+
// Add the completed element to the tuple.
240+
tupleNode->addChild(std::move(elt));
216241
}
217242
return tupleNode;
218243
}

0 commit comments

Comments
 (0)