@@ -2047,7 +2047,9 @@ class ExistentialCacheEntry {
2047
2047
FullMetadata<ExistentialTypeMetadata> Data;
2048
2048
2049
2049
struct Key {
2050
- size_t NumProtocols;
2050
+ const Metadata *SuperclassConstraint;
2051
+ ProtocolClassConstraint ClassConstraint : 1 ;
2052
+ size_t NumProtocols : 31 ;
2051
2053
const ProtocolDescriptor * const *Protocols;
2052
2054
};
2053
2055
@@ -2058,6 +2060,14 @@ class ExistentialCacheEntry {
2058
2060
}
2059
2061
2060
2062
int compareWithKey (Key key) const {
2063
+ if (auto result = compareIntegers (key.ClassConstraint ,
2064
+ Data.Flags .getClassConstraint ()))
2065
+ return result;
2066
+
2067
+ if (auto result = comparePointers (key.SuperclassConstraint ,
2068
+ Data.getSuperclassConstraint ()))
2069
+ return result;
2070
+
2061
2071
if (auto result = compareIntegers (key.NumProtocols ,
2062
2072
Data.Protocols .NumProtocols ))
2063
2073
return result;
@@ -2195,7 +2205,9 @@ ClassExistentialValueWitnessTables;
2195
2205
// / Instantiate a value witness table for a class-constrained existential
2196
2206
// / container with the given number of witness table pointers.
2197
2207
static const ExtraInhabitantsValueWitnessTable *
2198
- getClassExistentialValueWitnesses (unsigned numWitnessTables) {
2208
+ getClassExistentialValueWitnesses (const Metadata *superclass,
2209
+ unsigned numWitnessTables) {
2210
+ // FIXME: If the superclass is not @objc, use native reference counting.
2199
2211
if (numWitnessTables == 0 ) {
2200
2212
#if SWIFT_OBJC_INTEROP
2201
2213
return &VALUE_WITNESS_SYM (BO);
@@ -2245,6 +2257,7 @@ ClassExistentialValueWitnessTableCacheEntry(unsigned numWitnessTables) {
2245
2257
// / shared specialized table for common cases.
2246
2258
static const ValueWitnessTable *
2247
2259
getExistentialValueWitnesses (ProtocolClassConstraint classConstraint,
2260
+ const Metadata *superclassConstraint,
2248
2261
unsigned numWitnessTables,
2249
2262
SpecialProtocol special) {
2250
2263
// Use special representation for special protocols.
@@ -2266,8 +2279,10 @@ getExistentialValueWitnesses(ProtocolClassConstraint classConstraint,
2266
2279
2267
2280
switch (classConstraint) {
2268
2281
case ProtocolClassConstraint::Class:
2269
- return getClassExistentialValueWitnesses (numWitnessTables);
2282
+ return getClassExistentialValueWitnesses (superclassConstraint,
2283
+ numWitnessTables);
2270
2284
case ProtocolClassConstraint::Any:
2285
+ assert (superclassConstraint == nullptr );
2271
2286
return getOpaqueExistentialValueWitnesses (numWitnessTables);
2272
2287
}
2273
2288
@@ -2472,44 +2487,66 @@ ExistentialTypeMetadata::getWitnessTable(const OpaqueValue *container,
2472
2487
// / \brief Fetch a uniqued metadata for an existential type. The array
2473
2488
// / referenced by \c protocols will be sorted in-place.
2474
2489
const ExistentialTypeMetadata *
2475
- swift::swift_getExistentialTypeMetadata (size_t numProtocols,
2490
+ swift::swift_getExistentialTypeMetadata (ProtocolClassConstraint classConstraint,
2491
+ const Metadata *superclassConstraint,
2492
+ size_t numProtocols,
2476
2493
const ProtocolDescriptor **protocols)
2477
2494
SWIFT_CC (RegisterPreservingCC_IMPL) {
2478
2495
2479
2496
// Sort the protocol set.
2480
2497
std::sort (protocols, protocols + numProtocols);
2481
2498
2482
- ExistentialCacheEntry::Key key = { numProtocols, protocols };
2499
+ ExistentialCacheEntry::Key key = {
2500
+ superclassConstraint, classConstraint, numProtocols, protocols
2501
+ };
2483
2502
return &ExistentialTypes.getOrInsert (key).first ->Data ;
2484
2503
}
2485
2504
2486
2505
ExistentialCacheEntry::ExistentialCacheEntry (Key key) {
2487
2506
// Calculate the class constraint and number of witness tables for the
2488
2507
// protocol set.
2489
2508
unsigned numWitnessTables = 0 ;
2490
- ProtocolClassConstraint classConstraint = ProtocolClassConstraint::Any;
2491
2509
for (auto p : make_range (key.Protocols , key.Protocols + key.NumProtocols )) {
2492
- if (p->Flags .needsWitnessTable ()) {
2510
+ if (p->Flags .needsWitnessTable ())
2493
2511
++numWitnessTables;
2494
- }
2495
- if (p->Flags .getClassConstraint () == ProtocolClassConstraint::Class)
2512
+ }
2513
+
2514
+ #ifndef NDEBUG
2515
+ // Verify the class constraint.
2516
+ {
2517
+ auto classConstraint = ProtocolClassConstraint::Any;
2518
+
2519
+ if (key.SuperclassConstraint )
2496
2520
classConstraint = ProtocolClassConstraint::Class;
2521
+ else {
2522
+ for (auto p : make_range (key.Protocols , key.Protocols + key.NumProtocols )) {
2523
+ if (p->Flags .getClassConstraint () == ProtocolClassConstraint::Class)
2524
+ classConstraint = ProtocolClassConstraint::Class;
2525
+ }
2526
+ }
2527
+
2528
+ assert (classConstraint == key.ClassConstraint );
2497
2529
}
2530
+ #endif
2498
2531
2499
2532
// Get the special protocol kind for an uncomposed protocol existential.
2500
2533
// Protocol compositions are currently never special.
2501
2534
auto special = SpecialProtocol::None;
2502
2535
if (key.NumProtocols == 1 )
2503
2536
special = key.Protocols [0 ]->Flags .getSpecialProtocol ();
2504
-
2537
+
2505
2538
Data.setKind (MetadataKind::Existential);
2506
- Data.ValueWitnesses = getExistentialValueWitnesses (classConstraint,
2539
+ Data.ValueWitnesses = getExistentialValueWitnesses (key.ClassConstraint ,
2540
+ key.SuperclassConstraint ,
2507
2541
numWitnessTables,
2508
2542
special);
2509
2543
Data.Flags = ExistentialTypeFlags ()
2510
2544
.withNumWitnessTables (numWitnessTables)
2511
- .withClassConstraint (classConstraint )
2545
+ .withClassConstraint (key. ClassConstraint )
2512
2546
.withSpecialProtocol (special);
2547
+ // FIXME
2548
+ // Data.Superclass = key.superclassConstraint;
2549
+ assert (!key.SuperclassConstraint );
2513
2550
Data.Protocols .NumProtocols = key.NumProtocols ;
2514
2551
for (size_t i = 0 ; i < key.NumProtocols ; ++i)
2515
2552
Data.Protocols [i] = key.Protocols [i];
0 commit comments