Skip to content

Commit e0eaabf

Browse files
committed
[ABI] Optimize out the witness table pattern for resilient conformances.
Resilient conformances now put all witnesses into the resilient witness table, so optimize away the witness table pattern for such cases. Teach the runtime to fill in the protocol conformance descriptor, because that’s the only bit of real information that would be in the pattern. This is a minor optimization enabled by rdar://problem/46282080. (cherry picked from commit f2dd852)
1 parent f5df5d1 commit e0eaabf

File tree

7 files changed

+44
-40
lines changed

7 files changed

+44
-40
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,9 +1918,7 @@ namespace {
19181918
Flags = Flags.withNumConditionalRequirements(numConditional);
19191919

19201920
// Relative reference to the witness table.
1921-
auto witnessTableRef =
1922-
ConstantReference(Description.pattern, ConstantReference::Direct);
1923-
B.addRelativeAddress(witnessTableRef);
1921+
B.addRelativeAddressOrNull(Description.pattern);
19241922
}
19251923

19261924
void addFlags() {
@@ -2244,19 +2242,27 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
22442242
// Produce the initializer value.
22452243
auto initializer = wtableContents.finishAndCreateFuture();
22462244

2247-
bool isDependent = isDependentConformance(conf, /*considerResilience=*/true);
2248-
auto global = cast<llvm::GlobalVariable>(
2249-
isDependent
2250-
? getAddrOfWitnessTablePattern(cast<NormalProtocolConformance>(conf),
2251-
initializer)
2252-
: getAddrOfWitnessTable(conf, initializer));
2253-
global->setConstant(isConstantWitnessTable(wt));
2254-
global->setAlignment(getWitnessTableAlignment().getValue());
2245+
llvm::GlobalVariable *global = nullptr;
2246+
unsigned tableSize;
2247+
if (!isResilientConformance(conf)) {
2248+
bool isDependent =
2249+
isDependentConformance(conf, /*considerResilience=*/false);
2250+
global = cast<llvm::GlobalVariable>(
2251+
isDependent
2252+
? getAddrOfWitnessTablePattern(cast<NormalProtocolConformance>(conf),
2253+
initializer)
2254+
: getAddrOfWitnessTable(conf, initializer));
2255+
global->setConstant(isConstantWitnessTable(wt));
2256+
global->setAlignment(getWitnessTableAlignment().getValue());
2257+
tableSize = wtableBuilder.getTableSize();
2258+
} else {
2259+
initializer.abandon();
2260+
tableSize = 0;
2261+
}
22552262

22562263
// Collect the information that will go into the protocol conformance
22572264
// descriptor.
2258-
ConformanceDescription description(conf, wt, global,
2259-
wtableBuilder.getTableSize(),
2265+
ConformanceDescription description(conf, wt, global, tableSize,
22602266
wtableBuilder.getTablePrivateSize(),
22612267
wtableBuilder.requiresSpecialization(),
22622268
isDependentConformance(

stdlib/public/runtime/Metadata.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4040,12 +4040,18 @@ WitnessTableCacheEntry::allocate(
40404040
// Advance the address point; the private storage area is accessed via
40414041
// negative offsets.
40424042
auto table = fullTable + privateSizeInWords;
4043-
auto pattern = reinterpret_cast<void * const *>(
4044-
&*conformance->getWitnessTablePattern());
4045-
4046-
// Fill in the provided part of the requirements from the pattern.
4047-
for (size_t i = 0, e = numPatternWitnesses; i < e; ++i) {
4048-
table[i] = pattern[i];
4043+
if (auto pattern =
4044+
reinterpret_cast<void * const *>(
4045+
&*conformance->getWitnessTablePattern())) {
4046+
// Fill in the provided part of the requirements from the pattern.
4047+
for (size_t i = 0, e = numPatternWitnesses; i < e; ++i) {
4048+
table[i] = pattern[i];
4049+
}
4050+
} else {
4051+
// Put the conformance descriptor in place. Instantiation will fill in the
4052+
// rest.
4053+
assert(numPatternWitnesses == 0);
4054+
table[0] = (void *)conformance;
40494055
}
40504056

40514057
// Copy any instantiation arguments that correspond to conditional

test/IRGen/newtype.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import Newtype
88

99
// REQUIRES: objc_interop
1010

11-
// Witness table for synthesized ClosedEnums : _ObjectiveCBridgeable.
12-
// CHECK: @"$sSo13SNTClosedEnumas21_ObjectiveCBridgeableSCWp" = linkonce_odr
11+
// Conformance descriptor for synthesized ClosedEnums : _ObjectiveCBridgeable.
12+
// CHECK: @"$sSo13SNTClosedEnumas21_ObjectiveCBridgeableSCMc" =
1313

1414
// CHECK-LABEL: define swiftcc %TSo8NSStringC* @"$s7newtype14getErrorDomainSo08SNTErrorD0ayF"()
1515
public func getErrorDomain() -> ErrorDomain {

test/IRGen/objc_extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ extension NSDogcow {
180180
@NSManaged var woof: Int
181181
}
182182

183-
// CHECK: @"$sSo8NSObjectC15objc_extensionsE8SomeEnum33_1F05E59585E0BB585FCA206FBFF1A92DLLOSQACWp" =
183+
// CHECK: @"$sSo8NSObjectC15objc_extensionsE8SomeEnum33_1F05E59585E0BB585FCA206FBFF1A92DLLOSQACMc" =
184184

185185
class SwiftSubGizmo : SwiftBaseGizmo {
186186

test/IRGen/protocol_conformance_records.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ extension NativeGenericType : Spoon where T: Spoon {
119119
// -- nominal type descriptor
120120
// CHECK-SAME: @"{{got.|__imp_}}$sSiMn"
121121
// -- witness table pattern
122-
// CHECK-SAME: @"$sSi18resilient_protocol22OtherResilientProtocol0B20_conformance_recordsWp"
122+
// CHECK-SAME: i32 0,
123123
// -- flags
124124
// CHECK-SAME: i32 131144,
125125
// -- module context for retroactive conformance

test/IRGen/protocol_resilience.sil

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,33 +78,24 @@ protocol InternalProtocol {
7878
func f()
7979
}
8080

81-
// Generic witness table pattern for ConformsWithRequirements : ProtocolWithRequirements
81+
// No generic witness table pattern for ConformsWithRequirements : ProtocolWithRequirements; it's all resilient
8282

83-
// CHECK: @"$s19protocol_resilience24ConformsWithRequirementsV010resilient_A008ProtocoldE0AAWp" =
83+
// CHECK-NOT: @"$s19protocol_resilience24ConformsWithRequirementsV010resilient_A008ProtocoldE0AAWp" =
8484

85-
// CHECK-SAME: internal global [1 x i8*] [
8685

87-
// -- conformance descriptor
88-
// CHECK-SAME: "$s19protocol_resilience24ConformsWithRequirementsV010resilient_A008ProtocoldE0AAMc"
86+
// No witness table pattern for conformance with resilient associated type
8987

90-
// CHECK-SAME: ]
88+
// CHECK-NOT: @"$s19protocol_resilience26ConformsWithResilientAssocVAA03HaseF0AAWp" = {{(protected )?}}internal
9189

9290

93-
// Witness table pattern for conformance with resilient associated type
94-
95-
// CHECK: @"$s19protocol_resilience26ConformsWithResilientAssocVAA03HaseF0AAWp" = {{(protected )?}}internal global [3 x i8*] [
96-
// CHECK-SAME: @"associated conformance 19protocol_resilience26ConformsWithResilientAssocVAA03HaseF0AA1TAaDP_010resilient_A005OtherE8Protocol"
97-
// CHECK-SAME: @"symbolic 19protocol_resilience23ResilientConformingTypeV"
98-
// CHECK-SAME: ]
99-
10091
// Protocol conformance descriptor for ResilientConformingType : OtherResilientProtocol
10192

10293
// CHECK: @"$s19protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAMc" =
10394

10495
// CHECK-SAME: i32 131072,
10596

10697
// -- number of witness table entries
107-
// CHECK-SAME: i16 1,
98+
// CHECK-SAME: i16 0,
10899

109100
// -- size of private area + 'requires instantiation' bit (not set)
110101
// CHECK-SAME: i16 0,
@@ -134,7 +125,7 @@ protocol InternalProtocol {
134125
// CHECK-SAME: @secondWitness
135126

136127
// -- number of witness table entries
137-
// CHECK-SAME: i16 1,
128+
// CHECK-SAME: i16 0,
138129

139130
// -- size of private area + 'requires instantiation' bit (not set)
140131
// CHECK-SAME: i16 0,

test/IRGen/protocol_resilience_descriptors.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ public struct Y { }
6161

6262
// CHECK-USAGE-LABEL: @"$s31protocol_resilience_descriptors1YV010resilient_A022OtherResilientProtocolAAMc" =
6363
// CHECK-USAGE-SAME: i32 131072,
64-
// CHECK-USAGE-SAME: i16 1,
65-
// CHECK-USAGE-SAME: i16 0
64+
// CHECK-USAGE-SAME: i16 0,
65+
// CHECK-USAGE-SAME: i16 0,
66+
// CHECK-USAGE-SAME: i32 0
6667
extension Y: OtherResilientProtocol { }
6768

6869
// CHECK-USAGE: @"$s31protocol_resilience_descriptors29ConformsWithAssocRequirementsV010resilient_A008ProtocoleF12TypeDefaultsAAMc" =

0 commit comments

Comments
 (0)