Skip to content

Commit 314d1e1

Browse files
author
David Ungar
committed
Reorganization of SourceFileDepGraph building and mocking.
1 parent 8e8d195 commit 314d1e1

11 files changed

+1473
-1102
lines changed

include/swift/AST/FineGrainedDependencies.h

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,20 @@ template <typename KeyT, typename ValueT> class Memoizer {
9393
public:
9494
Memoizer() = default;
9595

96+
Optional<ValueT> findExisting(KeyT key) {
97+
auto iter = memos.find(key);
98+
if (iter != memos.end())
99+
return iter->second;
100+
return None;
101+
}
102+
96103
/// \p createFn must create a \ref ValueT that corresponds to the \ref KeyT
97104
/// passed into it.
98105
ValueT
99106
findExistingOrCreateIfNew(KeyT key,
100107
function_ref<ValueT(const KeyT &)> createFn) {
101-
auto iter = memos.find(key);
102-
if (iter != memos.end())
103-
return iter->second;
108+
if (auto existing = findExisting(key))
109+
return existing.getValue();
104110
ValueT v = createFn(key);
105111
(void)insert(key, v);
106112
return v;
@@ -499,10 +505,23 @@ class DependencyKey {
499505
}
500506
bool isInterface() const { return getAspect() == DeclAspect::interface; }
501507

508+
/// Create just the interface half of the keys for a provided Decl or Decl
509+
/// pair
510+
template <NodeKind kind, typename Entity>
511+
static DependencyKey createForProvidedEntityInterface(Entity);
512+
502513
/// Given some type of provided entity compute the context field of the key.
503514
template <NodeKind kind, typename Entity>
504515
static std::string computeContextForProvidedEntity(Entity);
505516

517+
DependencyKey correspondingImplementation() const {
518+
return withAspect(DeclAspect::implementation);
519+
}
520+
521+
DependencyKey withAspect(DeclAspect aspect) const {
522+
return DependencyKey(kind, aspect, context, name);
523+
}
524+
506525
/// Given some type of provided entity compute the name field of the key.
507526
template <NodeKind kind, typename Entity>
508527
static std::string computeNameForProvidedEntity(Entity);
@@ -514,7 +533,8 @@ class DependencyKey {
514533
template <NodeKind kind>
515534
static DependencyKey createDependedUponKey(StringRef);
516535

517-
static DependencyKey createKeyForWholeSourceFile(StringRef swiftDeps);
536+
static DependencyKey createKeyForWholeSourceFile(DeclAspect,
537+
StringRef swiftDeps);
518538

519539
std::string humanReadableName() const;
520540

@@ -616,6 +636,10 @@ class DepGraphNode {
616636
/// See SourceFileDepGraphNode::SourceFileDepGraphNode(...) and
617637
/// ModuleDepGraphNode::ModuleDepGraphNode(...) Don't set swiftDeps on
618638
/// creation because this field can change if a node is moved.
639+
DepGraphNode(DependencyKey key, Optional<StringRef> fingerprint)
640+
: DepGraphNode(key, fingerprint ? fingerprint->str()
641+
: Optional<std::string>()) {}
642+
619643
DepGraphNode(DependencyKey key, Optional<std::string> fingerprint)
620644
: key(key), fingerprint(fingerprint) {}
621645
DepGraphNode(const DepGraphNode &other) = default;
@@ -627,8 +651,12 @@ class DepGraphNode {
627651

628652
const DependencyKey &getKey() const { return key; }
629653

630-
const Optional<std::string> &getFingerprint() const { return fingerprint; }
631-
654+
const Optional<StringRef> getFingerprint() const {
655+
if (fingerprint) {
656+
return StringRef(fingerprint.getValue());
657+
}
658+
return None;
659+
}
632660
/// When driver reads a SourceFileDepGraphNode, it may be a node that was
633661
/// created to represent a name-lookup (a.k.a a "depend") in the frontend. In
634662
/// that case, the node represents an entity that resides in some other file
@@ -637,7 +665,9 @@ class DepGraphNode {
637665
/// (someday) have a fingerprint. In order to preserve the
638666
/// ModuleDepGraphNode's identity but bring its fingerprint up to date, it
639667
/// needs to set the fingerprint *after* the node has been created.
640-
void setFingerprint(Optional<std::string> fp) { fingerprint = fp; }
668+
void setFingerprint(Optional<StringRef> fp) {
669+
fingerprint = fp ? fp->str() : Optional<std::string>();
670+
}
641671

642672
SWIFT_DEBUG_DUMP;
643673
void dump(llvm::raw_ostream &os) const;
@@ -684,7 +714,7 @@ class SourceFileDepGraphNode : public DepGraphNode {
684714
SourceFileDepGraphNode() : DepGraphNode(), sequenceNumber(~0) {}
685715

686716
/// Used by the frontend to build nodes.
687-
SourceFileDepGraphNode(DependencyKey key, Optional<std::string> fingerprint,
717+
SourceFileDepGraphNode(DependencyKey key, Optional<StringRef> fingerprint,
688718
bool isProvides)
689719
: DepGraphNode(key, fingerprint), isProvides(isProvides) {
690720
assert(key.verify());
@@ -780,34 +810,6 @@ class SourceFileDepGraph {
780810
SourceFileDepGraph(const SourceFileDepGraph &g) = delete;
781811
SourceFileDepGraph(SourceFileDepGraph &&g) = default;
782812

783-
/// Simulate loading for unit testing:
784-
/// \param swiftDepsFileName The name of the swiftdeps file of the phony job
785-
/// \param includePrivateDeps Whether the graph includes intra-file arcs
786-
/// \param hadCompilationError Simulate a compilation error
787-
/// \param interfaceHash The interface hash of the simulated graph
788-
/// \param simpleNamesByRDK A map of vectors of names keyed by reference
789-
/// dependency key \param compoundNamesByRDK A map of (mangledHolder,
790-
/// baseName) pairs keyed by reference dependency key. For single-name
791-
/// dependencies, an initial underscore indicates that the name does not
792-
/// cascade. For compound names, it is the first name, the holder which
793-
/// indicates non-cascading. For member names, an initial underscore indicates
794-
/// file-privacy.
795-
static SourceFileDepGraph
796-
simulateLoad(std::string swiftDepsFileName, const bool includePrivateDeps,
797-
const bool hadCompilationError, std::string interfaceHash,
798-
llvm::StringMap<std::vector<std::string>> simpleNamesByRDK,
799-
llvm::StringMap<std::vector<std::pair<std::string, std::string>>>
800-
compoundNamesByRDK);
801-
802-
static constexpr char noncascadingOrPrivatePrefix = '#';
803-
static constexpr char nameFingerprintSeparator = ',';
804-
805-
static std::string noncascading(std::string name);
806-
807-
LLVM_ATTRIBUTE_UNUSED
808-
static std::string privatize(std::string name);
809-
810-
811813
/// Nodes are owned by the graph.
812814
~SourceFileDepGraph() {
813815
forEachNode([&](SourceFileDepGraphNode *n) { delete n; });
@@ -851,12 +853,15 @@ class SourceFileDepGraph {
851853
/// The frontend creates a pair of nodes for every tracked Decl and the source
852854
/// file itself.
853855
InterfaceAndImplementationPair<SourceFileDepGraphNode>
854-
findExistingNodePairOrCreateAndAddIfNew(
855-
NodeKind k, const ContextNameFingerprint &contextNameFingerprint);
856+
findExistingNodePairOrCreateAndAddIfNew(const DependencyKey &interfaceKey,
857+
Optional<StringRef> fingerprint);
858+
859+
NullablePtr<SourceFileDepGraphNode>
860+
findExistingNode(const DependencyKey &key);
856861

857862
SourceFileDepGraphNode *
858-
findExistingNodeOrCreateIfNew(DependencyKey key,
859-
const Optional<std::string> &fingerprint,
863+
findExistingNodeOrCreateIfNew(const DependencyKey &key,
864+
const Optional<StringRef> fingerprint,
860865
bool isProvides);
861866

862867
/// \p Use is the Node that must be rebuilt when \p def changes.
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
//===----- SourceFileDepGraphConstructor.h ----------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_AST_SOURCE_FILE_DEP_GRAPH_CONSTRUCTOR_H
14+
#define SWIFT_AST_SOURCE_FILE_DEP_GRAPH_CONSTRUCTOR_H
15+
16+
#include <swift/AST/DeclContext.h>
17+
18+
namespace swift {
19+
namespace fine_grained_dependencies {
20+
/// Reads the information provided by the frontend and builds the
21+
/// SourceFileDepGraph
22+
class SourceFileDepGraphConstructor {
23+
/// To match the existing system, set this to false.
24+
/// To include even private entities and get intra-file info, set to true.
25+
const bool includePrivateDeps;
26+
27+
/// If there was an error, cannot get accurate info.
28+
const bool hadCompilationError;
29+
30+
public:
31+
/// A lambda which invokes its parameter for every unconstrained \c Decl used
32+
/// in the source file, passing in the base name, and whether this use
33+
/// cascades..
34+
using ForEachUnconstrainedDeclUsed =
35+
function_ref<void(function_ref<void(StringRef, bool)>)>;
36+
37+
/// A lambda which invokes its parameter for every constrained \c Decl used in
38+
/// the source file, passing in the manged type name of the holder, the member
39+
/// base name, whether the holder is private to its source file, and whether
40+
/// the use cascades. If the baseName is empty, this entry will be a \c
41+
/// potentialMember dependency.
42+
using ForEachConstrainedDeclUsed =
43+
function_ref<void(function_ref<void(StringRef, StringRef, bool, bool)>)>;
44+
45+
/// Adds nodes to the graph corresponding to a defined \c Decl.
46+
/// Parameters are an interface key (implementation node will also be added)
47+
/// and the fingerprint if any.
48+
using AddDefinedDecl =
49+
function_ref<void(const DependencyKey &, Optional<StringRef>)>;
50+
51+
/// A lambda which invokes its parameter for every mock \c Decl "defined" in
52+
/// the source file, passing in to its argument the \c NodeKind, \c context,
53+
/// and \c name fields of resulting \c DependencyKey pair, and also the
54+
/// fingerprint (if present) of the resulting node pair.
55+
using ForEachDefinedDecl = function_ref<void(AddDefinedDecl)>;
56+
57+
/// A lambda which invokes its parameter for every use of a \c Decl in the
58+
/// source file, passing in to its argument the \c DependencyKey used, and the
59+
/// \c DependencyKey doing the using. (A.k.a. a "def" and an a "use".
60+
using ForEachUsedDecl = function_ref<void(
61+
function_ref<void(const DependencyKey &, const DependencyKey &)>)>;
62+
63+
private:
64+
/// Graph under construction
65+
SourceFileDepGraph g;
66+
67+
public:
68+
/// Expose this layer to enable faking up a constructor for testing.
69+
/// See the instance variable comments for explanation.
70+
// clang-format off
71+
SourceFileDepGraphConstructor(
72+
bool includePrivateDeps,
73+
bool hadCompilationError
74+
) :
75+
includePrivateDeps(includePrivateDeps),
76+
hadCompilationError(hadCompilationError)
77+
{} // clang-format on
78+
79+
/// Create a SourceFileDepGraph.
80+
///
81+
/// \param swiftDeps The "output path name" and \c sourceFileProvide node
82+
/// names \param interfaceHash The fingerprint for the \c sourceFileProvide
83+
/// nodes. \param forEachMockDefinedDecl Iterator for "provides", i.e.
84+
/// definitions in this file \param forEachMockUsedDecl Iterator for
85+
/// "depends", i.e. used definitions in this file
86+
SourceFileDepGraph construct(StringRef swiftDeps, StringRef interfaceHash,
87+
ForEachDefinedDecl forEachDefinedDecl,
88+
ForEachUsedDecl forEachUsedDecl) {
89+
90+
return addSourceFileNodesAndThen(swiftDeps, interfaceHash, [&] {
91+
addAllDefinedDecls(forEachDefinedDecl);
92+
addAllUsedDecls(forEachUsedDecl);
93+
});
94+
}
95+
96+
/// Centralize the invariant that the fingerprint of the whole file is the
97+
/// interface hash
98+
static std::string getFingerprint(SourceFile *SF);
99+
100+
void enumerateDefinedDecls(SourceFile *SF, AddDefinedDecl addDefinedDeclFn);
101+
102+
private:
103+
/// Add the first two nodes in the graph and then, if there is no compilation
104+
/// error, do rest of the work to build the graph.
105+
SourceFileDepGraph addSourceFileNodesAndThen(StringRef name,
106+
StringRef fingerprint,
107+
function_ref<void()> doTheRest);
108+
109+
/// Add the "provides" nodes when mocking up a graph
110+
void addAllDefinedDecls(ForEachDefinedDecl forEachDefinedDecl);
111+
112+
/// Add the "depends" nodes and arcs when mocking a graph
113+
void addAllUsedDecls(ForEachUsedDecl forEachUsedDecl);
114+
115+
/// At present, only nominals, protocols, and extensions have (body)
116+
/// fingerprints
117+
static Optional<std::string>
118+
getFingerprintIfAny(std::pair<const NominalTypeDecl *, const ValueDecl *>);
119+
120+
static Optional<std::string> getFingerprintIfAny(const Decl *d);
121+
122+
static std::string getInterfaceHash(SourceFile *SF);
123+
124+
void addSourceFileNodesToGraph(StringRef swiftDeps, StringRef fingerprint);
125+
126+
/// Given an array of Decls or pairs of them in \p declsOrPairs
127+
/// create node pairs for context and name
128+
template <NodeKind kind, typename ContentsT>
129+
void
130+
enumerateAllProviderNodesOfAGivenType(std::vector<ContentsT> &contentsVec,
131+
AddDefinedDecl addDefinedDeclFn);
132+
133+
/// Add an pair of interface, implementation nodes to the graph, which
134+
/// represent some \c Decl defined in this source file. \param key the
135+
/// interface key of the pair
136+
void addDefinedDecl(const DependencyKey &key,
137+
Optional<StringRef> fingerprint);
138+
};
139+
140+
} // namespace fine_grained_dependencies
141+
} // namespace swift
142+
143+
#endif // SWIFT_AST_SOURCE_FILE_DEP_GRAPH_CONSTRUCTOR_H

include/swift/Driver/FineGrainedDependencyDriverGraph.h

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ class ModuleDepGraphNode : public DepGraphNode {
5757
bool hasBeenTracedAsADependent = false;
5858

5959
public:
60-
ModuleDepGraphNode(const DependencyKey &key,
61-
Optional<std::string> fingerprint,
60+
ModuleDepGraphNode(const DependencyKey &key, Optional<StringRef> fingerprint,
6261
Optional<std::string> swiftDeps)
6362
: DepGraphNode(key, fingerprint), swiftDeps(swiftDeps) {}
6463

@@ -187,11 +186,13 @@ class ModuleDepGraph {
187186
/// files for the same name distinct, keep a sequence number for each name.
188187
std::unordered_map<std::string, unsigned> dotFileSequenceNumber;
189188

189+
public:
190190
const bool verifyFineGrainedDependencyGraphAfterEveryImport;
191191
const bool emitFineGrainedDependencyDotFileAfterEveryImport;
192192

193193
const bool EnableTypeFingerprints;
194194

195+
private:
195196
/// If tracing dependencies, holds a vector used to hold the current path
196197
/// def - use/def - use/def - ...
197198
Optional<std::vector<const ModuleDepGraphNode *>> currentPathIfTracing;
@@ -336,15 +337,6 @@ class ModuleDepGraph {
336337
const SourceFileDepGraph &,
337338
DiagnosticEngine &);
338339

339-
/// Also for unit tests
340-
Changes
341-
simulateLoad(const driver::Job *cmd,
342-
llvm::StringMap<std::vector<std::string>> simpleNames,
343-
llvm::StringMap<std::vector<std::pair<std::string, std::string>>>
344-
compoundNames = {},
345-
const bool includePrivateDeps = false,
346-
const bool hadCompilationError = false);
347-
348340

349341
private:
350342
/// Read a SourceFileDepGraph belonging to \p job from \p buffer
@@ -515,6 +507,8 @@ class ModuleDepGraph {
515507
/// Record a new (to this graph) Job.
516508
void registerJob(const driver::Job *);
517509

510+
std::vector<const driver::Job *> getAllJobs() const;
511+
518512
/// Find jobs that were previously not known to need compilation but that
519513
/// depend on \c externalDependency.
520514
std::vector<const driver::Job *>

0 commit comments

Comments
 (0)