Skip to content

Commit 3ba33b9

Browse files
committed
Install Faux Cross-Module Incremental Infrastructure In Driver
Treat any incremental external depends like normal external depends. This will eventually become the fallback behavior for cross-module incremental builds.
1 parent e646ef2 commit 3ba33b9

File tree

3 files changed

+111
-2
lines changed

3 files changed

+111
-2
lines changed

include/swift/Driver/FineGrainedDependencyDriverGraph.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ class ModuleDepGraph {
168168

169169
// Supports requests from the driver to getExternalDependencies.
170170
std::unordered_set<std::string> externalDependencies;
171+
std::unordered_set<std::string> incrementalExternalDependencies;
171172

172173
/// Keyed by swiftdeps filename, so we can get back to Jobs.
173174
std::unordered_map<std::string, const driver::Job *> jobsBySwiftDeps;
@@ -512,15 +513,28 @@ class ModuleDepGraph {
512513
std::vector<const driver::Job *>
513514
findExternallyDependentUntracedJobs(StringRef externalDependency);
514515

516+
/// Find jobs that were previously not known to need compilation but that
517+
/// depend on \c incrementalExternalDependency.
518+
///
519+
/// This code path should only act as a fallback to the status-quo behavior.
520+
/// Otherwise it acts to pessimize the behavior of cross-module incremental
521+
/// builds.
522+
std::vector<const driver::Job *>
523+
findIncrementalExternallyDependentUntracedJobs(StringRef externalDependency);
524+
515525
//============================================================================
516526
// MARK: ModuleDepGraph - External dependencies
517527
//============================================================================
518528

519529
public:
520530
std::vector<StringRef> getExternalDependencies() const;
531+
std::vector<StringRef> getIncrementalExternalDependencies() const;
521532

522533
void forEachUntracedJobDirectlyDependentOnExternalSwiftDeps(
523534
StringRef externalDependency, function_ref<void(const driver::Job *)> fn);
535+
void forEachUntracedJobDirectlyDependentOnExternalIncrementalSwiftDeps(
536+
StringRef externalDependency, function_ref<void(const driver::Job *)> fn);
537+
524538
//============================================================================
525539
// MARK: ModuleDepGraph - verification
526540
//============================================================================

lib/Driver/Compilation.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,10 @@ namespace driver {
935935
for (const auto cmd :
936936
collectExternallyDependentJobsFromDependencyGraph(forRanges))
937937
jobsToSchedule.insert(cmd);
938+
for (const auto cmd :
939+
collectIncrementalExternallyDependentJobsFromDependencyGraph(
940+
forRanges))
941+
jobsToSchedule.insert(cmd);
938942
return jobsToSchedule;
939943
}
940944

@@ -1109,6 +1113,21 @@ namespace driver {
11091113
}
11101114
}
11111115

1116+
void forEachOutOfDateIncrementalExternalDependency(
1117+
const bool forRanges,
1118+
function_ref<void(StringRef)> consumeExternalSwiftDeps) {
1119+
for (StringRef dependency :
1120+
getIncrementalExternalDependencies(forRanges)) {
1121+
// If the dependency has been modified since the oldest built file,
1122+
// or if we can't stat it for some reason (perhaps it's been
1123+
// deleted?), trigger rebuilds through the dependency graph.
1124+
llvm::sys::fs::file_status depStatus;
1125+
if (llvm::sys::fs::status(dependency, depStatus) ||
1126+
Comp.getLastBuildTime() < depStatus.getLastModificationTime())
1127+
consumeExternalSwiftDeps(dependency);
1128+
}
1129+
}
1130+
11121131
CommandSet collectCascadedJobsFromDependencyGraph(
11131132
const CommandSet &InitialCascadingCommands, const bool forRanges) {
11141133
CommandSet CascadedJobs;
@@ -1141,6 +1160,25 @@ namespace driver {
11411160
return ExternallyDependentJobs;
11421161
}
11431162

1163+
SmallVector<const Job *, 16>
1164+
collectIncrementalExternallyDependentJobsFromDependencyGraph(
1165+
const bool forRanges) {
1166+
SmallVector<const Job *, 16> ExternallyDependentJobs;
1167+
// Check all cross-module dependencies as well.
1168+
forEachOutOfDateIncrementalExternalDependency(
1169+
forRanges, [&](StringRef dependency) {
1170+
// If the dependency has been modified since the oldest built file,
1171+
// or if we can't stat it for some reason (perhaps it's been
1172+
// deleted?), trigger rebuilds through the dependency graph.
1173+
for (const Job *marked :
1174+
markExternalInDepGraph(dependency, forRanges))
1175+
ExternallyDependentJobs.push_back(marked);
1176+
});
1177+
noteBuildingJobs(ExternallyDependentJobs, forRanges,
1178+
"because of external dependencies");
1179+
return ExternallyDependentJobs;
1180+
}
1181+
11441182
/// Insert all jobs in \p Cmds (of descriptive name \p Kind) to the \c
11451183
/// TaskQueue, and clear \p Cmds.
11461184
template <typename Container>
@@ -1594,6 +1632,12 @@ namespace driver {
15941632
return getFineGrainedDepGraph(forRanges).getExternalDependencies();
15951633
}
15961634

1635+
std::vector<StringRef>
1636+
getIncrementalExternalDependencies(const bool forRanges) const {
1637+
return getFineGrainedDepGraph(forRanges)
1638+
.getIncrementalExternalDependencies();
1639+
}
1640+
15971641
std::vector<const Job*>
15981642
markExternalInDepGraph(StringRef externalDependency,
15991643
const bool forRanges) {

lib/Driver/FineGrainedDependencyDriverGraph.cpp

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ std::vector<StringRef> ModuleDepGraph::getExternalDependencies() const {
195195
externalDependencies.end());
196196
}
197197

198+
std::vector<StringRef>
199+
ModuleDepGraph::getIncrementalExternalDependencies() const {
200+
return std::vector<StringRef>(incrementalExternalDependencies.begin(),
201+
incrementalExternalDependencies.end());
202+
}
203+
198204
// Add every (swiftdeps) use of the external dependency to foundJobs.
199205
// Can return duplicates, but it doesn't break anything, and they will be
200206
// canonicalized later.
@@ -216,6 +222,26 @@ std::vector<const Job *> ModuleDepGraph::findExternallyDependentUntracedJobs(
216222
return foundJobs;
217223
}
218224

225+
std::vector<const Job *>
226+
ModuleDepGraph::findIncrementalExternallyDependentUntracedJobs(
227+
StringRef externalDependency) {
228+
FrontendStatsTracer tracer(stats,
229+
"fine-grained-dependencies-"
230+
"findIncrementalExternallyDependentUntracedJobs");
231+
std::vector<const Job *> foundJobs;
232+
forEachUntracedJobDirectlyDependentOnExternalIncrementalSwiftDeps(
233+
externalDependency, [&](const Job *job) {
234+
foundJobs.push_back(job);
235+
for (const Job *marked : findJobsToRecompileWhenWholeJobChanges(job)) {
236+
// findJobsToRecompileWhenWholeJobChanges is reflexive
237+
// Don't return job twice.
238+
if (marked != job)
239+
foundJobs.push_back(marked);
240+
}
241+
});
242+
return foundJobs;
243+
}
244+
219245
void ModuleDepGraph::forEachUntracedJobDirectlyDependentOnExternalSwiftDeps(
220246
StringRef externalSwiftDeps, function_ref<void(const Job *)> fn) {
221247
// TODO move nameForDep into key
@@ -228,6 +254,19 @@ void ModuleDepGraph::forEachUntracedJobDirectlyDependentOnExternalSwiftDeps(
228254
}
229255
}
230256

257+
void ModuleDepGraph::
258+
forEachUntracedJobDirectlyDependentOnExternalIncrementalSwiftDeps(
259+
StringRef externalSwiftDeps, function_ref<void(const Job *)> fn) {
260+
// TODO move nameForDep into key
261+
// These nodes will depend on the *interface* of the external Decl.
262+
DependencyKey key(NodeKind::incrementalExternalDepend, DeclAspect::interface,
263+
"", externalSwiftDeps.str());
264+
for (const ModuleDepGraphNode *useNode : usesByDef[key]) {
265+
if (!useNode->getHasBeenTraced())
266+
fn(getJob(useNode->getSwiftDepsOfProvides()));
267+
}
268+
}
269+
231270
//==============================================================================
232271
// MARK: Integrating SourceFileDepGraph into ModuleDepGraph
233272
//==============================================================================
@@ -387,9 +426,14 @@ bool ModuleDepGraph::recordWhatUseDependsUpon(
387426
sourceFileUseNode, [&](const SourceFileDepGraphNode *def) {
388427
const bool isNewUse =
389428
usesByDef[def->getKey()].insert(moduleUseNode).second;
390-
if (isNewUse && def->getKey().getKind() == NodeKind::externalDepend) {
429+
if (isNewUse) {
391430
StringRef externalSwiftDeps = def->getKey().getName();
392-
externalDependencies.insert(externalSwiftDeps.str());
431+
if (def->getKey().getKind() == NodeKind::externalDepend) {
432+
externalDependencies.insert(externalSwiftDeps.str());
433+
} else if (def->getKey().getKind() ==
434+
NodeKind::incrementalExternalDepend) {
435+
incrementalExternalDependencies.insert(externalSwiftDeps.str());
436+
}
393437
useHasNewExternalDependency = true;
394438
}
395439
});
@@ -641,6 +685,9 @@ void ModuleDepGraph::verifyExternalDependencyUniqueness(
641685
assert((key.getKind() != NodeKind::externalDepend ||
642686
externalDependencies.count(key.getName().str()) == 1) &&
643687
"Ensure each external dependency is tracked exactly once");
688+
assert((key.getKind() != NodeKind::incrementalExternalDepend ||
689+
incrementalExternalDependencies.count(key.getName().str()) == 1) &&
690+
"Ensure each incremental external dependency is tracked exactly once");
644691
}
645692

646693
void ModuleDepGraph::verifyCanFindEachJob() const {
@@ -725,6 +772,10 @@ void ModuleDepGraph::printOneNodeOfPath(raw_ostream &out,
725772
out << filename << " depends on " << key.aspectName() << " of module '"
726773
<< key.humanReadableName() << "'";
727774
break;
775+
case NodeKind::incrementalExternalDepend:
776+
out << filename << " depends on " << key.aspectName()
777+
<< " of incremental module '" << key.humanReadableName() << "'";
778+
break;
728779
case NodeKind::sourceFileProvide:
729780
out << key.aspectName() << " of source file " << key.humanReadableName();
730781
break;

0 commit comments

Comments
 (0)