Skip to content

Commit 627df41

Browse files
authored
Merge pull request #1056 from swiftwasm/master
[pull] swiftwasm from master
2 parents 3f4d4e0 + e67e8ab commit 627df41

Some content is hidden

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

51 files changed

+842
-308
lines changed

docs/Testing.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ uses an iOS 10.3 simulator configuration named "iPhone 5" for 32-bit testing.
3838
window, or with the command line:
3939

4040
```sh
41-
xcrun simctl create 'iPhone 5' 'com.apple.CoreSimulator.SimDeviceType.iPhone-5'
41+
xcrun simctl create 'iPhone 5' com.apple.CoreSimulator.SimDeviceType.iPhone-5 com.apple.CoreSimulator.SimRuntime.iOS-10-3
4242
```
4343

4444
3. Append `--ios` to the `utils/build-script` command line (see below).

include/swift/AST/AnyRequest.h

+30-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ struct AnyRequestVTable {
6666
static SourceLoc getNearestLoc(const void *ptr) {
6767
return static_cast<const Request *>(ptr)->getNearestLoc();
6868
}
69+
static bool isCached(const void *ptr) {
70+
return static_cast<const Request *>(ptr)->isCached();
71+
}
6972
};
7073

7174
const uint64_t typeID;
@@ -78,8 +81,29 @@ struct AnyRequestVTable {
7881
const std::function<void(const void *, DiagnosticEngine &)> diagnoseCycle;
7982
const std::function<void(const void *, DiagnosticEngine &)> noteCycleStep;
8083
const std::function<SourceLoc(const void *)> getNearestLoc;
84+
const std::function<bool(const void *)> isCached;
8185

82-
template <typename Request>
86+
template <typename Request,
87+
typename std::enable_if<Request::isEverCached>::type * = nullptr>
88+
static const AnyRequestVTable *get() {
89+
static const AnyRequestVTable vtable = {
90+
TypeID<Request>::value,
91+
sizeof(Request),
92+
&Impl<Request>::copy,
93+
&Impl<Request>::getHash,
94+
&Impl<Request>::deleter,
95+
&Impl<Request>::isEqual,
96+
&Impl<Request>::simpleDisplay,
97+
&Impl<Request>::diagnoseCycle,
98+
&Impl<Request>::noteCycleStep,
99+
&Impl<Request>::getNearestLoc,
100+
&Impl<Request>::isCached,
101+
};
102+
return &vtable;
103+
}
104+
105+
template <typename Request,
106+
typename std::enable_if<!Request::isEverCached>::type * = nullptr>
83107
static const AnyRequestVTable *get() {
84108
static const AnyRequestVTable vtable = {
85109
TypeID<Request>::value,
@@ -92,6 +116,7 @@ struct AnyRequestVTable {
92116
&Impl<Request>::diagnoseCycle,
93117
&Impl<Request>::noteCycleStep,
94118
&Impl<Request>::getNearestLoc,
119+
[](auto){ return false; },
95120
};
96121
return &vtable;
97122
}
@@ -194,6 +219,10 @@ class AnyRequestBase {
194219
return getVTable()->getNearestLoc(getRawStorage());
195220
}
196221

222+
bool isCached() const {
223+
return getVTable()->isCached(getRawStorage());
224+
}
225+
197226
/// Compare two instances for equality.
198227
friend bool operator==(const AnyRequestBase<Derived> &lhs,
199228
const AnyRequestBase<Derived> &rhs) {

include/swift/AST/Evaluator.h

+14-11
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ class Evaluator {
225225
/// so all clients must cope with cycles.
226226
llvm::DenseMap<AnyRequest, std::vector<AnyRequest>> dependencies;
227227

228-
evaluator::DependencyCollector collector;
228+
evaluator::DependencyRecorder recorder;
229229

230230
/// Retrieve the request function for the given zone and request IDs.
231231
AbstractRequestFunction *getAbstractRequestFunction(uint8_t zoneID,
@@ -268,8 +268,8 @@ class Evaluator {
268268
typename std::enable_if<Request::isEverCached>::type * = nullptr>
269269
llvm::Expected<typename Request::OutputType>
270270
operator()(const Request &request) {
271-
evaluator::DependencyCollector::StackRAII<Request> incDeps{collector,
272-
request};
271+
evaluator::DependencyRecorder::StackRAII<Request> incDeps{recorder,
272+
request};
273273
// The request can be cached, but check a predicate to determine
274274
// whether this particular instance is cached. This allows more
275275
// fine-grained control over which instances get cache.
@@ -285,8 +285,8 @@ class Evaluator {
285285
typename std::enable_if<!Request::isEverCached>::type * = nullptr>
286286
llvm::Expected<typename Request::OutputType>
287287
operator()(const Request &request) {
288-
evaluator::DependencyCollector::StackRAII<Request> incDeps{collector,
289-
request};
288+
evaluator::DependencyRecorder::StackRAII<Request> incDeps{recorder,
289+
request};
290290
return getResultUncached(request);
291291
}
292292

@@ -431,19 +431,22 @@ class Evaluator {
431431
}
432432

433433
private:
434-
// Report the result of evaluating a request that is not a dependency sink -
435-
// which is to say do nothing.
436-
template <typename Request,
437-
typename std::enable_if<!Request::isDependencySink>::type * = nullptr>
434+
// Report the result of evaluating a request that is not a dependency sink.
435+
template <typename Request, typename std::enable_if<
436+
!Request::isDependencySink>::type * = nullptr>
438437
void reportEvaluatedResult(const Request &r,
439-
const typename Request::OutputType &o) {}
438+
const typename Request::OutputType &o) {
439+
recorder.replay(ActiveRequest(r));
440+
}
440441

441442
// Report the result of evaluating a request that is a dependency sink.
442443
template <typename Request,
443444
typename std::enable_if<Request::isDependencySink>::type * = nullptr>
444445
void reportEvaluatedResult(const Request &r,
445446
const typename Request::OutputType &o) {
446-
r.writeDependencySink(collector, o);
447+
return recorder.record(activeRequests, [&r, &o](auto &c) {
448+
return r.writeDependencySink(c, o);
449+
});
447450
}
448451

449452
public:

include/swift/AST/EvaluatorDependencies.h

+116-23
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#ifndef SWIFT_AST_EVALUATOR_DEPENDENCIES_H
1919
#define SWIFT_AST_EVALUATOR_DEPENDENCIES_H
2020

21+
#include "swift/AST/AnyRequest.h"
2122
#include "swift/AST/AttrKind.h"
2223
#include "swift/AST/SourceFile.h"
2324
#include "llvm/ADT/PointerIntPair.h"
@@ -106,30 +107,78 @@ inline DependencyScope getScopeForAccessLevel(AccessLevel l) {
106107
// of individual contexts.
107108
using DependencySource = llvm::PointerIntPair<SourceFile *, 1, DependencyScope>;
108109

109-
/// A \c DependencyCollector is an aggregator of named references discovered in a
110-
/// particular \c DependencyScope during the course of request evaluation.
110+
struct DependencyRecorder;
111+
111112
struct DependencyCollector {
112-
private:
113-
/// A stack of dependency sources in the order they were evaluated.
114-
llvm::SmallVector<evaluator::DependencySource, 8> dependencySources;
113+
struct Reference {
114+
public:
115+
enum class Kind {
116+
Empty,
117+
Tombstone,
118+
UsedMember,
119+
PotentialMember,
120+
TopLevel,
121+
Dynamic,
122+
} kind;
115123

116-
public:
117-
enum class Mode {
118-
// Enables the current "status quo" behavior of the dependency collector.
119-
//
120-
// By default, the dependency collector moves to register dependencies in
121-
// the referenced name trackers at the top of the active dependency stack.
122-
StatusQuo,
123-
// Enables an experimental mode to only register private dependencies.
124-
//
125-
// This mode restricts the dependency collector to ignore changes of
126-
// scope. This has practical effect of charging all unqualified lookups to
127-
// the primary file being acted upon instead of to the destination file.
128-
ExperimentalPrivateDependencies,
124+
NominalTypeDecl *subject;
125+
DeclBaseName name;
126+
127+
private:
128+
Reference(Kind kind, NominalTypeDecl *subject, DeclBaseName name)
129+
: kind(kind), subject(subject), name(name) {}
130+
131+
public:
132+
static Reference empty() {
133+
return {Kind::Empty, llvm::DenseMapInfo<NominalTypeDecl *>::getEmptyKey(),
134+
llvm::DenseMapInfo<DeclBaseName>::getEmptyKey()};
135+
}
136+
137+
static Reference tombstone() {
138+
return {Kind::Empty,
139+
llvm::DenseMapInfo<NominalTypeDecl *>::getTombstoneKey(),
140+
llvm::DenseMapInfo<DeclBaseName>::getTombstoneKey()};
141+
}
142+
143+
public:
144+
static Reference usedMember(NominalTypeDecl *subject, DeclBaseName name) {
145+
return {Kind::UsedMember, subject, name};
146+
}
147+
148+
static Reference potentialMember(NominalTypeDecl *subject) {
149+
return {Kind::PotentialMember, subject, DeclBaseName()};
150+
}
151+
152+
static Reference topLevel(DeclBaseName name) {
153+
return {Kind::TopLevel, nullptr, name};
154+
}
155+
156+
static Reference dynamic(DeclBaseName name) {
157+
return {Kind::Dynamic, nullptr, name};
158+
}
159+
160+
public:
161+
struct Info {
162+
static inline Reference getEmptyKey() { return Reference::empty(); }
163+
static inline Reference getTombstoneKey() {
164+
return Reference::tombstone();
165+
}
166+
static inline unsigned getHashValue(const Reference &Val) {
167+
return llvm::hash_combine(Val.kind, Val.subject,
168+
Val.name.getAsOpaquePointer());
169+
}
170+
static bool isEqual(const Reference &LHS, const Reference &RHS) {
171+
return LHS.kind == RHS.kind && LHS.subject == RHS.subject &&
172+
LHS.name == RHS.name;
173+
}
174+
};
129175
};
130-
Mode mode;
131176

132-
explicit DependencyCollector(Mode mode) : mode{mode} {};
177+
DependencyRecorder &parent;
178+
llvm::DenseSet<Reference, Reference::Info> scratch;
179+
180+
public:
181+
explicit DependencyCollector(DependencyRecorder &parent) : parent(parent) {}
133182

134183
public:
135184
/// Registers a named reference from the current dependency scope to a member
@@ -168,6 +217,50 @@ struct DependencyCollector {
168217
/// a name that is found by \c AnyObject lookup.
169218
void addDynamicLookupName(DeclBaseName name);
170219

220+
public:
221+
const DependencyRecorder &getRecorder() const { return parent; }
222+
bool empty() const { return scratch.empty(); }
223+
};
224+
225+
/// A \c DependencyCollector is an aggregator of named references discovered in a
226+
/// particular \c DependencyScope during the course of request evaluation.
227+
struct DependencyRecorder {
228+
friend DependencyCollector;
229+
private:
230+
/// A stack of dependency sources in the order they were evaluated.
231+
llvm::SmallVector<evaluator::DependencySource, 8> dependencySources;
232+
233+
public:
234+
enum class Mode {
235+
// Enables the current "status quo" behavior of the dependency collector.
236+
//
237+
// By default, the dependency collector moves to register dependencies in
238+
// the referenced name trackers at the top of the active dependency stack.
239+
StatusQuo,
240+
// Enables an experimental mode to only register private dependencies.
241+
//
242+
// This mode restricts the dependency collector to ignore changes of
243+
// scope. This has practical effect of charging all unqualified lookups to
244+
// the primary file being acted upon instead of to the destination file.
245+
ExperimentalPrivateDependencies,
246+
};
247+
Mode mode;
248+
llvm::DenseMap<AnyRequest, llvm::DenseSet<DependencyCollector::Reference,
249+
DependencyCollector::Reference::Info>>
250+
requestReferences;
251+
bool isRecording;
252+
253+
explicit DependencyRecorder(Mode mode)
254+
: mode{mode}, requestReferences{}, isRecording{false} {};
255+
256+
private:
257+
void realize(const DependencyCollector::Reference &ref);
258+
259+
public:
260+
void replay(const swift::ActiveRequest &req);
261+
void record(const llvm::SetVector<swift::ActiveRequest> &stack,
262+
llvm::function_ref<void(DependencyCollector &)> rec);
263+
171264
public:
172265
/// Returns the scope of the current active scope.
173266
///
@@ -197,14 +290,14 @@ struct DependencyCollector {
197290
/// dependency source stack. It is specialized to be zero-cost for
198291
/// requests that are not dependency sources.
199292
template <typename Request, typename = detail::void_t<>> struct StackRAII {
200-
StackRAII(DependencyCollector &DC, const Request &Req) {}
293+
StackRAII(DependencyRecorder &DR, const Request &Req) {}
201294
};
202295

203296
template <typename Request>
204297
struct StackRAII<Request,
205298
typename std::enable_if<Request::isDependencySource>::type> {
206-
NullablePtr<DependencyCollector> Coll;
207-
StackRAII(DependencyCollector &coll, const Request &Req) {
299+
NullablePtr<DependencyRecorder> Coll;
300+
StackRAII(DependencyRecorder &coll, const Request &Req) {
208301
auto Source = Req.readDependencySource(coll);
209302
// If there is no source to introduce, bail. This can occur if
210303
// a request originates in the context of a module.

include/swift/AST/IRGenRequests.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ class IRGenSourceFileRequest
200200
public:
201201
// Incremental dependencies.
202202
evaluator::DependencySource
203-
readDependencySource(const evaluator::DependencyCollector &) const;
203+
readDependencySource(const evaluator::DependencyRecorder &) const;
204204
};
205205

206206
class IRGenWholeModuleRequest

include/swift/AST/NameLookupRequests.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ class InheritedProtocolsRequest
189189
public:
190190
// Incremental dependencies
191191
evaluator::DependencySource
192-
readDependencySource(const evaluator::DependencyCollector &e) const;
192+
readDependencySource(const evaluator::DependencyRecorder &e) const;
193193
void writeDependencySink(evaluator::DependencyCollector &tracker,
194194
ArrayRef<ProtocolDecl *> result) const;
195195
};
@@ -330,7 +330,7 @@ class GetDestructorRequest
330330
public:
331331
// Incremental dependencies.
332332
evaluator::DependencySource
333-
readDependencySource(const evaluator::DependencyCollector &) const;
333+
readDependencySource(const evaluator::DependencyRecorder &) const;
334334
};
335335

336336
class GenericParamListRequest :
@@ -434,7 +434,7 @@ class UnqualifiedLookupRequest
434434
public:
435435
// Incremental dependencies
436436
evaluator::DependencySource
437-
readDependencySource(const evaluator::DependencyCollector &) const;
437+
readDependencySource(const evaluator::DependencyRecorder &) const;
438438
void writeDependencySink(evaluator::DependencyCollector &tracker,
439439
LookupResult res) const;
440440
};
@@ -506,7 +506,7 @@ class ModuleQualifiedLookupRequest
506506
public:
507507
// Incremental dependencies
508508
evaluator::DependencySource
509-
readDependencySource(const evaluator::DependencyCollector &) const;
509+
readDependencySource(const evaluator::DependencyRecorder &) const;
510510
void writeDependencySink(evaluator::DependencyCollector &tracker,
511511
QualifiedLookupResult lookupResult) const;
512512
};
@@ -533,7 +533,7 @@ class QualifiedLookupRequest
533533
public:
534534
// Incremental dependencies.
535535
evaluator::DependencySource
536-
readDependencySource(const evaluator::DependencyCollector &) const;
536+
readDependencySource(const evaluator::DependencyRecorder &) const;
537537
};
538538

539539
/// The input type for a direct lookup request.

include/swift/AST/ParseRequests.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class ParseSourceFileRequest
103103

104104
public:
105105
evaluator::DependencySource
106-
readDependencySource(const evaluator::DependencyCollector &) const;
106+
readDependencySource(const evaluator::DependencyRecorder &) const;
107107
};
108108

109109
void simple_display(llvm::raw_ostream &out,
@@ -125,7 +125,7 @@ class CodeCompletionSecondPassRequest
125125

126126
public:
127127
evaluator::DependencySource
128-
readDependencySource(const evaluator::DependencyCollector &) const;
128+
readDependencySource(const evaluator::DependencyRecorder &) const;
129129
};
130130

131131
/// The zone number for the parser.

include/swift/AST/SILGenRequests.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class SILGenerationRequest
104104
public:
105105
// Incremental dependencies.
106106
evaluator::DependencySource
107-
readDependencySource(const evaluator::DependencyCollector &) const;
107+
readDependencySource(const evaluator::DependencyRecorder &) const;
108108
};
109109

110110
/// Parses a .sil file into a SILModule.

include/swift/AST/SimpleRequest.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ SourceLoc extractNearestSourceLoc(const std::tuple<First, Rest...> &value) {
232232
/// the 3 caching kinds defined above.
233233
/// \code
234234
/// evaluator::DependencySource
235-
/// readDependencySource(const evaluator::DependencyCollector &) const;
235+
/// readDependencySource(const evaluator::DependencyRecorder &) const;
236236
/// \endcode
237237
///
238238
/// Requests that define dependency sinks should instead override

0 commit comments

Comments
 (0)