2323#include " swift/AST/SourceFile.h"
2424#include " swift/Basic/NullablePtr.h"
2525#include " llvm/ADT/PointerIntPair.h"
26+ #include < vector>
2627
2728namespace swift {
2829
@@ -118,15 +119,12 @@ struct DependencyCollector {
118119 };
119120 };
120121
121- public:
122- using ReferenceSet = llvm::DenseSet<Reference, Reference::Info>;
123-
124122private:
125123 DependencyRecorder &parent;
126- ReferenceSet scratch;
127124
128125public:
129- explicit DependencyCollector (DependencyRecorder &parent) : parent(parent) {}
126+ explicit DependencyCollector (DependencyRecorder &parent);
127+ ~DependencyCollector ();
130128
131129public:
132130 // / Registers a named reference from the current dependency scope to a member
@@ -168,10 +166,6 @@ struct DependencyCollector {
168166public:
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
182176private:
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
202191public:
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);
223198private:
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
242201public:
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
0 commit comments