Refine Naive Dependency Collection Algorithm

Split off the notion of "recording" dependencies from the notion of
"collecting" dependencies. This corrects an oversight in the previous
design where dependency replay and recording were actually not "free" in
WMO where we actually never track dependencies. This architecture also
lays the groundwork for the removal of the referenced name trackers.

The algorithm builds upon the infrastructure for dependency sources and
sinks laid down during the cut over to request-based dependency tracking
in #30723.

The idea of the naive algorithm is this:

For a chain of requests A -> B* -> C -> D* -> ... -> L where L is a lookup
request and all starred requests are cached, once L writes into the
dependency collector, the active stack is walked and at each cache-point
the results of dependency collection are associated with the request
itself (in this example, B* and D* have all the names L found associated
with them). Subsequent evaluations of these cached requests (B* and D*
et al) will then *replay* the previous lookup results from L into the
active referenced name tracker. One complication is, suppose the
evaluation of a cached request involves multiple downstream name
lookups. More concretely, suppose we have the following request trace:

A* -> B -> L
      |
       -> C -> L
          |
           -> D -> L
              |
               -> ...

Then A* must see the union of the results of each L. If this reminds
anyone of a union-find, that is no accident! A persistent union-find
a la Conchon and Filliatre is probably in order to help bring down peak
heap usage...
This commit is contained in:
Robert Widmann
2020-05-18 13:36:56 -07:00
parent 115bd2855b
commit 0a7929e80f
14 changed files with 145 additions and 108 deletions

View File

@@ -168,7 +168,7 @@ ArrayRef<Decl *> ParseSourceFileRequest::evaluate(Evaluator &evaluator,
}
evaluator::DependencySource ParseSourceFileRequest::readDependencySource(
const evaluator::DependencyCollector &e) const {
const evaluator::DependencyRecorder &e) const {
return {std::get<0>(getStorage()), evaluator::DependencyScope::Cascading};
}
@@ -196,7 +196,7 @@ void swift::simple_display(llvm::raw_ostream &out,
evaluator::DependencySource
CodeCompletionSecondPassRequest::readDependencySource(
const evaluator::DependencyCollector &e) const {
const evaluator::DependencyRecorder &e) const {
return {std::get<0>(getStorage()), e.getActiveSourceScope()};
}