This commit is contained in:
David Ungar
2019-01-28 15:56:18 -08:00
parent fc4b7963ee
commit 14ba2a1b60
7 changed files with 142 additions and 119 deletions

View File

@@ -462,9 +462,11 @@ public:
/// Return true if this key can be recorded as a use of def.
/// If everything is the same except for aspect, it's tricky:
/// The implementation does not depend on the interface; it's the other way around.
/// The implementation does not depend on the interface; it's the other way
/// around.
bool canDependUpon(const DependencyKey &def) const {
if (getKind() != def.getKind() || getContext() != def.getContext() || getName() != def.getName())
if (getKind() != def.getKind() || getContext() != def.getContext() ||
getName() != def.getName())
return true;
if (getAspect() == def.getAspect())
return false;
@@ -664,7 +666,8 @@ public:
bool operator==(const SourceFileDepGraphNode &other) const {
return DepGraphNode::operator==(other) &&
sequenceNumber == other.sequenceNumber &&
defsIDependUpon == other.defsIDependUpon && isProvides == other.isProvides;
defsIDependUpon == other.defsIDependUpon &&
isProvides == other.isProvides;
}
size_t getSequenceNumber() const { return sequenceNumber; }
@@ -755,7 +758,8 @@ public:
const SourceFileDepGraphNode *use)>
fn) const;
void forEachDefDependedUponBy(const SourceFileDepGraphNode *n,
void forEachDefDependedUponBy(
const SourceFileDepGraphNode *n,
function_ref<void(SourceFileDepGraphNode *)> fn) const {
n->forEachDefIDependUpon([&](size_t useIndex) { fn(getNode(useIndex)); });
}
@@ -773,7 +777,8 @@ public:
/// \p Use is the Node that must be rebuilt when \p def changes.
/// Record that fact in the graph.
void addArc(SourceFileDepGraphNode *def, SourceFileDepGraphNode *use) {
getNode(use->getSequenceNumber())->addDefIDependUpon(def->getSequenceNumber());
getNode(use->getSequenceNumber())
->addDefIDependUpon(def->getSequenceNumber());
}
/// Read a swiftdeps file at \p path and return a SourceFileDepGraph if

View File

@@ -161,10 +161,11 @@ protected:
const void *node, MarkTracerImpl *tracer = nullptr);
bool markIntransitive(const void *node) {
assert(Provides.count(node) && "node is not in the graph");
// const driver::Job *HERE = (const driver::Job*)node;
// StringRef HERE1 = llvm::sys::path::filename(HERE->getOutput().getBaseInput(0));
// if (HERE1 == "Calendars.swift")
// llvm::errs() << "HERE10\n";
// const driver::Job *HERE = (const driver::Job*)node;
// StringRef HERE1 =
// llvm::sys::path::filename(HERE->getOutput().getBaseInput(0)); if
// (HERE1 == "Calendars.swift")
// llvm::errs() << "HERE10\n";
return Marked.insert(node).second;
}

View File

@@ -150,7 +150,7 @@ class ModuleDepGraph {
/// source file.)
/// Tracks def-use relationships by DependencyKey.
std::unordered_map<DependencyKey, std::unordered_set<ModuleDepGraphNode*>>
std::unordered_map<DependencyKey, std::unordered_set<ModuleDepGraphNode *>>
usesByDef;
// Supports requests from the driver to getExternalDependencies.
@@ -192,7 +192,8 @@ class ModuleDepGraph {
Optional<std::vector<const ModuleDepGraphNode *>> currentPathIfTracing;
/// If tracing dependencies, record the node sequence
std::unordered_multimap<const driver::Job*, std::vector<const ModuleDepGraphNode *>>
std::unordered_multimap<const driver::Job *,
std::vector<const ModuleDepGraphNode *>>
dependencyPathsToJobs;
/// For helping with performance tuning, may be null:
@@ -289,12 +290,15 @@ public:
/// Interface to status quo code in the driver.
bool isMarked(const driver::Job *) const;
/// Given a "cascading" job, that is a job whose dependents must be recompiled when this job is recompiled,
/// Compute two sets of jobs:
/// 1. Return value (via visited) is the set of jobs needing recompilation after this one, and
/// 2. Jobs not previously known to need dependencies reexamined after they are recompiled.
/// Such jobs are added to the \ref cascadingJobs set, and accessed via \ref isMarked.
void markTransitive(SmallVectorImpl<const driver::Job *> &consequentJobsToRecompile,
/// Given a "cascading" job, that is a job whose dependents must be recompiled
/// when this job is recompiled, Compute two sets of jobs:
/// 1. Return value (via visited) is the set of jobs needing recompilation
/// after this one, and
/// 2. Jobs not previously known to need dependencies reexamined after they
/// are recompiled. Such jobs are added to the \ref cascadingJobs set, and
/// accessed via \ref isMarked.
void markTransitive(
SmallVectorImpl<const driver::Job *> &consequentJobsToRecompile,
const driver::Job *jobToBeRecompiled, const void *ignored = nullptr);
/// "Mark" this node only.
@@ -367,23 +371,21 @@ private:
/// Integration happens when the driver needs to read SourceFileDepGraph.
DependencyGraphImpl::LoadResult integrate(const SourceFileDepGraph &);
enum class LocationOfPreexistingNode {
nowhere, here, elsewhere
};
enum class LocationOfPreexistingNode { nowhere, here, elsewhere };
typedef Optional<std::pair<LocationOfPreexistingNode, ModuleDepGraphNode *>> PreexistingNodeIfAny;
typedef Optional<std::pair<LocationOfPreexistingNode, ModuleDepGraphNode *>>
PreexistingNodeIfAny;
/// Find the preexisting node here that best matches the integrand.
PreexistingNodeIfAny
findPreexistingMatch(StringRef swiftDepsOfCompilationToBeIntegrated,
const SourceFileDepGraphNode *integrand);
/// Integrate the \p integrand into the receiver.
/// Return a bool indicating if this node represents a change that must be
/// propagated.
bool integrateSourceFileDepGraphNode(
const SourceFileDepGraph &g,
bool
integrateSourceFileDepGraphNode(const SourceFileDepGraph &g,
const SourceFileDepGraphNode *integrand,
const PreexistingNodeIfAny preexistingMatch);
@@ -391,10 +393,11 @@ private:
/// file being integrated. \p preexistingNodeInPlace holds the node
/// representing the same Decl that already exists, if there is one. \p
/// prexisintExpat holds a node with the same key that already exists, but was
/// not known to reside in any swiftDeps file. Return a bool indicating if this node represents a change that must be
/// propagated, and the integrated ModuleDepGraphNode.
std::pair<bool, ModuleDepGraphNode*> integrateSourceFileDeclNode(
const SourceFileDepGraphNode *integrand,
/// not known to reside in any swiftDeps file. Return a bool indicating if
/// this node represents a change that must be propagated, and the integrated
/// ModuleDepGraphNode.
std::pair<bool, ModuleDepGraphNode *>
integrateSourceFileDeclNode(const SourceFileDepGraphNode *integrand,
StringRef swiftDepsOfSourceFileGraph,
const PreexistingNodeIfAny preexistingMatch);
@@ -403,7 +406,8 @@ private:
integrateByCreatingANewNode(const SourceFileDepGraphNode *integrand,
Optional<std::string> swiftDepsForNewNode);
/// After importing a provides node from the frontend, record its dependencies.
/// After importing a provides node from the frontend, record its
/// dependencies.
void recordWhatUseDependsUpon(const SourceFileDepGraph &g,
const SourceFileDepGraphNode *sourceFileUseNode,
ModuleDepGraphNode *moduleUseNode);
@@ -415,7 +419,8 @@ private:
/// Given a definition node, and a list of already found dependents,
/// recursively add transitive closure of dependents of the definition
/// into the already found dependents.
/// Also record any dependents that "cascade", i.e. whose dependencies must be recomputed after recompilation so that its dependents can be recompiled.
/// Also record any dependents that "cascade", i.e. whose dependencies must be
/// recomputed after recompilation so that its dependents can be recompiled.
void findDependentNodesAndRecordCascadingOnes(
std::unordered_set<const ModuleDepGraphNode *> &foundDependents,
const ModuleDepGraphNode *definition);
@@ -424,15 +429,15 @@ private:
SmallVectorImpl<const driver::Job *> &uniqueJobs,
const std::unordered_set<const ModuleDepGraphNode *> &nodes);
/// Record a visit to this node for later dependency printing
size_t traceArrival(const ModuleDepGraphNode *visitedNode);
/// Record end of visit to this node.
void traceDeparture(size_t pathLengthAfterArrival);
/// For printing why a Job was compiled, record how it was found.
void recordDependencyPathToJob(const std::vector<const ModuleDepGraphNode *> &pathToJob, const driver::Job* dependentJob);
void recordDependencyPathToJob(
const std::vector<const ModuleDepGraphNode *> &pathToJob,
const driver::Job *dependentJob);
/// Return true if job did not cascade before
bool rememberThatJobCascades(StringRef swiftDeps) {

View File

@@ -69,7 +69,7 @@ void SourceFileDepGraph::forEachArc(
const SourceFileDepGraphNode *use)>
fn) const {
forEachNode([&](const SourceFileDepGraphNode *useNode) {
forEachDefDependedUponBy(useNode, [&](SourceFileDepGraphNode* defNode) {
forEachDefDependedUponBy(useNode, [&](SourceFileDepGraphNode *defNode) {
fn(defNode, useNode);
});
});
@@ -306,7 +306,8 @@ void MappingContextTraits<SourceFileDepGraphNode, SourceFileDepGraph>::mapping(
IO &io, SourceFileDepGraphNode &node, SourceFileDepGraph &g) {
MappingTraits<DepGraphNode>::mapping(io, node);
io.mapRequired("sequenceNumber", node.sequenceNumber);
std::vector<size_t> defsIDependUponVec(node.defsIDependUpon.begin(), node.defsIDependUpon.end());
std::vector<size_t> defsIDependUponVec(node.defsIDependUpon.begin(),
node.defsIDependUpon.end());
io.mapRequired("defsIDependUpon", defsIDependUponVec);
io.mapRequired("isProvides", node.isProvides);
if (!io.outputting()) {

View File

@@ -414,7 +414,6 @@ namespace driver {
SmallVector<const Job *, N> &Dependents,
DependencyGraphT &DepGraph) {
const CommandOutput &Output = FinishedCmd->getOutput();
StringRef DependenciesFile =
Output.getAdditionalOutputForType(file_types::TY_SwiftDeps);
@@ -441,8 +440,9 @@ namespace driver {
bool wasCascading = DepGraph.isMarked(FinishedCmd);
if (wasCascading && Comp.getShowIncrementalBuildDecisions())
llvm::outs() << "HERE cascading: " << LogJob(FinishedCmd) << "\n";
const driver::Job *HERE = (const driver::Job*)FinishedCmd;
StringRef HERE1 = llvm::sys::path::filename(HERE->getOutput().getBaseInput(0));
const driver::Job *HERE = (const driver::Job *)FinishedCmd;
StringRef HERE1 =
llvm::sys::path::filename(HERE->getOutput().getBaseInput(0));
if (HERE1 == "Calendars.swift")
llvm::errs() << "HERE10\n";

View File

@@ -311,27 +311,28 @@ void DependencyGraphImpl::markExternal(SmallVectorImpl<const void *> &visited,
}
}
//HERE
// HERE
#include "swift/Driver/Job.h"
#include "llvm/Support/Path.h"
#include "llvm/Option/Arg.h"
#include "llvm/Support/Path.h"
void
DependencyGraphImpl::markTransitive(SmallVectorImpl<const void *> &visited,
const void *node, MarkTracerImpl *tracer) {
const driver::Job *HERE = (const driver::Job*)node;
StringRef HERE1 = llvm::sys::path::filename(HERE->getOutput().getBaseInput(0));
const driver::Job *HERE = (const driver::Job *)node;
StringRef HERE1 =
llvm::sys::path::filename(HERE->getOutput().getBaseInput(0));
if (HERE1 == "Calendars.swift")
llvm::errs() << "HERE2\n";
const driver::InputAction *IA = dyn_cast<driver::InputAction>(HERE->getSource().getInputs().front());
const driver::InputAction *IA =
dyn_cast<driver::InputAction>(HERE->getSource().getInputs().front());
auto HERE2 = llvm::sys::path::filename(IA->getInputArg().getValue());
if (HERE2 == "Calendars.swift")
llvm::errs() << "HERE3\n";
// StringRef HERE3 = HERE->getInputs().front()->getOutput().getPrimaryOutputFilenames().front();
// if (HERE3 == "Calendars.swift")
// llvm::errs() << "HERE3\n";
// StringRef HERE3 =
// HERE->getInputs().front()->getOutput().getPrimaryOutputFilenames().front();
// if (HERE3 == "Calendars.swift")
// llvm::errs() << "HERE3\n";
assert(Provides.count(node) && "node is not in the graph");
llvm::SpecificBumpPtrAllocator<MarkTracerImpl::Entry> scratchAlloc;

View File

@@ -79,7 +79,8 @@ bool ModuleDepGraph::isMarked(const Job *cmd) const {
return cascadingJobs.count(getSwiftDeps(cmd));
}
void ModuleDepGraph::markTransitive(SmallVectorImpl<const Job *> &consequentJobsToRecompile,
void ModuleDepGraph::markTransitive(
SmallVectorImpl<const Job *> &consequentJobsToRecompile,
const Job *jobToBeRecompiled, const void *ignored) {
FrontendStatsTracer tracer(stats, "experimental-dependencies-markTransitive");
@@ -88,13 +89,15 @@ void ModuleDepGraph::markTransitive(SmallVectorImpl<const Job *> &consequentJobs
// Do the traversal.
for (auto &fileAndNode : nodeMap[swiftDepsToBeRecompiled]) {
assert(isCurrentPathForTracingEmpty());
findDependentNodesAndRecordCascadingOnes(dependentNodes, fileAndNode.second);
findDependentNodesAndRecordCascadingOnes(dependentNodes,
fileAndNode.second);
}
computeUniqueJobsFromNodes(consequentJobsToRecompile, dependentNodes);
}
void ModuleDepGraph::computeUniqueJobsFromNodes(SmallVectorImpl<const Job *> &jobs,
void ModuleDepGraph::computeUniqueJobsFromNodes(
SmallVectorImpl<const Job *> &jobs,
const std::unordered_set<const ModuleDepGraphNode *> &nodes) {
std::unordered_set<std::string> swiftDepsOfNodes;
for (const ModuleDepGraphNode *n : nodes) {
@@ -109,7 +112,6 @@ void ModuleDepGraph::computeUniqueJobsFromNodes(SmallVectorImpl<const Job *> &jo
}
}
bool ModuleDepGraph::markIntransitive(const Job *node) {
return rememberThatJobCascades(getSwiftDeps(node));
}
@@ -162,11 +164,11 @@ LoadResult ModuleDepGraph::integrate(const SourceFileDepGraph &g) {
g.forEachNode([&](const SourceFileDepGraphNode *integrand) {
const auto &key = integrand->getKey();
auto preexistingMatch = findPreexistingMatch(swiftDeps, integrand);
if (preexistingMatch.hasValue() && preexistingMatch.getValue().first == LocationOfPreexistingNode::here)
if (preexistingMatch.hasValue() &&
preexistingMatch.getValue().first == LocationOfPreexistingNode::here)
disappearedNodes.erase(key); // Node was and still is. Do not erase it.
const bool changed = integrateSourceFileDepGraphNode(g,
integrand,
preexistingMatch);
const bool changed =
integrateSourceFileDepGraphNode(g, integrand, preexistingMatch);
if (changed)
changedNodes.insert(key);
});
@@ -182,30 +184,32 @@ LoadResult ModuleDepGraph::integrate(const SourceFileDepGraph &g) {
: LoadResult::AffectsDownstream;
}
ModuleDepGraph::PreexistingNodeIfAny
ModuleDepGraph::findPreexistingMatch(
ModuleDepGraph::PreexistingNodeIfAny ModuleDepGraph::findPreexistingMatch(
StringRef swiftDepsOfCompilationToBeIntegrated,
const SourceFileDepGraphNode *integrand) {
const auto &matches = nodeMap[integrand->getKey()];
const auto &expatsIter = matches.find("");
if (expatsIter != matches.end()) {
assert(matches.size() == 1 && "If an expat exists, then must not be any matches in other files");
return std::make_pair(LocationOfPreexistingNode::nowhere, expatsIter->second);
assert(matches.size() == 1 &&
"If an expat exists, then must not be any matches in other files");
return std::make_pair(LocationOfPreexistingNode::nowhere,
expatsIter->second);
}
if (integrand->getIsProvides()) {
const auto &preexistingNodeInPlaceIter = matches.find(swiftDepsOfCompilationToBeIntegrated);
const auto &preexistingNodeInPlaceIter =
matches.find(swiftDepsOfCompilationToBeIntegrated);
if (preexistingNodeInPlaceIter != matches.end())
return std::make_pair(LocationOfPreexistingNode::here, preexistingNodeInPlaceIter->second);
return std::make_pair(LocationOfPreexistingNode::here,
preexistingNodeInPlaceIter->second);
}
if (!matches.empty())
return std::make_pair(LocationOfPreexistingNode::elsewhere, matches.begin()->second);
return std::make_pair(LocationOfPreexistingNode::elsewhere,
matches.begin()->second);
return None;
}
bool ModuleDepGraph::integrateSourceFileDepGraphNode(
const SourceFileDepGraph &g,
const SourceFileDepGraphNode *integrand,
const SourceFileDepGraph &g, const SourceFileDepGraphNode *integrand,
const PreexistingNodeIfAny preexistingMatch) {
// Track externalDependencies so Compilation can check them.
@@ -216,20 +220,21 @@ bool ModuleDepGraph::integrateSourceFileDepGraphNode(
return false; // dependency will be handled by the use node
StringRef swiftDepsOfSourceFileGraph = g.getSwiftDepsFromSourceFileProvide();
auto changedAndUseNode = integrateSourceFileDeclNode(integrand, swiftDepsOfSourceFileGraph,
preexistingMatch);
auto changedAndUseNode = integrateSourceFileDeclNode(
integrand, swiftDepsOfSourceFileGraph, preexistingMatch);
recordWhatUseDependsUpon(g, integrand, changedAndUseNode.second);
return changedAndUseNode.first;
}
std::pair<bool, ModuleDepGraphNode*> ModuleDepGraph::integrateSourceFileDeclNode(
std::pair<bool, ModuleDepGraphNode *>
ModuleDepGraph::integrateSourceFileDeclNode(
const SourceFileDepGraphNode *integrand,
StringRef swiftDepsOfSourceFileGraph,
const PreexistingNodeIfAny preexistingMatch) {
if (!preexistingMatch.hasValue()) {
auto *newNode = integrateByCreatingANewNode(integrand, swiftDepsOfSourceFileGraph.str());
auto *newNode = integrateByCreatingANewNode(
integrand, swiftDepsOfSourceFileGraph.str());
return std::make_pair(true, newNode); // New node
}
const auto where = preexistingMatch.getValue().first;
@@ -245,7 +250,8 @@ std::pair<bool, ModuleDepGraphNode*> ModuleDepGraph::integrateSourceFileDeclNode
return std::make_pair(true, match); // New Decl, assume changed
case LocationOfPreexistingNode::elsewhere:
auto *newNode = integrateByCreatingANewNode(integrand, swiftDepsOfSourceFileGraph.str());
auto *newNode = integrateByCreatingANewNode(
integrand, swiftDepsOfSourceFileGraph.str());
return std::make_pair(true, newNode); // New node;
}
llvm_unreachable("impossible");
@@ -261,7 +267,8 @@ ModuleDepGraphNode *ModuleDepGraph::integrateByCreatingANewNode(
return newNode;
}
void ModuleDepGraph::recordWhatUseDependsUpon(const SourceFileDepGraph &g,
void ModuleDepGraph::recordWhatUseDependsUpon(
const SourceFileDepGraph &g,
const SourceFileDepGraphNode *sourceFileUseNode,
ModuleDepGraphNode *moduleUseNode) {
g.forEachDefDependedUponBy(sourceFileUseNode,
@@ -359,15 +366,18 @@ size_t ModuleDepGraph::traceArrival(const ModuleDepGraphNode *visitedNode) {
return currentPath.size();
}
void ModuleDepGraph::recordDependencyPathToJob(const std::vector<const ModuleDepGraphNode *> &pathToJob, const driver::Job* dependentJob) {
dependencyPathsToJobs.insert( std::make_pair(dependentJob, pathToJob) );
void ModuleDepGraph::recordDependencyPathToJob(
const std::vector<const ModuleDepGraphNode *> &pathToJob,
const driver::Job *dependentJob) {
dependencyPathsToJobs.insert(std::make_pair(dependentJob, pathToJob));
}
void ModuleDepGraph::traceDeparture(size_t pathLengthAfterArrival) {
if (!currentPathIfTracing)
return;
auto &currentPath = currentPathIfTracing.getValue();
assert(pathLengthAfterArrival == currentPath.size() && "Path must be maintained throughout recursive visits.");
assert(pathLengthAfterArrival == currentPath.size() &&
"Path must be maintained throughout recursive visits.");
currentPath.pop_back();
}