@@ -116,7 +116,7 @@ extension IncrementalCompilationState.InitialStateComputer {
116
116
/// For inputs with swiftDeps in OFM, but no readable file, puts input in graph map, but no nodes in graph:
117
117
/// caller must ensure scheduling of those
118
118
private func computeGraphAndInputsInvalidatedByExternals( )
119
- -> ( ModuleDependencyGraph , Set < TypedVirtualPath > ) ? {
119
+ -> ( ModuleDependencyGraph , TransitivelyInvalidatedInputSet ) ? {
120
120
precondition ( sourceFiles. disappeared. isEmpty,
121
121
" Would have to remove nodes from the graph if reading prior " )
122
122
if readPriorsFromModuleDependencyGraph {
@@ -128,7 +128,7 @@ extension IncrementalCompilationState.InitialStateComputer {
128
128
}
129
129
130
130
private func readPriorGraphAndCollectInputsInvalidatedByChangedOrAddedExternals(
131
- ) -> ( ModuleDependencyGraph , Set < TypedVirtualPath > ) ?
131
+ ) -> ( ModuleDependencyGraph , TransitivelyInvalidatedInputSet ) ?
132
132
{
133
133
let dependencyGraphPath = buildRecordInfo. dependencyGraphPath
134
134
let graphIfPresent : ModuleDependencyGraph ?
@@ -152,8 +152,10 @@ extension IncrementalCompilationState.InitialStateComputer {
152
152
153
153
// Any externals not already in graph must be additions which should trigger
154
154
// recompilation. Thus, `ChangedOrAdded`.
155
- let nodesInvalidatedByExternals = graph. collectNodesInvalidatedByChangedOrAddedExternals ( )
156
- let inputsInvalidatedByExternals = graph. collectInputsUsingTransitivelyInvalidated ( nodes: nodesInvalidatedByExternals)
155
+ let nodesDirectlyInvalidatedByExternals = graph. collectNodesInvalidatedByChangedOrAddedExternals ( )
156
+ // Wait till the last minute to do the transitive closure as an optimization.
157
+ let inputsInvalidatedByExternals = graph. collectInputsUsingInvalidated (
158
+ nodes: nodesDirectlyInvalidatedByExternals)
157
159
return ( graph, inputsInvalidatedByExternals)
158
160
}
159
161
@@ -165,17 +167,15 @@ extension IncrementalCompilationState.InitialStateComputer {
165
167
/// For externalDependencies, puts then in graph.fingerprintedExternalDependencies, but otherwise
166
168
/// does nothing special.
167
169
private func buildInitialGraphFromSwiftDepsAndCollectInputsInvalidatedByChangedExternals(
168
- ) -> ( ModuleDependencyGraph , Set < TypedVirtualPath > ) ?
170
+ ) -> ( ModuleDependencyGraph , TransitivelyInvalidatedInputSet ) ?
169
171
{
170
- let graph = ModuleDependencyGraph ( self )
172
+ let graph = ModuleDependencyGraph ( self , . buildingWithoutAPrior )
171
173
assert ( outputFileMap. onlySourceFilesHaveSwiftDeps ( ) )
172
174
guard graph. populateInputDependencySourceMap ( ) else {
173
175
return nil
174
176
}
175
177
176
- // Every external will be an addition to the graph, but may not cause
177
- // a recompile, so includeAddedExternals is false.
178
- var inputsInvalidatedByChangedExternals = Set < TypedVirtualPath > ( )
178
+ var inputsInvalidatedByChangedExternals = TransitivelyInvalidatedInputSet ( )
179
179
for input in sourceFiles. currentInOrder {
180
180
guard let invalidatedInputs = graph. collectInputsRequiringCompilationFromExternalsFoundByCompiling ( input: input)
181
181
else {
@@ -195,7 +195,7 @@ extension IncrementalCompilationState.InitialStateComputer {
195
195
/// listed in fingerprintExternalDependencies.
196
196
private func computeInputsAndGroups(
197
197
_ moduleDependencyGraph: ModuleDependencyGraph ,
198
- _ inputsInvalidatedByExternals: Set < TypedVirtualPath > ,
198
+ _ inputsInvalidatedByExternals: TransitivelyInvalidatedInputSet ,
199
199
batchJobFormer: inout Driver
200
200
) throws -> ( skippedCompileGroups: [ TypedVirtualPath : CompileJobGroup ] ,
201
201
mandatoryJobsInOrder: [ Job ] )
@@ -215,9 +215,13 @@ extension IncrementalCompilationState.InitialStateComputer {
215
215
batchJobFormer. formBatchedJobs (
216
216
mandatoryCompileGroupsInOrder. flatMap { $0. allJobs ( ) } ,
217
217
showJobLifecycle: showJobLifecycle)
218
+
219
+ moduleDependencyGraph. phase = . buildingAfterEachCompilation
218
220
return ( skippedCompileGroups: [ : ] ,
219
221
mandatoryJobsInOrder: mandatoryJobsInOrder)
220
222
}
223
+ moduleDependencyGraph. phase = . updatingAfterCompilation
224
+
221
225
222
226
let skippedInputs = computeSkippedCompilationInputs (
223
227
inputsInvalidatedByExternals: inputsInvalidatedByExternals,
@@ -245,7 +249,7 @@ extension IncrementalCompilationState.InitialStateComputer {
245
249
246
250
/// Figure out which compilation inputs are *not* mandatory
247
251
private func computeSkippedCompilationInputs(
248
- inputsInvalidatedByExternals: Set < TypedVirtualPath > ,
252
+ inputsInvalidatedByExternals: TransitivelyInvalidatedInputSet ,
249
253
_ moduleDependencyGraph: ModuleDependencyGraph ,
250
254
_ buildRecord: BuildRecord
251
255
) -> Set < TypedVirtualPath > {
@@ -281,7 +285,7 @@ extension IncrementalCompilationState.InitialStateComputer {
281
285
// as each first wave job finished.
282
286
let speculativeInputs = collectInputsToBeSpeculativelyRecompiled (
283
287
changedInputs: changedInputs,
284
- externalDependents: Array ( inputsInvalidatedByExternals) ,
288
+ externalDependents: inputsInvalidatedByExternals,
285
289
inputsMissingOutputs: Set ( inputsMissingOutputs) ,
286
290
moduleDependencyGraph)
287
291
. subtracting ( definitelyRequiredInputs)
@@ -367,28 +371,28 @@ extension IncrementalCompilationState.InitialStateComputer {
367
371
/// before the whole frontend job finished.
368
372
private func collectInputsToBeSpeculativelyRecompiled(
369
373
changedInputs: [ ChangedInput ] ,
370
- externalDependents: [ TypedVirtualPath ] ,
374
+ externalDependents: TransitivelyInvalidatedInputSet ,
371
375
inputsMissingOutputs: Set < TypedVirtualPath > ,
372
376
_ moduleDependencyGraph: ModuleDependencyGraph
373
377
) -> Set < TypedVirtualPath > {
374
378
let cascadingChangedInputs = computeCascadingChangedInputs (
375
379
from: changedInputs,
376
380
inputsMissingOutputs: inputsMissingOutputs)
377
- let cascadingExternalDependents = alwaysRebuildDependents ? externalDependents : [ ]
378
- // Collect the dependent files to speculatively schedule
379
- var dependentFiles = Set < TypedVirtualPath > ( )
380
- let cascadingFileSet = Set ( cascadingChangedInputs) . union ( cascadingExternalDependents)
381
- for cascadingFile in cascadingFileSet {
382
- let dependentsOfOneFile = moduleDependencyGraph
383
- . collectInputsTransitivelyInvalidatedBy ( input: cascadingFile)
384
- for dep in dependentsOfOneFile where !cascadingFileSet. contains ( dep) {
385
- if dependentFiles. insert ( dep) . 0 {
381
+
382
+ var inputsToBeCertainlyRecompiled = alwaysRebuildDependents ? externalDependents : TransitivelyInvalidatedInputSet ( )
383
+ inputsToBeCertainlyRecompiled. formUnion ( cascadingChangedInputs)
384
+
385
+ return inputsToBeCertainlyRecompiled. reduce ( into: Set ( ) ) {
386
+ speculativelyRecompiledInputs, certainlyRecompiledInput in
387
+ let speculativeDependents = moduleDependencyGraph. collectInputsInvalidatedBy ( input: certainlyRecompiledInput)
388
+ for speculativeDependent in speculativeDependents
389
+ where !inputsToBeCertainlyRecompiled. contains ( speculativeDependent) {
390
+ if speculativelyRecompiledInputs. insert ( speculativeDependent) . inserted {
386
391
reporter? . report (
387
- " Immediately scheduling dependent on \( cascadingFile . file. basename) " , dep )
392
+ " Immediately scheduling dependent on \( certainlyRecompiledInput . file. basename) " , speculativeDependent )
388
393
}
389
394
}
390
395
}
391
- return dependentFiles
392
396
}
393
397
394
398
// Collect the files that will be compiled whose dependents should be schedule
0 commit comments