20
20
21
21
#include " swift/AST/AnyRequest.h"
22
22
#include " swift/AST/DependencyCollector.h"
23
+ #include " swift/AST/RequestCache.h"
23
24
#include " swift/Basic/NullablePtr.h"
24
25
#include " llvm/ADT/DenseMap.h"
25
26
#include " llvm/ADT/DenseSet.h"
@@ -63,15 +64,14 @@ struct DependencyRecorder {
63
64
// / downstream request as well. Note that uncached requests don't appear as
64
65
// / keys in this map; their references are charged to the innermost cached
65
66
// / active request.
66
- llvm::DenseMap<AnyRequest, std::vector<DependencyCollector::Reference>>
67
- requestReferences;
67
+ RequestReferences requestReferences;
68
68
69
69
// / Stack of references from each cached active request. When evaluating a
70
70
// / dependency sink request, we update the innermost set of references.
71
71
// / Upon completion of a request, we union the completed request's references
72
72
// / with the next innermost active request.
73
- std::vector<llvm::DenseSet <DependencyCollector::Reference,
74
- DependencyCollector::Reference::Info>>
73
+ std::vector<llvm::SmallDenseSet <DependencyCollector::Reference, 2 ,
74
+ DependencyCollector::Reference::Info>>
75
75
activeRequestReferences;
76
76
77
77
#ifndef NDEBUG
@@ -83,22 +83,30 @@ struct DependencyRecorder {
83
83
84
84
public:
85
85
// / Push a new empty set onto the activeRequestReferences stack.
86
- void beginRequest (const swift::ActiveRequest &req);
86
+ template <typename Request>
87
+ void beginRequest ();
87
88
88
89
// / Pop the activeRequestReferences stack, and insert recorded references
89
90
// / into the requestReferences map, as well as the next innermost entry in
90
91
// / activeRequestReferences.
91
- void endRequest (const swift::ActiveRequest &req);
92
+ template <typename Request>
93
+ void endRequest (const Request &req);
92
94
93
95
// / When replaying a request whose value has already been cached, we need
94
96
// / to update the innermost set in the activeRequestReferences stack.
95
- void replayCachedRequest (const swift::ActiveRequest &req);
97
+ template <typename Request>
98
+ void replayCachedRequest (const Request &req);
96
99
97
100
// / Upon completion of a dependency source request, we update the
98
101
// / fileReferences map.
99
- void handleDependencySourceRequest (const swift::ActiveRequest &req,
102
+ template <typename Request>
103
+ void handleDependencySourceRequest (const Request &req,
100
104
SourceFile *source);
101
105
106
+ // / Clear the recorded dependencies of a request, if any.
107
+ template <typename Request>
108
+ void clearRequest (const Request &req);
109
+
102
110
private:
103
111
// / Add an entry to the innermost set on the activeRequestReferences stack.
104
112
// / Called from the DependencyCollector.
@@ -120,6 +128,76 @@ struct DependencyRecorder {
120
128
void enumerateReferencesInFile (const SourceFile *SF,
121
129
ReferenceEnumerator f) const ;
122
130
};
131
+
132
+ template <typename Request>
133
+ void evaluator::DependencyRecorder::beginRequest () {
134
+ if (!Request::isEverCached && !Request::isDependencySource)
135
+ return ;
136
+
137
+ activeRequestReferences.push_back ({});
138
+ }
139
+
140
+ template <typename Request>
141
+ void evaluator::DependencyRecorder::endRequest (const Request &req) {
142
+ if (!Request::isEverCached && !Request::isDependencySource)
143
+ return ;
144
+
145
+ // Grab all the dependencies we've recorded so far, and pop
146
+ // the stack.
147
+ auto recorded = std::move (activeRequestReferences.back ());
148
+ activeRequestReferences.pop_back ();
149
+
150
+ // If we didn't record anything, there is nothing to do.
151
+ if (recorded.empty ())
152
+ return ;
153
+
154
+ // Convert the set of dependencies into a vector.
155
+ std::vector<DependencyCollector::Reference>
156
+ vec (recorded.begin (), recorded.end ());
157
+
158
+ // The recorded dependencies bubble up to the parent request.
159
+ if (!activeRequestReferences.empty ()) {
160
+ activeRequestReferences.back ().insert (vec.begin (),
161
+ vec.end ());
162
+ }
163
+
164
+ // Finally, record the dependencies so we can replay them
165
+ // later when the request is re-evaluated.
166
+ requestReferences.insert <Request>(std::move (req), std::move (vec));
167
+ }
168
+
169
+ template <typename Request>
170
+ void evaluator::DependencyRecorder::replayCachedRequest (const Request &req) {
171
+ assert (req.isCached ());
172
+
173
+ if (activeRequestReferences.empty ())
174
+ return ;
175
+
176
+ auto found = requestReferences.find_as <Request>(req);
177
+ if (found == requestReferences.end <Request>())
178
+ return ;
179
+
180
+ activeRequestReferences.back ().insert (found->second .begin (),
181
+ found->second .end ());
182
+ }
183
+
184
+ template <typename Request>
185
+ void evaluator::DependencyRecorder::handleDependencySourceRequest (
186
+ const Request &req,
187
+ SourceFile *source) {
188
+ auto found = requestReferences.find_as <Request>(req);
189
+ if (found != requestReferences.end <Request>()) {
190
+ fileReferences[source].insert (found->second .begin (),
191
+ found->second .end ());
192
+ }
193
+ }
194
+
195
+ template <typename Request>
196
+ void evaluator::DependencyRecorder::clearRequest (
197
+ const Request &req) {
198
+ requestReferences.erase (req);
199
+ }
200
+
123
201
} // end namespace evaluator
124
202
125
203
} // end namespace swift
0 commit comments