Skip to content

Commit a2df6b9

Browse files
author
David Ungar
authored
Merge pull request swiftlang#29463 from davidungar/PBP-2-21-ICNR-on
[DNM, Incremental: Type-body-fingerprints on-by-default]
2 parents 8b249e7 + 4510c2f commit a2df6b9

File tree

66 files changed

+2416
-1273
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2416
-1273
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ SWIFT_TYPEID_NAMED(SourceFile *, SourceFile)
5353
SWIFT_TYPEID_NAMED(TypeAliasDecl *, TypeAliasDecl)
5454
SWIFT_TYPEID_NAMED(ValueDecl *, ValueDecl)
5555
SWIFT_TYPEID_NAMED(VarDecl *, VarDecl)
56+
SWIFT_TYPEID(FingerprintAndMembers)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct TypePair;
6161
struct TypeWitnessAndDecl;
6262
enum class AncestryFlags : uint8_t;
6363
enum class ImplicitMemberAction : uint8_t;
64+
struct FingerprintAndMembers;
6465

6566
// Define the AST type zone (zone 1)
6667
#define SWIFT_TYPEID_ZONE AST

include/swift/AST/DeclContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,12 @@ class IterableDeclContext {
802802
// Some Decls are IterableDeclContexts, but not all.
803803
static bool classof(const Decl *D);
804804

805+
/// Return a hash of all tokens in the body for dependency analysis, if
806+
/// available.
807+
Optional<std::string> getBodyFingerprint() const;
808+
809+
bool areDependenciesUsingTokenHashesForTypeBodies() const;
810+
805811
private:
806812
/// Add a member to the list for iteration purposes, but do not notify the
807813
/// subclass that we have done so.

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ ERROR(error_unknown_arg,none,
9494
"unknown argument: '%0'", (StringRef))
9595
ERROR(error_invalid_arg_value,none,
9696
"invalid value '%1' in '%0'", (StringRef, StringRef))
97+
WARNING(warning_type_fingerprints_require_fine_grained_dependencies,none,
98+
"Type fingerprints require fine-grained dependencies", ())
9799
WARNING(warning_cannot_multithread_batch_mode,none,
98100
"ignoring -num-threads argument; cannot multithread batch mode", ())
99101
ERROR(error_unsupported_option_argument,none,

include/swift/AST/FineGrainedDependencies.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "swift/Basic/Debug.h"
1717
#include "swift/Basic/LLVM.h"
18+
#include "swift/Basic/NullablePtr.h"
1819
#include "swift/Basic/Range.h"
1920
#include "llvm/ADT/Hashing.h"
2021
#include "llvm/Support/MD5.h"
@@ -139,6 +140,11 @@ template <typename Key1, typename Key2, typename Value> class TwoStageMap {
139140
return iter2 == iter->second.end() ? None : Optional<Value>(iter2->second);
140141
}
141142

143+
NullablePtr<const InnerMap> find(const Key1 &k1) const {
144+
auto iter = map.find(k1);
145+
return iter == map.end() ? nullptr : &iter->second;
146+
}
147+
142148
/// The sought value must be present.
143149
Value findAndErase(const Key1 &k1, const Key2 &k2) {
144150
auto &submap = map[k1];
@@ -237,6 +243,20 @@ class BiIndexedTwoStageMap {
237243
}
238244
Optional<Value> find(const Key2 &k2, Key1 &k1) const { return find(k1, k2); }
239245

246+
/// Return the submap for a given Key1. May create one, after the fashion of
247+
/// the standard libary.
248+
const Key2Map &operator[](const Key1 &k1) { return map1[k1]; }
249+
/// Return the submap for a given Key2. May create one, after the fashion of
250+
/// the standard libary.
251+
const Key1Map &operator[](const Key2 &k2) { return map2[k2]; }
252+
253+
NullablePtr<const Key2Map> find(const Key1 &k1) const {
254+
return map1.find(k1);
255+
}
256+
NullablePtr<const Key1Map> find(const Key2 &k2) const {
257+
return map2.find(k2);
258+
}
259+
240260
/// Element must be present.
241261
/// Return the erased value.
242262
Value findAndErase(const Key1 &k1, const Key2 &k2) {
@@ -250,12 +270,6 @@ class BiIndexedTwoStageMap {
250270
Value findAndErase(const Key2 &k2, const Key1 &k1) {
251271
return findAndErase(k1, k2);
252272
}
253-
/// Return the submap for a given Key1. May create one, after the fashion of
254-
/// the standard libary.
255-
const Key2Map &operator[](const Key1 &k1) { return map1[k1]; }
256-
/// Return the submap for a given Key2. May create one, after the fashion of
257-
/// the standard libary.
258-
const Key1Map &operator[](const Key2 &k2) { return map2[k2]; }
259273

260274
/// Invoke \p fn on each Key2 and Value matching (\p k1, *)
261275
void forEachValueMatching(
@@ -500,8 +514,7 @@ class DependencyKey {
500514
template <NodeKind kind>
501515
static DependencyKey createDependedUponKey(StringRef);
502516

503-
static DependencyKey
504-
createTransitiveKeyForWholeSourceFile(StringRef swiftDeps);
517+
static DependencyKey createKeyForWholeSourceFile(StringRef swiftDeps);
505518

506519
std::string humanReadableName() const;
507520

@@ -787,6 +800,12 @@ class SourceFileDepGraph {
787800

788801
static constexpr char noncascadingOrPrivatePrefix = '#';
789802

803+
static std::string noncascading(std::string name);
804+
805+
LLVM_ATTRIBUTE_UNUSED
806+
static std::string privatize(std::string name);
807+
808+
790809
/// Nodes are owned by the graph.
791810
~SourceFileDepGraph() {
792811
forEachNode([&](SourceFileDepGraphNode *n) { delete n; });

include/swift/AST/ParseRequests.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,31 @@ template<typename Request>
2727
void reportEvaluatedRequest(UnifiedStatsReporter &stats,
2828
const Request &request);
2929

30+
struct FingerprintAndMembers {
31+
Optional<std::string> fingerprint = None;
32+
ArrayRef<Decl *> members = {};
33+
bool operator==(const FingerprintAndMembers &x) const {
34+
return fingerprint == x.fingerprint && members == x.members;
35+
}
36+
};
37+
38+
void simple_display(llvm::raw_ostream &out, const FingerprintAndMembers &value);
39+
3040
/// Parse the members of a nominal type declaration or extension.
31-
class ParseMembersRequest :
32-
public SimpleRequest<ParseMembersRequest,
33-
ArrayRef<Decl *>(IterableDeclContext *),
34-
CacheKind::Cached>
35-
{
41+
/// Return a fingerprint and the members.
42+
class ParseMembersRequest
43+
: public SimpleRequest<ParseMembersRequest,
44+
FingerprintAndMembers(IterableDeclContext *),
45+
CacheKind::Cached> {
3646
public:
3747
using SimpleRequest::SimpleRequest;
3848

3949
private:
4050
friend SimpleRequest;
4151

4252
// Evaluation.
43-
ArrayRef<Decl *> evaluate(Evaluator &evaluator,
44-
IterableDeclContext *idc) const;
53+
FingerprintAndMembers evaluate(Evaluator &evaluator,
54+
IterableDeclContext *idc) const;
4555

4656
public:
4757
// Caching

include/swift/AST/ParseTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
SWIFT_REQUEST(Parse, ParseMembersRequest,
18-
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
18+
FingerprintAndMembers(IterableDeclContext *), Cached, NoLocationInfo)
1919
SWIFT_REQUEST(Parse, ParseAbstractFunctionBodyRequest,
2020
BraceStmt *(AbstractFunctionDecl *), SeparatelyCached,
2121
NoLocationInfo)

include/swift/AST/SourceFile.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -423,12 +423,8 @@ class SourceFile final : public FileUnit {
423423
return InterfaceHash.hasValue();
424424
}
425425

426-
void recordInterfaceToken(StringRef token) {
427-
assert(!token.empty());
428-
InterfaceHash->update(token);
429-
// Add null byte to separate tokens.
430-
uint8_t a[1] = {0};
431-
InterfaceHash->update(a);
426+
NullablePtr<llvm::MD5> getInterfaceHashPtr() {
427+
return InterfaceHash ? InterfaceHash.getPointer() : nullptr;
432428
}
433429

434430
void getInterfaceHash(llvm::SmallString<32> &str) const {

include/swift/Basic/LangOptions.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,14 @@ namespace swift {
298298

299299
/// Emit the newer, finer-grained swiftdeps file. Eventually will support
300300
/// faster rebuilds.
301-
/// The initializer here sets the default for the frontend and driver.
302301
bool EnableFineGrainedDependencies = true;
303302

303+
/// Instead of hashing tokens inside of NominalType and ExtensionBodies into
304+
/// the interface hash, hash them into per-iterable-decl-context
305+
/// fingerprints. Fine-grained dependency types won't dirty every provides
306+
/// in a file when the user adds a member to, e.g., a struct.
307+
bool EnableTypeFingerprints = true;
308+
304309
/// When using fine-grained dependencies, emit dot files for every swiftdeps
305310
/// file.
306311
bool EmitFineGrainedDependencySourcefileDotFiles = false;

include/swift/Basic/Statistic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class SourceFile;
6969
class SourceManager;
7070
class Stmt;
7171
class TypeRepr;
72+
struct FingerprintAndMembers;
7273

7374
// There are a handful of cases where the swift compiler can introduce
7475
// counter-measurement noise via nondeterminism, especially via

include/swift/Driver/Action.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -173,17 +173,20 @@ class CompileJobAction : public JobAction {
173173
/// if 0 or >1 such inputs exist, return nullptr.
174174
const InputAction *findSingleSwiftInput() const {
175175
auto Inputs = getInputs();
176-
auto isSwiftInput = [](const Action *A) -> const InputAction* {
177-
if (auto const *S = dyn_cast<InputAction>(A))
178-
return S->getType() == file_types::TY_Swift ? S : nullptr;
179-
return nullptr;
180-
};
181-
const auto loc1 = std::find_if(Inputs.begin(), Inputs.end(), isSwiftInput);
182-
if (loc1 == Inputs.end())
183-
return nullptr; // none found
184-
// Ensure uniqueness
185-
const auto loc2 = std::find_if(loc1 + 1, Inputs.end(), isSwiftInput);
186-
return loc2 == Inputs.end() ? dyn_cast<InputAction>(*loc1) : nullptr;
176+
const InputAction *IA = nullptr;
177+
for (auto const *I : Inputs) {
178+
if (auto const *S = dyn_cast<InputAction>(I)) {
179+
if (S->getType() == file_types::TY_Swift) {
180+
if (IA == nullptr) {
181+
IA = S;
182+
} else {
183+
// Already found one, two is too many.
184+
return nullptr;
185+
}
186+
}
187+
}
188+
}
189+
return IA;
187190
}
188191
};
189192

include/swift/Driver/CoarseGrainedDependencyGraph.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class CoarseGrainedDependencyGraphImpl {
150150
LoadResult loadFromString(const void *node, StringRef data);
151151
LoadResult loadFromPath(const void *node, StringRef path);
152152

153-
void addIndependentNode(const void *node) {
153+
void registerJob(const void *node) {
154154
bool newlyInserted = Provides.insert({node, {}}).second;
155155
assert(newlyInserted && "node is already in graph");
156156
(void)newlyInserted;
@@ -260,8 +260,8 @@ class CoarseGrainedDependencyGraph : public CoarseGrainedDependencyGraphImpl {
260260
/// Adds \p node to the dependency graph without any connections.
261261
///
262262
/// This can be used for new nodes that may be updated later.
263-
void addIndependentNode(T node) {
264-
return CoarseGrainedDependencyGraphImpl::addIndependentNode(
263+
void registerJob(T node) {
264+
return CoarseGrainedDependencyGraphImpl::registerJob(
265265
Traits::getAsVoidPointer(node));
266266
}
267267

include/swift/Driver/Compilation.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,17 @@ class Compilation {
279279
/// faster rebuilds.
280280
const bool EnableFineGrainedDependencies;
281281

282+
/// Is the parser recording token hashes for each type body?
283+
const bool EnableTypeFingerprints;
284+
282285
/// Helpful for debugging, but slows down the driver. So, only turn on when
283286
/// needed.
284287
const bool VerifyFineGrainedDependencyGraphAfterEveryImport;
285288
/// Helpful for debugging, but slows down the driver. So, only turn on when
286289
/// needed.
287290
const bool EmitFineGrainedDependencyDotFileAfterEveryImport;
288291

289-
/// Experiment with inter-file dependencies
292+
/// Experiment with intrafile dependencies
290293
const bool FineGrainedDependenciesIncludeIntrafileOnes;
291294

292295
/// Experiment with source-range-based dependencies
@@ -328,8 +331,10 @@ class Compilation {
328331
bool ShowDriverTimeCompilation = false,
329332
std::unique_ptr<UnifiedStatsReporter> Stats = nullptr,
330333
bool OnlyOneDependencyFile = false,
331-
bool EnableFineGrainedDependencies =
332-
LangOptions().EnableFineGrainedDependencies,
334+
bool EnableFineGrainedDependencies
335+
= LangOptions().EnableFineGrainedDependencies,
336+
bool EnableTypeFingerprints =
337+
LangOptions().EnableTypeFingerprints,
333338
bool VerifyFineGrainedDependencyGraphAfterEveryImport = false,
334339
bool EmitFineGrainedDependencyDotFileAfterEveryImport = false,
335340
bool FineGrainedDependenciesIncludeIntrafileOnes = false,
@@ -398,6 +403,8 @@ class Compilation {
398403
return EnableFineGrainedDependencies;
399404
}
400405

406+
bool getEnableTypeFingerprints() const { return EnableTypeFingerprints; }
407+
401408
bool getVerifyFineGrainedDependencyGraphAfterEveryImport() const {
402409
return VerifyFineGrainedDependencyGraphAfterEveryImport;
403410
}

0 commit comments

Comments
 (0)