| Index: pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart b/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
|
| deleted file mode 100644
|
| index 4433510e7b91068efd4287d42cd44d407d89c6b2..0000000000000000000000000000000000000000
|
| --- a/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
|
| +++ /dev/null
|
| @@ -1,175 +0,0 @@
|
| -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -library dart2js.cps_ir.loop_hierarchy;
|
| -
|
| -import 'cps_fragment.dart';
|
| -import 'cps_ir_nodes.dart';
|
| -
|
| -/// Determines the effective nesting of loops.
|
| -///
|
| -/// The effective nesting of loops is different from the lexical nesting, since
|
| -/// recursive continuations can generally contain all the code following
|
| -/// after the loop in addition to the looping code itself.
|
| -///
|
| -/// For example, the 'else' branch below is not effectively part of the loop:
|
| -///
|
| -/// let rec kont x =
|
| -/// if (<loop condition>)
|
| -/// <loop body>
|
| -/// InvokeContinuation kont x'
|
| -/// else
|
| -/// <after loop>
|
| -/// return p.foo()
|
| -///
|
| -/// We use the term "loop" to mean recursive continuation.
|
| -/// The `null` value is used to represent a context not part of any loop.
|
| -class LoopHierarchy {
|
| - /// Nesting depth of the given loop.
|
| - Map<Continuation, int> loopDepth = <Continuation, int>{};
|
| -
|
| - /// The innermost loop (other than itself) that may be invoked recursively
|
| - /// as a result of invoking the given continuation.
|
| - Map<Continuation, Continuation> loopTarget = <Continuation, Continuation>{};
|
| -
|
| - /// Current nesting depth.
|
| - int _currentDepth = 0;
|
| -
|
| - /// The loop target to use for missing code. Used by [update].
|
| - Continuation _exitLoop;
|
| -
|
| - /// Computes the loop hierarchy for the given function.
|
| - ///
|
| - /// Parent pointers must be computed for [node].
|
| - LoopHierarchy(FunctionDefinition node) {
|
| - _processBlock(node.body, null);
|
| - }
|
| -
|
| - /// Returns the innermost loop which [cont] is effectively part of.
|
| - Continuation getLoopHeader(Continuation cont) {
|
| - return cont.isRecursive ? cont : loopTarget[cont];
|
| - }
|
| -
|
| - /// Returns the innermost loop which the given continuation is part of, other
|
| - /// than itself.
|
| - Continuation getEnclosingLoop(Continuation cont) {
|
| - return loopTarget[cont];
|
| - }
|
| -
|
| - /// Marks the innermost loop as a subloop of the other loop.
|
| - ///
|
| - /// Returns the innermost loop.
|
| - ///
|
| - /// Both continuations, [c1] and [c2] may be null (i.e. no loop).
|
| - ///
|
| - /// A loop is said to be a subloop of an enclosing loop if it can invoke
|
| - /// that loop recursively. This information is stored in [loopTarget].
|
| - ///
|
| - /// This method is only invoked with two distinct loops if there is a
|
| - /// point that can reach a recursive invocation of both loops.
|
| - /// This implies that one loop is nested in the other, because they must
|
| - /// both be in scope at that point.
|
| - Continuation _markInnerLoop(Continuation c1, Continuation c2) {
|
| - assert(c1 == null || c1.isRecursive);
|
| - assert(c2 == null || c2.isRecursive);
|
| - if (c1 == null) return c2;
|
| - if (c2 == null) return c1;
|
| - if (c1 == c2) return c1;
|
| - if (loopDepth[c1] > loopDepth[c2]) {
|
| - loopTarget[c1] = _markInnerLoop(loopTarget[c1], c2);
|
| - return c1;
|
| - } else {
|
| - loopTarget[c2] = _markInnerLoop(loopTarget[c2], c1);
|
| - return c2;
|
| - }
|
| - }
|
| -
|
| - /// Analyzes the body of [cont] and returns the innermost loop
|
| - /// that can be invoked recursively from [cont] (other than [cont] itself).
|
| - ///
|
| - /// [catchLoop] is the innermost loop that can be invoked recursively
|
| - /// from the current exception handler.
|
| - Continuation _processContinuation(Continuation cont, Continuation catchLoop) {
|
| - if (cont.isRecursive) {
|
| - ++_currentDepth;
|
| - loopDepth[cont] = _currentDepth;
|
| - Continuation target = _processBlock(cont.body, catchLoop);
|
| - _markInnerLoop(loopTarget[cont], target);
|
| - --_currentDepth;
|
| - } else {
|
| - loopTarget[cont] = _processBlock(cont.body, catchLoop);
|
| - }
|
| - return loopTarget[cont];
|
| - }
|
| -
|
| - /// Analyzes a basic block and returns the innermost loop that
|
| - /// can be invoked recursively from that block.
|
| - Continuation _processBlock(Expression node, Continuation catchLoop) {
|
| - for (; node != null && node is! TailExpression; node = node.next) {
|
| - if (node is LetCont) {
|
| - for (Continuation cont in node.continuations) {
|
| - _processContinuation(cont, catchLoop);
|
| - }
|
| - } else if (node is LetHandler) {
|
| - catchLoop = _processContinuation(node.handler, catchLoop);
|
| - }
|
| - }
|
| - Continuation target;
|
| - if (node is InvokeContinuation) {
|
| - if (node.isRecursive) {
|
| - target = node.continuation;
|
| - } else {
|
| - target = loopTarget[node.continuation];
|
| - }
|
| - } else if (node is Branch) {
|
| - target = _markInnerLoop(loopTarget[node.trueContinuation],
|
| - loopTarget[node.falseContinuation]);
|
| - } else if (node == null) {
|
| - // If the code ends abruptly, use the exit loop provided in [update].
|
| - target = _exitLoop;
|
| - } else {
|
| - assert(node is Unreachable || node is Throw || node == null);
|
| - }
|
| - return _markInnerLoop(target, catchLoop);
|
| - }
|
| -
|
| - /// Returns the innermost loop that effectively encloses both
|
| - /// c1 and c2 (or `null` if there is no such loop).
|
| - Continuation lowestCommonAncestor(Continuation c1, Continuation c2) {
|
| - int d1 = getDepth(c1), d2 = getDepth(c2);
|
| - while (c1 != c2) {
|
| - if (d1 <= d2) {
|
| - c2 = getEnclosingLoop(c2);
|
| - d2 = getDepth(c2);
|
| - } else {
|
| - c1 = getEnclosingLoop(c1);
|
| - d1 = getDepth(c1);
|
| - }
|
| - }
|
| - return c1;
|
| - }
|
| -
|
| - /// Returns the lexical nesting depth of [loop].
|
| - int getDepth(Continuation loop) {
|
| - if (loop == null) return 0;
|
| - return loopDepth[loop];
|
| - }
|
| -
|
| - /// Sets the loop header for each continuation bound inside the given
|
| - /// fragment.
|
| - ///
|
| - /// If the fragment is open, [exitLoop] denotes the loop header for
|
| - /// the code that will occur after the fragment.
|
| - ///
|
| - /// [catchLoop] is the loop target for the catch clause of the try/catch
|
| - /// surrounding the inserted fragment.
|
| - void update(CpsFragment fragment,
|
| - {Continuation exitLoop, Continuation catchLoop}) {
|
| - if (fragment.isEmpty) return;
|
| - _exitLoop = exitLoop;
|
| - _currentDepth = getDepth(exitLoop);
|
| - _processBlock(fragment.root, catchLoop);
|
| - _exitLoop = null;
|
| - }
|
| -}
|
|
|