Simplify and optimize the structural type metadata caches to use ConcurrentMap directly.

Previously, these were all using MetadataCache.  MetadataCache is a
more heavyweight structure which acquires a lock before building the
metadata.  This is appropriate if building the metadata is very
expensive or might have semantic side-effects which cannot be rolled
back.  It's also useful when there's a risk of re-entrance, since it
can diagnose such things instead of simply dead-locking or infinitely
recursing.  However, it's necessary for structural cases like tuple
and function types, and instead we can just use ConcurrentMap, which
does a compare-and-swap to publish the constructed metadata and
potentially destroys it if another thread successfully won the race.

This is an optimization which we could not previously attempt.

As part of this, fix tuple metadata uniquing to consider the label
string correctly.  This exposes a bug where the runtime demangling
of tuple metadata nodes doesn't preserve labels; fix this as well.
This commit is contained in:
John McCall
2016-08-19 14:48:12 -07:00
parent 99c52e89ad
commit 17d72f558b
3 changed files with 559 additions and 421 deletions

View File

@@ -209,10 +209,35 @@ Demangle::NodePointer swift::_swift_buildDemanglingForMetadata(const Metadata *t
}
case MetadataKind::Tuple: {
auto tuple = static_cast<const TupleTypeMetadata *>(type);
const char *labels = tuple->Labels;
auto tupleNode = NodeFactory::create(Node::Kind::NonVariadicTuple);
for (unsigned i = 0, e = tuple->NumElements; i < e; ++i) {
auto elt = _swift_buildDemanglingForMetadata(tuple->getElement(i).Type);
tupleNode->addChild(elt);
auto elt = NodeFactory::create(Node::Kind::TupleElement);
// Add a label child if applicable:
if (labels) {
// Look for the next space in the labels string.
if (const char *space = strchr(labels, ' ')) {
// If there is one, and the label isn't empty, add a label child.
if (labels != space) {
auto eltName =
NodeFactory::create(Node::Kind::TupleElementName,
std::string(labels, space));
elt->addChild(std::move(eltName));
}
// Skip past the space.
labels = space + 1;
}
}
// Add the element type child.
auto eltType =
_swift_buildDemanglingForMetadata(tuple->getElement(i).Type);
elt->addChild(std::move(eltType));
// Add the completed element to the tuple.
tupleNode->addChild(std::move(elt));
}
return tupleNode;
}