@@ -116,7 +116,7 @@ extension IncrementalCompilationState.InitialStateComputer {
116116 /// For inputs with swiftDeps in OFM, but no readable file, puts input in graph map, but no nodes in graph:
117117 /// caller must ensure scheduling of those
118118 private func computeGraphAndInputsInvalidatedByExternals( )
119- -> ( ModuleDependencyGraph , Set < TypedVirtualPath > ) ? {
119+ -> ( ModuleDependencyGraph , TransitivelyInvalidatedInputSet ) ? {
120120 precondition ( sourceFiles. disappeared. isEmpty,
121121 " Would have to remove nodes from the graph if reading prior " )
122122 if readPriorsFromModuleDependencyGraph {
@@ -128,7 +128,7 @@ extension IncrementalCompilationState.InitialStateComputer {
128128 }
129129
130130 private func readPriorGraphAndCollectInputsInvalidatedByChangedOrAddedExternals(
131- ) -> ( ModuleDependencyGraph , Set < TypedVirtualPath > ) ?
131+ ) -> ( ModuleDependencyGraph , TransitivelyInvalidatedInputSet ) ?
132132 {
133133 let dependencyGraphPath = buildRecordInfo. dependencyGraphPath
134134 let graphIfPresent : ModuleDependencyGraph ?
@@ -152,8 +152,10 @@ extension IncrementalCompilationState.InitialStateComputer {
152152
153153 // Any externals not already in graph must be additions which should trigger
154154 // 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)
157159 return ( graph, inputsInvalidatedByExternals)
158160 }
159161
@@ -165,17 +167,15 @@ extension IncrementalCompilationState.InitialStateComputer {
165167 /// For externalDependencies, puts then in graph.fingerprintedExternalDependencies, but otherwise
166168 /// does nothing special.
167169 private func buildInitialGraphFromSwiftDepsAndCollectInputsInvalidatedByChangedExternals(
168- ) -> ( ModuleDependencyGraph , Set < TypedVirtualPath > ) ?
170+ ) -> ( ModuleDependencyGraph , TransitivelyInvalidatedInputSet ) ?
169171 {
170- let graph = ModuleDependencyGraph ( self )
172+ let graph = ModuleDependencyGraph ( self , . buildingWithoutAPrior )
171173 assert ( outputFileMap. onlySourceFilesHaveSwiftDeps ( ) )
172174 guard graph. populateInputDependencySourceMap ( ) else {
173175 return nil
174176 }
175177
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 ( )
179179 for input in sourceFiles. currentInOrder {
180180 guard let invalidatedInputs = graph. collectInputsRequiringCompilationFromExternalsFoundByCompiling ( input: input)
181181 else {
@@ -195,7 +195,7 @@ extension IncrementalCompilationState.InitialStateComputer {
195195 /// listed in fingerprintExternalDependencies.
196196 private func computeInputsAndGroups(
197197 _ moduleDependencyGraph: ModuleDependencyGraph ,
198- _ inputsInvalidatedByExternals: Set < TypedVirtualPath > ,
198+ _ inputsInvalidatedByExternals: TransitivelyInvalidatedInputSet ,
199199 batchJobFormer: inout Driver
200200 ) throws -> ( skippedCompileGroups: [ TypedVirtualPath : CompileJobGroup ] ,
201201 mandatoryJobsInOrder: [ Job ] )
@@ -215,9 +215,13 @@ extension IncrementalCompilationState.InitialStateComputer {
215215 batchJobFormer. formBatchedJobs (
216216 mandatoryCompileGroupsInOrder. flatMap { $0. allJobs ( ) } ,
217217 showJobLifecycle: showJobLifecycle)
218+
219+ moduleDependencyGraph. phase = . buildingAfterEachCompilation
218220 return ( skippedCompileGroups: [ : ] ,
219221 mandatoryJobsInOrder: mandatoryJobsInOrder)
220222 }
223+ moduleDependencyGraph. phase = . updatingAfterCompilation
224+
221225
222226 let skippedInputs = computeSkippedCompilationInputs (
223227 inputsInvalidatedByExternals: inputsInvalidatedByExternals,
@@ -245,7 +249,7 @@ extension IncrementalCompilationState.InitialStateComputer {
245249
246250 /// Figure out which compilation inputs are *not* mandatory
247251 private func computeSkippedCompilationInputs(
248- inputsInvalidatedByExternals: Set < TypedVirtualPath > ,
252+ inputsInvalidatedByExternals: TransitivelyInvalidatedInputSet ,
249253 _ moduleDependencyGraph: ModuleDependencyGraph ,
250254 _ buildRecord: BuildRecord
251255 ) -> Set < TypedVirtualPath > {
@@ -281,7 +285,7 @@ extension IncrementalCompilationState.InitialStateComputer {
281285 // as each first wave job finished.
282286 let speculativeInputs = collectInputsToBeSpeculativelyRecompiled (
283287 changedInputs: changedInputs,
284- externalDependents: Array ( inputsInvalidatedByExternals) ,
288+ externalDependents: inputsInvalidatedByExternals,
285289 inputsMissingOutputs: Set ( inputsMissingOutputs) ,
286290 moduleDependencyGraph)
287291 . subtracting ( definitelyRequiredInputs)
@@ -367,28 +371,28 @@ extension IncrementalCompilationState.InitialStateComputer {
367371 /// before the whole frontend job finished.
368372 private func collectInputsToBeSpeculativelyRecompiled(
369373 changedInputs: [ ChangedInput ] ,
370- externalDependents: [ TypedVirtualPath ] ,
374+ externalDependents: TransitivelyInvalidatedInputSet ,
371375 inputsMissingOutputs: Set < TypedVirtualPath > ,
372376 _ moduleDependencyGraph: ModuleDependencyGraph
373377 ) -> Set < TypedVirtualPath > {
374378 let cascadingChangedInputs = computeCascadingChangedInputs (
375379 from: changedInputs,
376380 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 {
386391 reporter? . report (
387- " Immediately scheduling dependent on \( cascadingFile . file. basename) " , dep )
392+ " Immediately scheduling dependent on \( certainlyRecompiledInput . file. basename) " , speculativeDependent )
388393 }
389394 }
390395 }
391- return dependentFiles
392396 }
393397
394398 // Collect the files that will be compiled whose dependents should be schedule
0 commit comments