Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Unified Diff: pkg/analyzer/lib/src/summary/link.dart

Issue 2554973002: Move dependency walker logic to front end. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/front_end/lib/src/dependency_walker.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/summary/link.dart
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index ec0806e3e2ee6f3385b0f41ac3451661237c53bd..1e375c9e82d242db122dcf1986647a4fdc824461 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -72,6 +72,7 @@ import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/prelink.dart';
import 'package:analyzer/src/task/strong_mode.dart';
+import 'package:front_end/src/dependency_walker.dart';
bool isIncrementOrDecrement(UnlinkedExprAssignOperator operator) {
switch (operator) {
@@ -1752,132 +1753,6 @@ class ContextForLink implements AnalysisContext {
}
/**
- * An instance of [DependencyWalker] contains the core algorithms for
- * walking a dependency graph and evaluating nodes in a safe order.
- */
-abstract class DependencyWalker<NodeType extends Node<NodeType>> {
- /**
- * Called by [walk] to evaluate a single non-cyclical node, after
- * all that node's dependencies have been evaluated.
- */
- void evaluate(NodeType v);
-
- /**
- * Called by [walk] to evaluate a strongly connected component
- * containing one or more nodes. All dependencies of the strongly
- * connected component have been evaluated.
- */
- void evaluateScc(List<NodeType> scc);
-
- /**
- * Walk the dependency graph starting at [startingPoint], finding
- * strongly connected components and evaluating them in a safe order
- * by calling [evaluate] and [evaluateScc].
- *
- * This is an implementation of Tarjan's strongly connected
- * components algorithm
- * (https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm).
- */
- void walk(NodeType startingPoint) {
- // TODO(paulberry): consider rewriting in a non-recursive way so
- // that long dependency chains don't cause stack overflow.
-
- // TODO(paulberry): in the event that an exception occurs during
- // the walk, restore the state of the [Node] data structures so
- // that further evaluation will be safe.
-
- // The index which will be assigned to the next node that is
- // freshly visited.
- int index = 1;
-
- // Stack of nodes which have been seen so far and whose strongly
- // connected component is still being determined. Nodes are only
- // popped off the stack when they are evaluated, so sometimes the
- // stack contains nodes that were visited after the current node.
- List<NodeType> stack = <NodeType>[];
-
- void strongConnect(NodeType node) {
- bool hasTrivialCycle = false;
-
- // Assign the current node an index and add it to the stack. We
- // haven't seen any of its dependencies yet, so set its lowLink
- // to its index, indicating that so far it is the only node in
- // its strongly connected component.
- node.index = node.lowLink = index++;
- stack.add(node);
-
- // Consider the node's dependencies one at a time.
- for (NodeType dependency in node.dependencies) {
- // If the dependency has already been evaluated, it can't be
- // part of this node's strongly connected component, so we can
- // skip it.
- if (dependency.isEvaluated) {
- continue;
- }
- if (identical(node, dependency)) {
- // If a node includes itself as a dependency, there is no need to
- // explore the dependency further.
- hasTrivialCycle = true;
- } else if (dependency.index == 0) {
- // The dependency hasn't been seen yet, so recurse on it.
- strongConnect(dependency);
- // If the dependency's lowLink refers to a node that was
- // visited before the current node, that means that the
- // current node, the dependency, and the node referred to by
- // the dependency's lowLink are all part of the same
- // strongly connected component, so we need to update the
- // current node's lowLink accordingly.
- if (dependency.lowLink < node.lowLink) {
- node.lowLink = dependency.lowLink;
- }
- } else {
- // The dependency has already been seen, so it is part of
- // the current node's strongly connected component. If it
- // was visited earlier than the current node's lowLink, then
- // it is a new addition to the current node's strongly
- // connected component, so we need to update the current
- // node's lowLink accordingly.
- if (dependency.index < node.lowLink) {
- node.lowLink = dependency.index;
- }
- }
- }
-
- // If the current node's lowLink is the same as its index, then
- // we have finished visiting a strongly connected component, so
- // pop the stack and evaluate it before moving on.
- if (node.lowLink == node.index) {
- // The strongly connected component has only one node. If there is a
- // cycle, it's a trivial one.
- if (identical(stack.last, node)) {
- stack.removeLast();
- if (hasTrivialCycle) {
- evaluateScc(<NodeType>[node]);
- } else {
- evaluate(node);
- }
- } else {
- // There are multiple nodes in the strongly connected
- // component.
- List<NodeType> scc = <NodeType>[];
- while (true) {
- NodeType otherNode = stack.removeLast();
- scc.add(otherNode);
- if (identical(otherNode, node)) {
- break;
- }
- }
- evaluateScc(scc);
- }
- }
- }
-
- // Kick off the algorithm starting with the starting point.
- strongConnect(startingPoint);
- }
-}
-
-/**
* Base class for executable elements resynthesized from a summary during
* linking.
*/
@@ -3856,45 +3731,6 @@ class MethodElementForLink extends ExecutableElementForLink_NonLocal
}
/**
- * Instances of [Node] represent nodes in a dependency graph. The
- * type parameter, [NodeType], is the derived type (this affords some
- * extra type safety by making it difficult to accidentally construct
- * bridges between unrelated dependency graphs).
- */
-abstract class Node<NodeType> {
- /**
- * Index used by Tarjan's strongly connected components algorithm.
- * Zero means the node has not been visited yet; a nonzero value
- * counts the order in which the node was visited.
- */
- int index = 0;
-
- /**
- * Low link used by Tarjan's strongly connected components
- * algorithm. This represents the smallest [index] of all the nodes
- * in the strongly connected component to which this node belongs.
- */
- int lowLink = 0;
-
- List<NodeType> _dependencies;
-
- /**
- * Retrieve the dependencies of this node.
- */
- List<NodeType> get dependencies => _dependencies ??= computeDependencies();
-
- /**
- * Indicates whether this node has been evaluated yet.
- */
- bool get isEvaluated;
-
- /**
- * Compute the dependencies of this node.
- */
- List<NodeType> computeDependencies();
-}
-
-/**
* Element used for references that result from trying to access a non-static
* member of an element that is not a container (e.g. accessing the "length"
* property of a constant).
« no previous file with comments | « no previous file | pkg/front_end/lib/src/dependency_walker.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698