Skip to content

Commit 8f0c66f

Browse files
authored
Merge pull request #2395 from swiftwasm/main
[pull] swiftwasm from main
2 parents 2a70058 + 07f632a commit 8f0c66f

File tree

59 files changed

+1242
-487
lines changed

Some content is hidden

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

59 files changed

+1242
-487
lines changed

include/swift/AST/AnyRequest.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ struct AnyRequestVTable {
8383
const std::function<void(const void *, DiagnosticEngine &)> noteCycleStep;
8484
const std::function<SourceLoc(const void *)> getNearestLoc;
8585
const std::function<bool(const void *)> isCached;
86+
bool isDependencySource;
8687

8788
template <typename Request,
8889
typename std::enable_if<Request::isEverCached>::type * = nullptr>
@@ -99,6 +100,7 @@ struct AnyRequestVTable {
99100
&Impl<Request>::noteCycleStep,
100101
&Impl<Request>::getNearestLoc,
101102
&Impl<Request>::isCached,
103+
Request::isDependencySource,
102104
};
103105
return &vtable;
104106
}
@@ -118,6 +120,7 @@ struct AnyRequestVTable {
118120
&Impl<Request>::noteCycleStep,
119121
&Impl<Request>::getNearestLoc,
120122
[](auto){ return false; },
123+
Request::isDependencySource,
121124
};
122125
return &vtable;
123126
}
@@ -224,6 +227,10 @@ class AnyRequestBase {
224227
return getVTable()->isCached(getRawStorage());
225228
}
226229

230+
bool isDependencySource() const {
231+
return getVTable()->isDependencySource;
232+
}
233+
227234
/// Compare two instances for equality.
228235
friend bool operator==(const AnyRequestBase<Derived> &lhs,
229236
const AnyRequestBase<Derived> &rhs) {

include/swift/AST/Evaluator.h

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,6 @@ class Evaluator {
271271
typename std::enable_if<Request::isEverCached>::type * = nullptr>
272272
llvm::Expected<typename Request::OutputType>
273273
operator()(const Request &request) {
274-
evaluator::DependencyRecorder::StackRAII<Request> incDeps{recorder,
275-
request};
276274
// The request can be cached, but check a predicate to determine
277275
// whether this particular instance is cached. This allows more
278276
// fine-grained control over which instances get cache.
@@ -288,8 +286,6 @@ class Evaluator {
288286
typename std::enable_if<!Request::isEverCached>::type * = nullptr>
289287
llvm::Expected<typename Request::OutputType>
290288
operator()(const Request &request) {
291-
evaluator::DependencyRecorder::StackRAII<Request> incDeps{recorder,
292-
request};
293289
return getResultUncached(request);
294290
}
295291

@@ -366,13 +362,6 @@ class Evaluator {
366362
std::make_unique<CyclicalRequestError<Request>>(request, *this));
367363
}
368364

369-
// Make sure we remove this from the set of active requests once we're
370-
// done.
371-
SWIFT_DEFER {
372-
assert(activeRequests.back() == activeReq);
373-
activeRequests.pop_back();
374-
};
375-
376365
// Clear out the dependencies on this request; we're going to recompute
377366
// them now anyway.
378367
if (buildDependencyGraph)
@@ -384,8 +373,20 @@ class Evaluator {
384373
FrontendStatsTracer statsTracer = make_tracer(stats, request);
385374
if (stats) reportEvaluatedRequest(*stats, request);
386375

376+
recorder.beginRequest(activeReq);
377+
387378
auto &&r = getRequestFunction<Request>()(request, *this);
388-
reportEvaluatedResult<Request>(request, r);
379+
380+
recorder.endRequest(activeReq);
381+
382+
handleDependencySourceRequest<Request>(request);
383+
handleDependencySinkRequest<Request>(request, r);
384+
385+
// Make sure we remove this from the set of active requests once we're
386+
// done.
387+
assert(activeRequests.back() == activeReq);
388+
activeRequests.pop_back();
389+
389390
return std::move(r);
390391
}
391392

@@ -398,7 +399,8 @@ class Evaluator {
398399
getResultCached(const Request &request) {
399400
// If there is a cached result, return it.
400401
if (auto cached = request.getCachedResult()) {
401-
reportEvaluatedResult<Request>(request, *cached);
402+
recorder.replayCachedRequest(ActiveRequest(request));
403+
handleDependencySinkRequest<Request>(request, *cached);
402404
return *cached;
403405
}
404406

@@ -426,7 +428,8 @@ class Evaluator {
426428
auto known = cache.find_as(request);
427429
if (known != cache.end()) {
428430
auto r = known->second.template castTo<typename Request::OutputType>();
429-
reportEvaluatedResult<Request>(request, r);
431+
recorder.replayCachedRequest(ActiveRequest(request));
432+
handleDependencySinkRequest<Request>(request, r);
430433
return r;
431434
}
432435

@@ -441,22 +444,30 @@ class Evaluator {
441444
}
442445

443446
private:
444-
// Report the result of evaluating a request that is not a dependency sink.
445447
template <typename Request, typename std::enable_if<
446448
!Request::isDependencySink>::type * = nullptr>
447-
void reportEvaluatedResult(const Request &r,
448-
const typename Request::OutputType &o) {
449-
recorder.replay(activeRequests, ActiveRequest(r));
450-
}
449+
void handleDependencySinkRequest(const Request &r,
450+
const typename Request::OutputType &o) {}
451451

452-
// Report the result of evaluating a request that is a dependency sink.
453452
template <typename Request,
454453
typename std::enable_if<Request::isDependencySink>::type * = nullptr>
455-
void reportEvaluatedResult(const Request &r,
456-
const typename Request::OutputType &o) {
457-
return recorder.record(activeRequests, [&r, &o](auto &c) {
458-
return r.writeDependencySink(c, o);
459-
});
454+
void handleDependencySinkRequest(const Request &r,
455+
const typename Request::OutputType &o) {
456+
evaluator::DependencyCollector collector(recorder);
457+
r.writeDependencySink(collector, o);
458+
}
459+
460+
template <typename Request, typename std::enable_if<
461+
!Request::isDependencySource>::type * = nullptr>
462+
void handleDependencySourceRequest(const Request &r) {}
463+
464+
template <typename Request,
465+
typename std::enable_if<Request::isDependencySource>::type * = nullptr>
466+
void handleDependencySourceRequest(const Request &r) {
467+
auto source = r.readDependencySource(recorder);
468+
if (!source.isNull() && source.get()->isPrimary()) {
469+
recorder.handleDependencySourceRequest(ActiveRequest(r), source.get());
470+
}
460471
}
461472

462473
public:

include/swift/AST/EvaluatorDependencies.h

Lines changed: 19 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/SourceFile.h"
2424
#include "swift/Basic/NullablePtr.h"
2525
#include "llvm/ADT/PointerIntPair.h"
26+
#include <vector>
2627

2728
namespace swift {
2829

@@ -118,15 +119,12 @@ struct DependencyCollector {
118119
};
119120
};
120121

121-
public:
122-
using ReferenceSet = llvm::DenseSet<Reference, Reference::Info>;
123-
124122
private:
125123
DependencyRecorder &parent;
126-
ReferenceSet scratch;
127124

128125
public:
129-
explicit DependencyCollector(DependencyRecorder &parent) : parent(parent) {}
126+
explicit DependencyCollector(DependencyRecorder &parent);
127+
~DependencyCollector();
130128

131129
public:
132130
/// Registers a named reference from the current dependency scope to a member
@@ -168,10 +166,6 @@ struct DependencyCollector {
168166
public:
169167
/// Retrieves the dependency recorder that created this dependency collector.
170168
const DependencyRecorder &getRecorder() const { return parent; }
171-
172-
/// Returns \c true if this collector has not accumulated
173-
/// any \c Reference objects.
174-
bool empty() const { return scratch.empty(); }
175169
};
176170

177171
/// A \c DependencyRecorder is an aggregator of named references discovered in a
@@ -180,64 +174,29 @@ struct DependencyRecorder {
180174
friend DependencyCollector;
181175

182176
private:
183-
/// A stack of dependency sources in the order they were evaluated.
184-
llvm::SmallVector<evaluator::DependencySource, 8> dependencySources;
185-
llvm::DenseMap<SourceFile *, DependencyCollector::ReferenceSet>
177+
llvm::DenseMap<SourceFile *,
178+
llvm::DenseSet<DependencyCollector::Reference,
179+
DependencyCollector::Reference::Info>>
186180
fileReferences;
187-
llvm::DenseMap<AnyRequest, DependencyCollector::ReferenceSet>
181+
llvm::DenseMap<AnyRequest, std::vector<DependencyCollector::Reference>>
188182
requestReferences;
189-
bool isRecording;
183+
std::vector<llvm::DenseSet<DependencyCollector::Reference,
184+
DependencyCollector::Reference::Info>>
185+
activeRequestReferences;
190186

191-
public:
192-
explicit DependencyRecorder() : isRecording{false} {};
193-
194-
private:
195-
/// Records the given \c Reference as a dependency of the current dependency
196-
/// source.
197-
///
198-
/// This is as opposed to merely collecting a \c Reference, which may just buffer
199-
/// it for realization or replay later.
200-
void realize(const DependencyCollector::Reference &ref);
187+
#ifndef NDEBUG
188+
bool isRecording = false;
189+
#endif
201190

202191
public:
203-
/// Begins the recording of references by invoking the given continuation
204-
/// with a fresh \c DependencyCollector object. This object should be used
205-
/// to buffer dependency-relevant references to names looked up by a
206-
/// given request.
207-
///
208-
/// Recording only occurs for requests that are dependency sinks.
209-
void record(const llvm::SetVector<swift::ActiveRequest> &stack,
210-
llvm::function_ref<void(DependencyCollector &)> rec);
192+
void beginRequest(const swift::ActiveRequest &req);
193+
void endRequest(const swift::ActiveRequest &req);
194+
void replayCachedRequest(const swift::ActiveRequest &req);
195+
void handleDependencySourceRequest(const swift::ActiveRequest &req,
196+
SourceFile *source);
211197

212-
/// Replays the \c Reference objects collected by a given cached request and
213-
/// its sub-requests into the current dependency scope.
214-
///
215-
/// Dependency replay ensures that cached requests do not "hide" names from
216-
/// the active dependency scope. This would otherwise occur frequently in
217-
/// batch mode, where cached requests effectively block the re-evaluation of
218-
/// a large quantity of computations that perform name lookups by design.
219-
///
220-
/// Replay need only occur for requests that are (separately) cached.
221-
void replay(const llvm::SetVector<swift::ActiveRequest> &stack,
222-
const swift::ActiveRequest &req);
223198
private:
224-
/// Given the current stack of requests and a buffer of \c Reference objects
225-
/// walk the active stack looking for the next-innermost cached request. If
226-
/// found, insert the buffer of references into that request's known reference
227-
/// set.
228-
///
229-
/// This algorithm ensures that references propagate lazily up the request
230-
/// graph from cached sub-requests to their cached parents. Once this process
231-
/// completes, all cached requests in the request graph will see the
232-
/// union of all references recorded while evaluating their sub-requests.
233-
///
234-
/// This algorithm *must* be tail-called during
235-
/// \c DependencyRecorder::record or \c DependencyRecorder::replay
236-
/// or the corresponding set of references for the active dependency scope
237-
/// will become incoherent.
238-
void
239-
unionNearestCachedRequest(ArrayRef<swift::ActiveRequest> stack,
240-
const DependencyCollector::ReferenceSet &scratch);
199+
void recordDependency(const DependencyCollector::Reference &ref);
241200

242201
public:
243202
using ReferenceEnumerator =
@@ -250,49 +209,6 @@ struct DependencyRecorder {
250209
/// of callers to ensure they are order-invariant or are sorting the result.
251210
void enumerateReferencesInFile(const SourceFile *SF,
252211
ReferenceEnumerator f) const ;
253-
254-
public:
255-
/// Returns the active dependency's source file, or \c nullptr if no
256-
/// dependency source is active.
257-
///
258-
/// The use of this accessor is strongly discouraged, as it implies that a
259-
/// dependency sink is seeking to filter out names based on the files they
260-
/// come from. Existing callers are being migrated to more reasonable ways
261-
/// of judging the relevancy of a dependency.
262-
evaluator::DependencySource getActiveDependencySourceOrNull() const {
263-
if (dependencySources.empty())
264-
return nullptr;
265-
return dependencySources.front();
266-
}
267-
268-
public:
269-
/// An RAII type that manages manipulating the evaluator's
270-
/// dependency source stack. It is specialized to be zero-cost for
271-
/// requests that are not dependency sources.
272-
template <typename Request, typename = detail::void_t<>> struct StackRAII {
273-
StackRAII(DependencyRecorder &DR, const Request &Req) {}
274-
};
275-
276-
template <typename Request>
277-
struct StackRAII<Request,
278-
typename std::enable_if<Request::isDependencySource>::type> {
279-
NullablePtr<DependencyRecorder> Coll;
280-
StackRAII(DependencyRecorder &coll, const Request &Req) {
281-
auto Source = Req.readDependencySource(coll);
282-
// If there is no source to introduce, bail. This can occur if
283-
// a request originates in the context of a module.
284-
if (Source.isNull() || !Source.get()->isPrimary()) {
285-
return;
286-
}
287-
coll.dependencySources.emplace_back(Source);
288-
Coll = &coll;
289-
}
290-
291-
~StackRAII() {
292-
if (Coll.isNonNull())
293-
Coll.get()->dependencySources.pop_back();
294-
}
295-
};
296212
};
297213
} // end namespace evaluator
298214

include/swift/AST/NameLookupRequests.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ class UnqualifiedLookupRequest
406406
public:
407407
// Incremental dependencies
408408
void writeDependencySink(evaluator::DependencyCollector &tracker,
409-
LookupResult res) const;
409+
const LookupResult &res) const;
410410
};
411411

412412
using QualifiedLookupResult = SmallVector<ValueDecl *, 4>;
@@ -434,7 +434,7 @@ class LookupInModuleRequest
434434
public:
435435
// Incremental dependencies
436436
void writeDependencySink(evaluator::DependencyCollector &tracker,
437-
QualifiedLookupResult l) const;
437+
const QualifiedLookupResult &l) const;
438438
};
439439

440440
/// Perform \c AnyObject lookup for a given member.
@@ -457,7 +457,7 @@ class AnyObjectLookupRequest
457457
public:
458458
// Incremental dependencies
459459
void writeDependencySink(evaluator::DependencyCollector &tracker,
460-
QualifiedLookupResult l) const;
460+
const QualifiedLookupResult &l) const;
461461
};
462462

463463
class ModuleQualifiedLookupRequest
@@ -482,7 +482,7 @@ class ModuleQualifiedLookupRequest
482482
public:
483483
// Incremental dependencies
484484
void writeDependencySink(evaluator::DependencyCollector &tracker,
485-
QualifiedLookupResult lookupResult) const;
485+
const QualifiedLookupResult &lookupResult) const;
486486
};
487487

488488
class QualifiedLookupRequest
@@ -555,7 +555,7 @@ class DirectLookupRequest
555555
public:
556556
// Incremental dependencies
557557
void writeDependencySink(evaluator::DependencyCollector &tracker,
558-
TinyPtrVector<ValueDecl *> result) const;
558+
const TinyPtrVector<ValueDecl *> &result) const;
559559
};
560560

561561
class OperatorLookupDescriptor final {
@@ -636,7 +636,7 @@ class DirectOperatorLookupRequest
636636
public:
637637
// Incremental dependencies.
638638
void writeDependencySink(evaluator::DependencyCollector &tracker,
639-
TinyPtrVector<OperatorDecl *> ops) const;
639+
const TinyPtrVector<OperatorDecl *> &ops) const;
640640
};
641641

642642
/// Looks up an precedencegroup in a given file or module without looking
@@ -659,7 +659,7 @@ class DirectPrecedenceGroupLookupRequest
659659
public:
660660
// Incremental dependencies.
661661
void writeDependencySink(evaluator::DependencyCollector &tracker,
662-
TinyPtrVector<PrecedenceGroupDecl *> groups) const;
662+
const TinyPtrVector<PrecedenceGroupDecl *> &groups) const;
663663
};
664664

665665
class LookupConformanceDescriptor final {

include/swift/AST/TypeCheckRequests.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2504,7 +2504,7 @@ class LookupAllConformancesInContextRequest
25042504

25052505
// Incremental dependencies
25062506
void writeDependencySink(evaluator::DependencyCollector &tracker,
2507-
ProtocolConformanceLookupResult r) const;
2507+
const ProtocolConformanceLookupResult &r) const;
25082508
};
25092509

25102510
class CheckRedeclarationRequest

0 commit comments

Comments
 (0)