diff --git a/include/swift/AST/FineGrainedDependencies.h b/include/swift/AST/FineGrainedDependencies.h index 50cba234d0e46..49f0b755f9e39 100644 --- a/include/swift/AST/FineGrainedDependencies.h +++ b/include/swift/AST/FineGrainedDependencies.h @@ -799,6 +799,7 @@ class SourceFileDepGraph { compoundNamesByRDK); static constexpr char noncascadingOrPrivatePrefix = '#'; + static constexpr char nameFingerprintSeparator = ','; static std::string noncascading(std::string name); diff --git a/include/swift/Driver/FineGrainedDependencyDriverGraph.h b/include/swift/Driver/FineGrainedDependencyDriverGraph.h index af7b2f5116c06..9d1e9954d2c15 100644 --- a/include/swift/Driver/FineGrainedDependencyDriverGraph.h +++ b/include/swift/Driver/FineGrainedDependencyDriverGraph.h @@ -437,7 +437,7 @@ class ModuleDepGraph { /// Call \p fn for each node whose key matches \p key. void forEachMatchingNode(const DependencyKey &key, - function_ref) const; + function_ref) const; void forEachNodeInJob(StringRef swiftDeps, function_ref) const; diff --git a/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp b/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp index a2cb94342861f..eba5fe33192bb 100644 --- a/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp +++ b/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp @@ -848,12 +848,29 @@ bool swift::fine_grained_dependencies::emitReferenceDependencies( static StringRef stripPrefix(const StringRef name) { return name.ltrim(SourceFileDepGraph::noncascadingOrPrivatePrefix); } +static StringRef stripFingerprint(const StringRef nameAndFingerprint) { + return nameAndFingerprint.split(SourceFileDepGraph::nameFingerprintSeparator) + .first; +} +static StringRef stripName(const StringRef nameAndFingerprint) { + return nameAndFingerprint.split(SourceFileDepGraph::nameFingerprintSeparator) + .second; +} +static std::string extractName(const StringRef prefixNameFingerprint) { + return stripFingerprint(stripPrefix(prefixNameFingerprint)).str(); +} +static Optional extractFingerprint( + const StringRef prefixNameFingerprint) { + const auto fp = stripName(stripPrefix(prefixNameFingerprint)); + return fp.empty() ? None : Optional(fp.str()); +} static std::vector getBaseNameProvides(ArrayRef simpleNames) { std::vector result; for (StringRef n : simpleNames) - result.push_back(ContextNameFingerprint("", stripPrefix(n).str(), None)); + result.push_back(ContextNameFingerprint("", extractName(n), + extractFingerprint(n))); return result; } @@ -861,7 +878,8 @@ static std::vector getMangledHolderProvides(ArrayRef simpleNames) { std::vector result; for (StringRef n : simpleNames) - result.push_back(ContextNameFingerprint(stripPrefix(n).str(), "", None)); + result.push_back(ContextNameFingerprint(extractName(n), "", + extractFingerprint(n))); return result; } @@ -869,12 +887,15 @@ static std::vector getCompoundProvides( ArrayRef> compoundNames) { std::vector result; for (const auto &p : compoundNames) - result.push_back(ContextNameFingerprint(stripPrefix(p.first), - stripPrefix(p.second), None)); + result.push_back(ContextNameFingerprint(extractName(p.first), + extractName(p.second), + extractFingerprint(p.second))); return result; } -static bool cascades(const std::string &s) { return s.empty() || s[0] != SourceFileDepGraph::noncascadingOrPrivatePrefix; } +static bool cascades(const std::string &s) { + return s.empty() || s[0] != SourceFileDepGraph::noncascadingOrPrivatePrefix; +} // Use '_' as a prefix for a file-private member static bool isPrivate(const std::string &s) { @@ -904,7 +925,8 @@ getCompoundDepends( // (On Linux, the compiler needs more verbosity than: // result.push_back({{n, "", false}, cascades(n)}); result.push_back( - std::make_pair(std::make_tuple(stripPrefix(n), std::string(), false), cascades(n))); + std::make_pair(std::make_tuple(stripPrefix(n), std::string(), false), + cascades(n))); } for (auto &p : compoundNames) { // Likewise, for Linux expand the following out: @@ -932,7 +954,8 @@ SourceFileDepGraph SourceFileDepGraph::simulateLoad( SourceFileDepGraphConstructor c( swiftDepsFilename, includePrivateDeps, hadCompilationError, interfaceHash, getSimpleDepends(simpleNamesByRDK[dependsTopLevel]), - getCompoundDepends(simpleNamesByRDK[dependsNominal], compoundNamesByRDK[dependsMember]), + getCompoundDepends(simpleNamesByRDK[dependsNominal], + compoundNamesByRDK[dependsMember]), getSimpleDepends(simpleNamesByRDK[dependsDynamicLookup]), getExternalDepends(simpleNamesByRDK[dependsExternal]), {}, // precedence groups diff --git a/lib/Driver/FineGrainedDependencyDriverGraph.cpp b/lib/Driver/FineGrainedDependencyDriverGraph.cpp index dd997a283f1ca..5bda1956f9b4c 100644 --- a/lib/Driver/FineGrainedDependencyDriverGraph.cpp +++ b/lib/Driver/FineGrainedDependencyDriverGraph.cpp @@ -171,6 +171,11 @@ ModuleDepGraph::findJobsToRecompileWhenNodesChange< std::unordered_set>( const std::unordered_set &); +template std::vector +ModuleDepGraph::findJobsToRecompileWhenNodesChange< + std::vector>( + const std::vector &); + std::vector ModuleDepGraph::computeSwiftDepsFromNodes( ArrayRef nodes) const { llvm::StringSet<> swiftDepsOfNodes; @@ -441,7 +446,7 @@ void ModuleDepGraph::forEachNode( void ModuleDepGraph::forEachMatchingNode( const DependencyKey &key, - function_ref fn) const { + function_ref fn) const { nodeMap.forEachValueMatching( key, [&](const std::string &, ModuleDepGraphNode *n) { fn(n); }); } diff --git a/unittests/Driver/FineGrainedDependencyGraphTests.cpp b/unittests/Driver/FineGrainedDependencyGraphTests.cpp index b8af2dddc03a7..28e8286866d9e 100644 --- a/unittests/Driver/FineGrainedDependencyGraphTests.cpp +++ b/unittests/Driver/FineGrainedDependencyGraphTests.cpp @@ -808,3 +808,19 @@ TEST(ModuleDepGraph, MutualInterfaceHash) { const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_TRUE(contains(jobs, &job1)); } + +TEST(ModuleDepGraph, DisabledTypeBodyFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); + + graph.simulateLoad(&job0, {{dependsNominal, {"B2"}}}); + graph.simulateLoad(&job1, {{providesNominal, {"B1", "B2"}}}); + graph.simulateLoad(&job2, {{dependsNominal, {"B1"}}}); + + { + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); + EXPECT_EQ(3u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + } +} diff --git a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp index ff06b0344c252..041cc9c2ee416 100644 --- a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp +++ b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp @@ -808,3 +808,24 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MutualInterfaceHash) { const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_TRUE(contains(jobs, &job1)); } + +TEST(ModuleDepGraph, EnabledTypeBodyFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); + + graph.simulateLoad(&job0, {{dependsNominal, {"B2"}}}); + graph.simulateLoad(&job1, {{providesNominal, {"B1", "B2"}}}); + graph.simulateLoad(&job2, {{dependsNominal, {"B1"}}}); + + + const DependencyKey k = DependencyKey(NodeKind::nominal, + DeclAspect::interface, "B1", ""); + std::vector changedNodes; + graph.forEachMatchingNode( + k, + [&](ModuleDepGraphNode* n) {changedNodes.push_back(n);}); + { + const auto jobs = graph.findJobsToRecompileWhenNodesChange(changedNodes); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_FALSE(contains(jobs, &job0)); + } +}