Skip to content

Commit b9a6387

Browse files
author
David Ungar
authored
Merge pull request #28642 from davidungar/markTransExt-returns-value
[Driver] Change `markTransitive` and `markExternal` to return values
2 parents 4d88150 + 9bfed89 commit b9a6387

File tree

6 files changed

+225
-278
lines changed

6 files changed

+225
-278
lines changed

include/swift/Driver/CoarseGrainedDependencyGraph.h

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,13 @@ class CoarseGrainedDependencyGraphImpl {
158158

159159
/// See CoarseGrainedDependencyGraph::markTransitive.
160160

161-
void markTransitive(SmallVectorImpl<const void *> &visited,
162-
const void *node, MarkTracerImpl *tracer = nullptr);
161+
std::vector<const void*> markTransitive(const void *node, MarkTracerImpl *tracer = nullptr);
162+
163163
bool markIntransitive(const void *node) {
164164
assert(Provides.count(node) && "node is not in the graph");
165165
return Marked.insert(node).second;
166166
}
167-
void markExternal(SmallVectorImpl<const void *> &visited,
168-
StringRef externalDependency);
167+
std::vector<const void*> markExternal(StringRef externalDependency);
169168

170169
public:
171170
void forEachUnmarkedJobDirectlyDependentOnExternalSwiftdeps(
@@ -202,13 +201,14 @@ class CoarseGrainedDependencyGraph : public CoarseGrainedDependencyGraphImpl {
202201
using Traits = llvm::PointerLikeTypeTraits<T>;
203202
static_assert(Traits::NumLowBitsAvailable >= 0, "not a pointer-like type");
204203

205-
static void copyBack(SmallVectorImpl<T> &result,
206-
ArrayRef<const void *> rawNodes) {
207-
result.reserve(result.size() + rawNodes.size());
204+
static std::vector<T> copyBack(ArrayRef<const void *> rawNodes) {
205+
std::vector<T> result;
206+
result.reserve(rawNodes.size());
208207
std::transform(rawNodes.begin(), rawNodes.end(), std::back_inserter(result),
209208
[](const void *rawNode) {
210209
return Traits::getFromVoidPointer(const_cast<void *>(rawNode));
211210
});
211+
return result;
212212
}
213213

214214
public:
@@ -286,23 +286,20 @@ class CoarseGrainedDependencyGraph : public CoarseGrainedDependencyGraphImpl {
286286
///
287287
/// The traversal routines use
288288
/// \p visited to avoid endless recursion.
289-
template <unsigned N>
290-
void markTransitive(SmallVector<T, N> &visited, T node,
289+
std::vector<T> markTransitive(T node,
291290
MarkTracer *tracer = nullptr) {
292-
SmallVector<const void *, N> rawMarked;
291+
std::vector<const void *> rawMarked =
293292
CoarseGrainedDependencyGraphImpl::markTransitive(
294-
rawMarked, Traits::getAsVoidPointer(node), tracer);
293+
Traits::getAsVoidPointer(node), tracer);
295294
// FIXME: How can we avoid this copy?
296-
copyBack(visited, rawMarked);
295+
return copyBack(rawMarked);
297296
}
298297

299-
template <unsigned N>
300-
void markExternal(SmallVector<T, N> &visited, StringRef externalDependency) {
301-
SmallVector<const void *, N> rawMarked;
302-
CoarseGrainedDependencyGraphImpl::markExternal(rawMarked,
303-
externalDependency);
298+
std::vector<T>
299+
markExternal(StringRef externalDependency) {
300+
const auto rawMarked = CoarseGrainedDependencyGraphImpl::markExternal(externalDependency);
304301
// FIXME: How can we avoid this copy?
305-
copyBack(visited, rawMarked);
302+
return copyBack(rawMarked);
306303
}
307304

308305
/// Marks \p node without marking any dependencies.

include/swift/Driver/FineGrainedDependencyDriverGraph.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,7 @@ class ModuleDepGraph {
304304
/// 2. Jobs not previously known to need dependencies reexamined after they
305305
/// are recompiled. Such jobs are added to the \ref cascadingJobs set, and
306306
/// accessed via \ref isMarked.
307-
void markTransitive(
308-
SmallVectorImpl<const driver::Job *> &consequentJobsToRecompile,
307+
std::vector<const driver::Job*> markTransitive(
309308
const driver::Job *jobToBeRecompiled, const void *ignored = nullptr);
310309

311310
/// "Mark" this node only.
@@ -316,8 +315,7 @@ class ModuleDepGraph {
316315

317316
std::vector<StringRef> getExternalDependencies() const;
318317

319-
void markExternal(SmallVectorImpl<const driver::Job *> &uses,
320-
StringRef externalDependency);
318+
std::vector<const driver::Job*> markExternal(StringRef externalDependency);
321319

322320
void forEachUnmarkedJobDirectlyDependentOnExternalSwiftdeps(
323321
StringRef externalDependency, function_ref<void(const driver::Job *)> fn);
@@ -436,8 +434,7 @@ class ModuleDepGraph {
436434
std::unordered_set<const ModuleDepGraphNode *> &foundDependents,
437435
const ModuleDepGraphNode *definition);
438436

439-
void computeUniqueJobsFromNodes(
440-
SmallVectorImpl<const driver::Job *> &uniqueJobs,
437+
std::vector<const driver::Job*> computeUniqueJobsFromNodes(
441438
const std::unordered_set<const ModuleDepGraphNode *> &nodes);
442439

443440
/// Record a visit to this node for later dependency printing

lib/Driver/CoarseGrainedDependencyGraph.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,16 @@ CoarseGrainedDependencyGraphImpl::loadFromBuffer(const void *node,
297297
interfaceHashCallback);
298298
}
299299

300-
void CoarseGrainedDependencyGraphImpl::markExternal(
301-
SmallVectorImpl<const void *> &visited, StringRef externalDependency) {
300+
std::vector<const void*> CoarseGrainedDependencyGraphImpl::markExternal(
301+
StringRef externalDependency) {
302+
std::vector<const void*> visited;
302303
forEachUnmarkedJobDirectlyDependentOnExternalSwiftdeps(
303-
externalDependency, [&](const void *node) {
304-
visited.push_back(node);
305-
markTransitive(visited, node);
306-
});
304+
externalDependency, [&](const void *node) {
305+
visited.push_back(node);
306+
for (const void* markedNode: markTransitive(node))
307+
visited.push_back(markedNode);
308+
});
309+
return visited;
307310
}
308311

309312
void CoarseGrainedDependencyGraphImpl::
@@ -322,9 +325,10 @@ void CoarseGrainedDependencyGraphImpl::
322325
}
323326
}
324327

325-
void CoarseGrainedDependencyGraphImpl::markTransitive(
326-
SmallVectorImpl<const void *> &visited, const void *node,
328+
std::vector<const void*> CoarseGrainedDependencyGraphImpl::markTransitive(
329+
const void *node,
327330
MarkTracerImpl *tracer) {
331+
std::vector <const void*> visited;
328332
assert(Provides.count(node) && "node is not in the graph");
329333
llvm::SpecificBumpPtrAllocator<MarkTracerImpl::Entry> scratchAlloc;
330334

@@ -408,6 +412,7 @@ void CoarseGrainedDependencyGraphImpl::markTransitive(
408412
continue;
409413
record(next);
410414
}
415+
return visited;
411416
}
412417

413418
void CoarseGrainedDependencyGraphImpl::MarkTracerImpl::countStatsForNodeMarking(

lib/Driver/Compilation.cpp

Lines changed: 72 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -437,11 +437,9 @@ namespace driver {
437437
/// invalidated by any new dependency edges introduced by it. If reloading
438438
/// fails, this can cause deferred jobs to be immediately scheduled.
439439

440-
template <unsigned N>
441-
void reloadAndRemarkDeps(const Job *FinishedCmd, int ReturnCode,
442-
SmallVector<const Job *, N> &Dependents,
440+
std::vector<const Job*>
441+
reloadAndRemarkDeps(const Job *FinishedCmd, int ReturnCode,
443442
const bool forRanges) {
444-
445443
const CommandOutput &Output = FinishedCmd->getOutput();
446444
StringRef DependenciesFile =
447445
Output.getAdditionalOutputForType(file_types::TY_SwiftDeps);
@@ -454,7 +452,7 @@ namespace driver {
454452
// not using either of those right now, and this logic should probably
455453
// be revisited when we are.
456454
assert(FinishedCmd->getCondition() == Job::Condition::Always);
457-
return;
455+
return {};
458456
}
459457
// If we have a dependency file /and/ the frontend task exited normally,
460458
// we can be discerning about what downstream files to rebuild.
@@ -470,61 +468,61 @@ namespace driver {
470468

471469
switch (loadDepGraphFromPath(FinishedCmd, DependenciesFile,
472470
Comp.getDiags(), forRanges)) {
473-
case CoarseGrainedDependencyGraphImpl::LoadResult::HadError:
474-
if (ReturnCode == EXIT_SUCCESS) {
475-
dependencyLoadFailed(DependenciesFile);
476-
// Better try compiling whatever was waiting on more info.
477-
for (const Job *Cmd : DeferredCommands)
478-
scheduleCommandIfNecessaryAndPossible(Cmd);
479-
DeferredCommands.clear();
480-
Dependents.clear();
481-
} // else, let the next build handle it.
471+
case CoarseGrainedDependencyGraph::LoadResult::HadError:
472+
if (ReturnCode != EXIT_SUCCESS)
473+
// let the next build handle it.
474+
break;
475+
dependencyLoadFailed(DependenciesFile);
476+
// Better try compiling whatever was waiting on more info.
477+
for (const Job *Cmd : DeferredCommands)
478+
scheduleCommandIfNecessaryAndPossible(Cmd);
479+
DeferredCommands.clear();
482480
break;
483-
case CoarseGrainedDependencyGraphImpl::LoadResult::UpToDate:
481+
482+
case CoarseGrainedDependencyGraph::LoadResult::UpToDate:
484483
if (!wasCascading)
485484
break;
486485
LLVM_FALLTHROUGH;
487-
case CoarseGrainedDependencyGraphImpl::LoadResult::AffectsDownstream:
488-
markTransitiveInDepGraph(Dependents, FinishedCmd, forRanges,
486+
case CoarseGrainedDependencyGraph::LoadResult::AffectsDownstream:
487+
return markTransitiveInDepGraph(FinishedCmd, forRanges,
489488
IncrementalTracer);
490-
break;
491489
}
492-
} else {
493-
// If there's an abnormal exit (a crash), assume the worst.
494-
switch (FinishedCmd->getCondition()) {
495-
case Job::Condition::NewlyAdded:
496-
// The job won't be treated as newly added next time. Conservatively
497-
// mark it as affecting other jobs, because some of them may have
498-
// completed already.
499-
markTransitiveInDepGraph(Dependents, FinishedCmd, forRanges,
500-
IncrementalTracer);
501-
break;
502-
case Job::Condition::Always:
503-
// Any incremental task that shows up here has already been marked;
504-
// we didn't need to wait for it to finish to start downstream
505-
// tasks.
506-
assert(isMarkedInDepGraph(FinishedCmd, forRanges));
507-
break;
508-
case Job::Condition::RunWithoutCascading:
509-
// If this file changed, it might have been a non-cascading change
510-
// and it might not. Unfortunately, the interface hash has been
511-
// updated or compromised, so we don't actually know anymore; we
512-
// have to conservatively assume the changes could affect other
513-
// files.
514-
markTransitiveInDepGraph(Dependents, FinishedCmd, forRanges,
515-
IncrementalTracer);
516-
break;
517-
case Job::Condition::CheckDependencies:
518-
// If the only reason we're running this is because something else
519-
// changed, then we can trust the dependency graph as to whether
520-
// it's a cascading or non-cascading change. That is, if whatever
521-
// /caused/ the error isn't supposed to affect other files, and
522-
// whatever /fixes/ the error isn't supposed to affect other files,
523-
// then there's no need to recompile any other inputs. If either of
524-
// those are false, we /do/ need to recompile other inputs.
525-
break;
526-
}
490+
return {};
527491
}
492+
// If there's an abnormal exit (a crash), assume the worst.
493+
switch (FinishedCmd->getCondition()) {
494+
case Job::Condition::NewlyAdded:
495+
// The job won't be treated as newly added next time. Conservatively
496+
// mark it as affecting other jobs, because some of them may have
497+
// completed already.
498+
return markTransitiveInDepGraph(FinishedCmd, forRanges,
499+
IncrementalTracer);
500+
case Job::Condition::Always:
501+
// Any incremental task that shows up here has already been marked;
502+
// we didn't need to wait for it to finish to start downstream
503+
// tasks.
504+
assert(isMarkedInDepGraph(FinishedCmd, forRanges));
505+
break;
506+
case Job::Condition::RunWithoutCascading:
507+
// If this file changed, it might have been a non-cascading change
508+
// and it might not. Unfortunately, the interface hash has been
509+
// updated or compromised, so we don't actually know anymore; we
510+
// have to conservatively assume the changes could affect other
511+
// files.
512+
return markTransitiveInDepGraph(FinishedCmd, forRanges,
513+
IncrementalTracer);
514+
515+
case Job::Condition::CheckDependencies:
516+
// If the only reason we're running this is because something else
517+
// changed, then we can trust the dependency graph as to whether
518+
// it's a cascading or non-cascading change. That is, if whatever
519+
// /caused/ the error isn't supposed to affect other files, and
520+
// whatever /fixes/ the error isn't supposed to affect other files,
521+
// then there's no need to recompile any other inputs. If either of
522+
// those are false, we /do/ need to recompile other inputs.
523+
break;
524+
}
525+
return {};
528526
}
529527

530528
/// Check to see if a job produced a zero-length serialized diagnostics
@@ -744,8 +742,7 @@ namespace driver {
744742
const bool forRanges) {
745743
if (!Comp.getIncrementalBuildEnabled())
746744
return {};
747-
SmallVector<const Job *, 16> Dependents;
748-
reloadAndRemarkDeps(FinishedCmd, ReturnCode, Dependents, forRanges);
745+
auto Dependents = reloadAndRemarkDeps(FinishedCmd, ReturnCode, forRanges);
749746
CommandSet DepSet;
750747
for (const Job *Cmd : Dependents)
751748
DepSet.insert(Cmd);
@@ -1035,12 +1032,12 @@ namespace driver {
10351032
const auto loadResult = loadDepGraphFromPath(Cmd, DependenciesFile,
10361033
Comp.getDiags(), forRanges);
10371034
switch (loadResult) {
1038-
case CoarseGrainedDependencyGraphImpl::LoadResult::HadError:
1035+
case CoarseGrainedDependencyGraph::LoadResult::HadError:
10391036
dependencyLoadFailed(DependenciesFile, /*Warn=*/true);
10401037
return None;
1041-
case CoarseGrainedDependencyGraphImpl::LoadResult::UpToDate:
1038+
case CoarseGrainedDependencyGraph::LoadResult::UpToDate:
10421039
return std::make_pair(Cmd->getCondition(), true);
1043-
case CoarseGrainedDependencyGraphImpl::LoadResult::AffectsDownstream:
1040+
case CoarseGrainedDependencyGraph::LoadResult::AffectsDownstream:
10441041
if (Comp.getEnableFineGrainedDependencies()) {
10451042
// The fine-grained graph reports a change, since it lumps new
10461043
// files together with new "Provides".
@@ -1106,15 +1103,16 @@ namespace driver {
11061103
}
11071104
}
11081105

1109-
SmallVector<const Job *, 16> collectCascadedJobsFromDependencyGraph(
1106+
CommandSet collectCascadedJobsFromDependencyGraph(
11101107
const CommandSet &InitialCascadingCommands, const bool forRanges) {
1111-
SmallVector<const Job *, 16> CascadedJobs;
1108+
CommandSet CascadedJobs;
11121109
// We scheduled all of the files that have actually changed. Now add the
11131110
// files that haven't changed, so that they'll get built in parallel if
11141111
// possible and after the first set of files if it's not.
11151112
for (auto *Cmd : InitialCascadingCommands) {
1116-
markTransitiveInDepGraph(CascadedJobs, Cmd, forRanges,
1117-
IncrementalTracer);
1113+
for (const auto *transitiveCmd: markTransitiveInDepGraph(Cmd, forRanges,
1114+
IncrementalTracer))
1115+
CascadedJobs.insert(transitiveCmd);
11181116
}
11191117
for (auto *transitiveCmd : CascadedJobs)
11201118
noteBuilding(transitiveCmd, /*willBeBuilding=*/true,
@@ -1133,7 +1131,8 @@ namespace driver {
11331131
// If the dependency has been modified since the oldest built file,
11341132
// or if we can't stat it for some reason (perhaps it's been
11351133
// deleted?), trigger rebuilds through the dependency graph.
1136-
markExternalInDepGraph(ExternallyDependentJobs, dependency, forRanges);
1134+
for (const Job * marked: markExternalInDepGraph(dependency, forRanges))
1135+
ExternallyDependentJobs.push_back(marked);
11371136
});
11381137
for (auto *externalCmd : ExternallyDependentJobs) {
11391138
noteBuilding(externalCmd, /*willBeBuilding=*/true,
@@ -1574,15 +1573,12 @@ namespace driver {
15741573
return Dependencies;
15751574
}
15761575

1577-
template <unsigned N>
1578-
void markExternalInDepGraph(SmallVector<const driver::Job *, N> &uses,
1579-
StringRef externalDependency,
1576+
std::vector<const Job*>
1577+
markExternalInDepGraph(StringRef externalDependency,
15801578
const bool forRanges) {
1581-
if (Comp.getEnableFineGrainedDependencies())
1582-
getFineGrainedDepGraph(forRanges).markExternal(uses,
1583-
externalDependency);
1584-
else
1585-
getDepGraph(forRanges).markExternal(uses, externalDependency);
1579+
return Comp.getEnableFineGrainedDependencies()
1580+
? getFineGrainedDepGraph(forRanges).markExternal(externalDependency)
1581+
: getDepGraph(forRanges).markExternal(externalDependency);
15861582
}
15871583

15881584
bool markIntransitiveInDepGraph(const Job *Cmd, const bool forRanges) {
@@ -1600,15 +1596,13 @@ namespace driver {
16001596
: getDepGraph(forRanges).loadFromPath(Cmd, path, diags);
16011597
}
16021598

1603-
template <unsigned N>
1604-
void markTransitiveInDepGraph(
1605-
SmallVector<const Job *, N> &visited, const Job *Cmd,
1599+
std::vector<const Job*> markTransitiveInDepGraph(
1600+
const Job *Cmd,
16061601
const bool forRanges,
16071602
CoarseGrainedDependencyGraph::MarkTracer *tracer = nullptr) {
1608-
if (Comp.getEnableFineGrainedDependencies())
1609-
getFineGrainedDepGraph(forRanges).markTransitive(visited, Cmd, tracer);
1610-
else
1611-
getDepGraph(forRanges).markTransitive(visited, Cmd, tracer);
1603+
return Comp.getEnableFineGrainedDependencies()
1604+
? getFineGrainedDepGraph(forRanges).markTransitive(Cmd, tracer)
1605+
: getDepGraph(forRanges).markTransitive(Cmd, tracer);
16121606
}
16131607

16141608
void addIndependentNodeToDepGraph(const Job *Cmd, const bool forRanges) {

0 commit comments

Comments
 (0)