Skip to content

Commit ce8f783

Browse files
authored
Merge pull request #42563 from rjmccall/reunique-existential-shapes
Unique extended existential shapes using the generalized AST type
2 parents ee7446f + bd77714 commit ce8f783

21 files changed

+398
-336
lines changed

docs/ABI/Mangling.rst

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ Types
637637
type ::= protocol-list 'p' // existential type
638638
type ::= protocol-list superclass 'Xc' // existential type with superclass
639639
type ::= protocol-list 'Xl' // existential type with AnyObject
640-
type ::= protocol-list 'y' (type* '_')* type* retroactive-conformance* 'Xp' // parameterized protocol type
640+
type ::= protocol-list 'y' (type* '_')* type* retroactive-conformance* 'XP' // parameterized protocol type
641641
type ::= type-list 't' // tuple
642642
type ::= type generic-signature 'u' // generic type
643643
type ::= 'x' // generic param, depth=0, idx=0
@@ -918,21 +918,9 @@ root protocol conformance, and the suffix 'g'.
918918

919919
::
920920

921-
// No generalization signature, no type expression.
922-
extended-existential-shape ::= generic-signature 'Xg' extended-existential-value-storage
923-
924-
// Generalization signature (the second one), no type expression.
925-
extended-existential-shape ::= generic-signature generic-signature 'XG' extended-existential-value-storage
926-
927-
// No generalization signature, type expression.
928-
extended-existential-shape ::= generic-signature type 'Xh' extended-existential-value-storage
929-
930-
// Generalization signature (the second one), type expression.
931-
extended-existential-shape ::= generic-signature generic-signature type 'Xh' extended-existential-value-storage
932-
933-
extended-existential-value-storage ::= 'o' // opaque
934-
extended-existential-value-storage ::= 'c' // class
935-
extended-existential-value-storage ::= 'm' // metatype
921+
// No generalization signature.
922+
extended-existential-shape ::= type 'Xg' // no generalization signature
923+
extended-existential-shape ::= generic-signature type 'XG'
936924

937925
Identifiers
938926
~~~~~~~~~~~

include/swift/ABI/Metadata.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,6 +1855,32 @@ struct TargetExtendedExistentialTypeShape
18551855
/// Flags for the existential shape.
18561856
ExtendedExistentialTypeShapeFlags Flags;
18571857

1858+
/// The mangling of the generalized existential type, expressed
1859+
/// (if necessary) in terms of the type parameters of the
1860+
/// generalization signature.
1861+
///
1862+
/// If this shape is non-unique, this is always a flat string, not a
1863+
/// "symbolic" mangling which can contain relative references. This
1864+
/// allows uniquing to simply compare the string content.
1865+
///
1866+
/// In principle, the content of the requirement signature and type
1867+
/// expression are derivable from this type. We store them separately
1868+
/// so that code which only needs to work with the logical content of
1869+
/// the type doesn't have to break down the existential type string.
1870+
/// This both (1) allows those operations to work substantially more
1871+
/// efficiently (and without needing code to produce a requirement
1872+
/// signature from an existential type to exist in the runtime) and
1873+
/// (2) potentially allows old runtimes to support new existential
1874+
/// types without as much invasive code.
1875+
///
1876+
/// The content of this string is *not* necessarily derivable from
1877+
/// the requirement signature. This is because there may be multiple
1878+
/// existential types that have equivalent logical content but which
1879+
/// we nonetheless distinguish at compile time. Storing this also
1880+
/// allows us to far more easily produce a formal type from this
1881+
/// shape reflectively.
1882+
RelativeStringPointer ExistentialType;
1883+
18581884
/// The header describing the requirement signature of the existential.
18591885
TargetGenericContextDescriptorHeader<Runtime> ReqSigHeader;
18601886

@@ -2024,6 +2050,9 @@ struct UniqueHash {
20242050

20252051
/// A descriptor for an extended existential type descriptor which
20262052
/// needs to be uniqued at runtime.
2053+
///
2054+
/// Uniquing is performed by comparing the existential type strings
2055+
/// of the shapes.
20272056
template <typename Runtime>
20282057
struct TargetNonUniqueExtendedExistentialTypeShape {
20292058
/// A reference to memory that can be used to cache a globally-unique
@@ -2032,10 +2061,12 @@ struct TargetNonUniqueExtendedExistentialTypeShape {
20322061
std::atomic<ConstTargetMetadataPointer<Runtime,
20332062
TargetExtendedExistentialTypeShape>>> UniqueCache;
20342063

2035-
/// A hash of the mangling of the existential shape.
2036-
///
2037-
/// TODO: describe that mangling here
2038-
UniqueHash Hash;
2064+
llvm::StringRef getExistentialTypeStringForUniquing() const {
2065+
// When we have a non-unique shape, we're guaranteed that
2066+
// ExistentialType contains no symbolic references, so we can just
2067+
// recover it this way rather than having to parse it.
2068+
return LocalCopy.ExistentialType.get();
2069+
}
20392070

20402071
/// The local copy of the existential shape descriptor.
20412072
TargetExtendedExistentialTypeShape<Runtime> LocalCopy;

include/swift/Demangling/DemangleNodes.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ NODE(OpaqueReturnTypeIndexed)
336336
NODE(BackDeploymentThunk)
337337
NODE(BackDeploymentFallback)
338338
NODE(ExtendedExistentialTypeShape)
339-
NODE(ExtendedExistentialValueStorage)
340339
NODE(Uniquable)
341340

342341
#undef CONTEXT_NODE

include/swift/IRGen/Linking.h

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,6 @@ class LinkEntity {
125125
ExtendedExistentialIsUniqueMask = 0x100,
126126
ExtendedExistentialIsSharedShift = 9,
127127
ExtendedExistentialIsSharedMask = 0x200,
128-
ExtendedExistentialMetatypeDepthShift = 10,
129-
ExtendedExistentialMetatypeDepthMask =
130-
~(KindMask | ExtendedExistentialIsUniqueMask |
131-
ExtendedExistentialIsSharedMask),
132128
};
133129
#define LINKENTITY_SET_FIELD(field, value) (value << field##Shift)
134130
#define LINKENTITY_GET_FIELD(value, field) ((value & field##Mask) >> field##Shift)
@@ -1368,9 +1364,7 @@ class LinkEntity {
13681364
}
13691365

13701366
static LinkEntity forExtendedExistentialTypeShape(CanGenericSignature genSig,
1371-
CanExistentialType
1372-
existentialType,
1373-
unsigned metatypeDepth,
1367+
CanType existentialType,
13741368
bool isUnique,
13751369
bool isShared) {
13761370
LinkEntity entity;
@@ -1380,8 +1374,7 @@ class LinkEntity {
13801374
entity.Data =
13811375
LINKENTITY_SET_FIELD(Kind, unsigned(Kind::ExtendedExistentialTypeShape))
13821376
| LINKENTITY_SET_FIELD(ExtendedExistentialIsUnique, unsigned(isUnique))
1383-
| LINKENTITY_SET_FIELD(ExtendedExistentialIsShared, unsigned(isShared))
1384-
| LINKENTITY_SET_FIELD(ExtendedExistentialMetatypeDepth, metatypeDepth);
1377+
| LINKENTITY_SET_FIELD(ExtendedExistentialIsShared, unsigned(isShared));
13851378
return entity;
13861379
}
13871380

@@ -1484,9 +1477,9 @@ class LinkEntity {
14841477
reinterpret_cast<const GenericSignatureImpl*>(SecondaryPointer));
14851478
}
14861479

1487-
CanExistentialType getExtendedExistentialTypeShapeType() const {
1480+
CanType getExtendedExistentialTypeShapeType() const {
14881481
assert(getKind() == Kind::ExtendedExistentialTypeShape);
1489-
return cast<ExistentialType>(CanType(reinterpret_cast<TypeBase*>(Pointer)));
1482+
return CanType(reinterpret_cast<TypeBase*>(Pointer));
14901483
}
14911484

14921485
bool isExtendedExistentialTypeShapeUnique() const {
@@ -1499,11 +1492,6 @@ class LinkEntity {
14991492
return LINKENTITY_GET_FIELD(Data, ExtendedExistentialIsShared);
15001493
}
15011494

1502-
unsigned getExtendedExistentialTypeShapeMetatypeDepth() const {
1503-
assert(getKind() == Kind::ExtendedExistentialTypeShape);
1504-
return LINKENTITY_GET_FIELD(Data, ExtendedExistentialMetatypeDepth);
1505-
}
1506-
15071495
bool isDynamicallyReplaceable() const {
15081496
assert(getKind() == Kind::SILFunction);
15091497
return LINKENTITY_GET_FIELD(Data, IsDynamicallyReplaceableImpl);

lib/Demangling/Demangler.cpp

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3231,8 +3231,6 @@ NodePointer Demangler::demangleSpecialType() {
32313231
return popFunctionType(Node::Kind::CFunctionPointer);
32323232
case 'g':
32333233
case 'G':
3234-
case 'h':
3235-
case 'H':
32363234
return demangleExtendedExistentialShape(specialChar);
32373235
case 'z':
32383236
switch (auto cchar = nextChar()) {
@@ -3382,47 +3380,19 @@ NodePointer Demangler::demangleSpecialType() {
33823380
}
33833381

33843382
NodePointer Demangler::demangleExtendedExistentialShape(char nodeKind) {
3385-
assert(nodeKind == 'g' || nodeKind == 'G' ||
3386-
nodeKind == 'h' || nodeKind == 'H');
3383+
assert(nodeKind == 'g' || nodeKind == 'G');
33873384

3388-
NodePointer type = nullptr;
3389-
if (nodeKind == 'h' || nodeKind == 'H')
3390-
type = popNode(Node::Kind::Type);
3385+
NodePointer type = popNode(Node::Kind::Type);
33913386

33923387
NodePointer genSig = nullptr;
3393-
if (nodeKind == 'G' || nodeKind == 'H')
3388+
if (nodeKind == 'G')
33943389
genSig = popNode(Node::Kind::DependentGenericSignature);
33953390

3396-
NodePointer reqSig = popNode(Node::Kind::DependentGenericSignature);
3397-
3398-
NodePointer valueStorage = [&]() -> NodePointer {
3399-
switch (nextChar()) {
3400-
case 'o':
3401-
return createNode(Node::Kind::ExtendedExistentialValueStorage,
3402-
"opaque");
3403-
case 'c':
3404-
return createNode(Node::Kind::ExtendedExistentialValueStorage,
3405-
"class");
3406-
case 'm':
3407-
return createNode(Node::Kind::ExtendedExistentialValueStorage,
3408-
"metatype");
3409-
default:
3410-
return nullptr;
3411-
}
3412-
}();
3413-
if (!valueStorage) return nullptr;
3414-
3415-
// Make a default type expression if one wasn't given.
3416-
if (!type) {
3417-
type = createType(getDependentGenericParamType(genSig ? 1 : 0, 0));
3418-
}
3419-
34203391
if (genSig) {
34213392
return createWithChildren(Node::Kind::ExtendedExistentialTypeShape,
3422-
reqSig, genSig, type, valueStorage);
3393+
genSig, type);
34233394
} else {
3424-
return createWithChildren(Node::Kind::ExtendedExistentialTypeShape,
3425-
reqSig, type, valueStorage);
3395+
return createWithChild(Node::Kind::ExtendedExistentialTypeShape, type);
34263396
}
34273397
}
34283398

lib/Demangling/NodePrinter.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,6 @@ class NodePrinter {
595595
case Node::Kind::BackDeploymentThunk:
596596
case Node::Kind::BackDeploymentFallback:
597597
case Node::Kind::ExtendedExistentialTypeShape:
598-
case Node::Kind::ExtendedExistentialValueStorage:
599598
case Node::Kind::Uniquable:
600599
return false;
601600
}
@@ -2975,9 +2974,8 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
29752974
auto savedDisplayWhereClauses = Options.DisplayWhereClauses;
29762975
Options.DisplayWhereClauses = true;
29772976

2978-
NodePointer reqSig = Node->getChild(0);
29792977
NodePointer genSig = nullptr, type = nullptr;
2980-
if (Node->getNumChildren() == 4) {
2978+
if (Node->getNumChildren() == 2) {
29812979
genSig = Node->getChild(1);
29822980
type = Node->getChild(2);
29832981
} else {
@@ -2989,17 +2987,12 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
29892987
print(genSig, depth + 1);
29902988
Printer << " ";
29912989
}
2992-
Printer << "any";
2993-
print(reqSig, depth + 1);
2994-
Printer << " ";
2990+
Printer << "any ";
29952991
print(type, depth + 1);
29962992

29972993
Options.DisplayWhereClauses = savedDisplayWhereClauses;
29982994
return nullptr;
29992995
}
3000-
case Node::Kind::ExtendedExistentialValueStorage:
3001-
Printer << Node->getText();
3002-
return nullptr;
30032996
}
30042997

30052998
printer_unreachable("bad node kind!");

lib/Demangling/OldRemangler.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,10 +2725,6 @@ ManglingError Remangler::mangleExtendedExistentialTypeShape(Node *node,
27252725
unsigned int depth) {
27262726
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
27272727
}
2728-
ManglingError Remangler::mangleExtendedExistentialValueStorage(Node *node,
2729-
unsigned int depth) {
2730-
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
2731-
}
27322728
ManglingError
27332729
Remangler::mangleCanonicalSpecializedGenericMetaclass(Node *node,
27342730
unsigned depth) {

lib/Demangling/Remangler.cpp

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3445,65 +3445,25 @@ ManglingError Remangler::mangleUniquable(Node *node, unsigned depth) {
34453445

34463446
ManglingError Remangler::mangleExtendedExistentialTypeShape(Node *node,
34473447
unsigned depth) {
3448-
NodePointer reqSig, genSig, type, storage;
3449-
reqSig = node->getChild(0);
3450-
if (node->getNumChildren() == 3) {
3448+
NodePointer genSig, type;
3449+
if (node->getNumChildren() == 1) {
34513450
genSig = nullptr;
3452-
type = node->getChild(1);
3453-
storage = node->getChild(2);
3451+
type = node->getChild(0);
34543452
} else {
3455-
genSig = node->getChild(1);
3456-
type = node->getChild(2);
3457-
storage = node->getChild(3);
3453+
genSig = node->getChild(0);
3454+
type = node->getChild(1);
34583455
}
34593456

3460-
RETURN_IF_ERROR(mangle(reqSig, depth + 1));
34613457
if (genSig) {
34623458
RETURN_IF_ERROR(mangle(genSig, depth + 1));
34633459
}
3460+
RETURN_IF_ERROR(mangle(type, depth + 1));
34643461

3465-
// Recognize the special case of a type expression that's just the
3466-
// unique requirement type parameter.
3467-
{
3468-
if (type->getKind() != Node::Kind::Type)
3469-
return MANGLING_ERROR(ManglingError::WrongNodeType, type);
3470-
auto typeNode = type->getChild(0);
3471-
3472-
if (typeNode->getKind() == Node::Kind::DependentGenericParamType) {
3473-
auto paramDepth = typeNode->getChild(0)->getIndex();
3474-
auto index = typeNode->getChild(1)->getIndex();
3475-
if (paramDepth == (genSig ? 1 : 0) && index == 0)
3476-
type = nullptr;
3477-
}
3478-
}
3479-
if (type)
3480-
RETURN_IF_ERROR(mangle(type, depth + 1));
3481-
3482-
if (genSig && type)
3483-
Buffer << "XH";
3484-
else if (type)
3485-
Buffer << "Xh";
3486-
else if (genSig)
3462+
if (genSig)
34873463
Buffer << "XG";
34883464
else
34893465
Buffer << "Xg";
34903466

3491-
RETURN_IF_ERROR(mangle(storage, depth + 1));
3492-
3493-
return ManglingError::Success;
3494-
}
3495-
3496-
ManglingError Remangler::mangleExtendedExistentialValueStorage(Node *node,
3497-
unsigned depth) {
3498-
if (node->getText() == "opaque")
3499-
Buffer << "o";
3500-
else if (node->getText() == "class")
3501-
Buffer << "c";
3502-
else if (node->getText() == "metatype")
3503-
Buffer << "m";
3504-
else
3505-
return MANGLING_ERROR(ManglingError::UnknownEncoding, node);
3506-
35073467
return ManglingError::Success;
35083468
}
35093469

0 commit comments

Comments
 (0)