Skip to content

Commit 3a7ed92

Browse files
committed
MandatoryPerformanceOptimizations: fix adding witness methods to the function worklist
We were missing adding witness methods of not-specialized witness tables. This resulted in functions not being processed which led to crashes in IRGen. rdar://158224693
1 parent 8558931 commit 3a7ed92

File tree

2 files changed

+53
-31
lines changed

2 files changed

+53
-31
lines changed

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,8 @@ private func optimize(function: Function, _ context: FunctionPassContext, _ modu
138138
case let initExRef as InitExistentialRefInst:
139139
if context.options.enableEmbeddedSwift {
140140
for c in initExRef.conformances where c.isConcrete {
141-
specializeWitnessTable(for: c, moduleContext) {
142-
worklist.addWitnessMethods(of: $0)
143-
}
141+
specializeWitnessTable(for: c, moduleContext)
142+
worklist.addWitnessMethods(of: c, moduleContext)
144143
}
145144
}
146145

@@ -149,9 +148,9 @@ private func optimize(function: Function, _ context: FunctionPassContext, _ modu
149148
case .BuildOrdinaryTaskExecutorRef,
150149
.BuildOrdinarySerialExecutorRef,
151150
.BuildComplexEqualitySerialExecutorRef:
152-
specializeWitnessTable(for: bi.substitutionMap.conformances[0], moduleContext) {
153-
worklist.addWitnessMethods(of: $0)
154-
}
151+
let conformance = bi.substitutionMap.conformances[0]
152+
specializeWitnessTable(for: conformance, moduleContext)
153+
worklist.addWitnessMethods(of: conformance, moduleContext)
155154

156155
default:
157156
break
@@ -515,15 +514,44 @@ extension FunctionWorklist {
515514
}
516515
}
517516

518-
mutating func addWitnessMethods(of witnessTable: WitnessTable) {
517+
mutating func addWitnessMethods(of conformance: Conformance, _ context: ModulePassContext) {
518+
var visited = Set<Conformance>()
519+
addWitnessMethodsRecursively(of: conformance, visited: &visited, context)
520+
}
521+
522+
private mutating func addWitnessMethodsRecursively(of conformance: Conformance,
523+
visited: inout Set<Conformance>,
524+
_ context: ModulePassContext)
525+
{
526+
guard conformance.isConcrete,
527+
visited.insert(conformance).inserted
528+
else {
529+
return
530+
}
531+
let witnessTable: WitnessTable
532+
if let wt = context.lookupWitnessTable(for: conformance) {
533+
witnessTable = wt
534+
} else if let wt = context.lookupWitnessTable(for: conformance.rootConformance) {
535+
witnessTable = wt
536+
} else {
537+
return
538+
}
519539
for entry in witnessTable.entries {
520-
if case .method(_, let witness) = entry,
521-
let method = witness,
522-
// A new witness table can still contain a generic function if the method couldn't be specialized for
523-
// some reason and an error has been printed. Exclude generic functions to not run into an assert later.
524-
!method.isGeneric
525-
{
526-
pushIfNotVisited(method)
540+
switch entry {
541+
case .invalid, .associatedType:
542+
break
543+
case .method(_, let witness):
544+
if let method = witness,
545+
// A new witness table can still contain a generic function if the method couldn't be specialized for
546+
// some reason and an error has been printed. Exclude generic functions to not run into an assert later.
547+
!method.isGeneric
548+
{
549+
pushIfNotVisited(method)
550+
}
551+
case .baseProtocol(_, let baseConf):
552+
addWitnessMethodsRecursively(of: baseConf, visited: &visited, context)
553+
case .associatedConformance(_, let assocConf):
554+
addWitnessMethodsRecursively(of: assocConf, visited: &visited, context)
527555
}
528556
}
529557
}

SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,7 @@ private struct VTableSpecializer {
106106
}
107107

108108
/// Specializes a witness table of `conformance` for the concrete type of the conformance.
109-
func specializeWitnessTable(for conformance: Conformance,
110-
_ context: ModulePassContext,
111-
_ notifyNewWitnessTable: (WitnessTable) -> ())
112-
{
109+
func specializeWitnessTable(for conformance: Conformance, _ context: ModulePassContext) {
113110
if let existingSpecialization = context.lookupWitnessTable(for: conformance),
114111
existingSpecialization.isSpecialized
115112
{
@@ -125,7 +122,7 @@ func specializeWitnessTable(for conformance: Conformance,
125122
let baseConf = conformance.isInherited ? conformance.inheritedConformance: conformance
126123
if !baseConf.isSpecialized {
127124
var visited = Set<Conformance>()
128-
specializeDefaultMethods(for: conformance, visited: &visited, context, notifyNewWitnessTable)
125+
specializeDefaultMethods(for: conformance, visited: &visited, context)
129126
return
130127
}
131128

@@ -158,7 +155,7 @@ func specializeWitnessTable(for conformance: Conformance,
158155
let baseConf = context.getSpecializedConformance(of: witness,
159156
for: conformance.type,
160157
substitutions: conformance.specializedSubstitutions)
161-
specializeWitnessTable(for: baseConf, context, notifyNewWitnessTable)
158+
specializeWitnessTable(for: baseConf, context)
162159
return .baseProtocol(requirement: requirement, witness: baseConf)
163160
case .associatedType(let requirement, let witness):
164161
let substType = witness.subst(with: conformance.specializedSubstitutions)
@@ -169,15 +166,14 @@ func specializeWitnessTable(for conformance: Conformance,
169166
let concreteAssociateConf = conformance.getAssociatedConformance(ofAssociatedType: requirement.rawType,
170167
to: assocConf.protocol)
171168
if concreteAssociateConf.isSpecialized {
172-
specializeWitnessTable(for: concreteAssociateConf, context, notifyNewWitnessTable)
169+
specializeWitnessTable(for: concreteAssociateConf, context)
173170
}
174171
return .associatedConformance(requirement: requirement,
175172
witness: concreteAssociateConf)
176173
}
177174
}
178-
let newWT = context.createSpecializedWitnessTable(entries: newEntries,conformance: conformance,
179-
linkage: .shared, serialized: false)
180-
notifyNewWitnessTable(newWT)
175+
context.createSpecializedWitnessTable(entries: newEntries,conformance: conformance,
176+
linkage: .shared, serialized: false)
181177
}
182178

183179
/// Specializes the default methods of a non-generic witness table.
@@ -186,8 +182,7 @@ func specializeWitnessTable(for conformance: Conformance,
186182
/// specialize inherited conformances so that the concrete self type is correct, even for derived classes.
187183
private func specializeDefaultMethods(for conformance: Conformance,
188184
visited: inout Set<Conformance>,
189-
_ context: ModulePassContext,
190-
_ notifyNewWitnessTable: (WitnessTable) -> ())
185+
_ context: ModulePassContext)
191186
{
192187
// Avoid infinite recursion, which may happen if an associated conformance is the conformance itself.
193188
guard visited.insert(conformance).inserted,
@@ -224,21 +219,20 @@ private func specializeDefaultMethods(for conformance: Conformance,
224219
specialized = true
225220
return .method(requirement: requirement, witness: specializedMethod)
226221
case .baseProtocol(_, let witness):
227-
specializeDefaultMethods(for: witness, visited: &visited, context, notifyNewWitnessTable)
222+
specializeDefaultMethods(for: witness, visited: &visited, context)
228223
return origEntry
229224
case .associatedType:
230225
return origEntry
231226
case .associatedConformance(_, let assocConf):
232-
specializeDefaultMethods(for: assocConf, visited: &visited, context, notifyNewWitnessTable)
227+
specializeDefaultMethods(for: assocConf, visited: &visited, context)
233228
return origEntry
234229
}
235230
}
236231
// If the witness table does not contain any default methods, there is no need to create a
237232
// specialized witness table.
238233
if specialized {
239-
let newWT = context.createSpecializedWitnessTable(entries: newEntries,conformance: conformance,
240-
linkage: .shared, serialized: false)
241-
notifyNewWitnessTable(newWT)
234+
context.createSpecializedWitnessTable(entries: newEntries,conformance: conformance,
235+
linkage: .shared, serialized: false)
242236
}
243237
}
244238

0 commit comments

Comments
 (0)