23
23
#include " swift/AST/SourceFile.h"
24
24
#include " swift/Basic/NullablePtr.h"
25
25
#include " llvm/ADT/PointerIntPair.h"
26
+ #include < vector>
26
27
27
28
namespace swift {
28
29
@@ -118,15 +119,12 @@ struct DependencyCollector {
118
119
};
119
120
};
120
121
121
- public:
122
- using ReferenceSet = llvm::DenseSet<Reference, Reference::Info>;
123
-
124
122
private:
125
123
DependencyRecorder &parent;
126
- ReferenceSet scratch;
127
124
128
125
public:
129
- explicit DependencyCollector (DependencyRecorder &parent) : parent(parent) {}
126
+ explicit DependencyCollector (DependencyRecorder &parent);
127
+ ~DependencyCollector ();
130
128
131
129
public:
132
130
// / Registers a named reference from the current dependency scope to a member
@@ -168,10 +166,6 @@ struct DependencyCollector {
168
166
public:
169
167
// / Retrieves the dependency recorder that created this dependency collector.
170
168
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 (); }
175
169
};
176
170
177
171
// / A \c DependencyRecorder is an aggregator of named references discovered in a
@@ -180,64 +174,29 @@ struct DependencyRecorder {
180
174
friend DependencyCollector;
181
175
182
176
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> >
186
180
fileReferences;
187
- llvm::DenseMap<AnyRequest, DependencyCollector::ReferenceSet >
181
+ llvm::DenseMap<AnyRequest, std::vector< DependencyCollector::Reference> >
188
182
requestReferences;
189
- bool isRecording;
183
+ std::vector<llvm::DenseSet<DependencyCollector::Reference,
184
+ DependencyCollector::Reference::Info>>
185
+ activeRequestReferences;
190
186
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
201
190
202
191
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);
211
197
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);
223
198
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);
241
200
242
201
public:
243
202
using ReferenceEnumerator =
@@ -250,49 +209,6 @@ struct DependencyRecorder {
250
209
// / of callers to ensure they are order-invariant or are sorting the result.
251
210
void enumerateReferencesInFile (const SourceFile *SF,
252
211
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
- };
296
212
};
297
213
} // end namespace evaluator
298
214
0 commit comments