OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.cps_ir.loop_hierarchy; | 5 library dart2js.cps_ir.loop_hierarchy; |
6 | 6 |
7 import 'cps_ir_nodes.dart'; | 7 import 'cps_ir_nodes.dart'; |
8 | 8 |
9 /// Determines the effective nesting of loops. | 9 /// Determines the effective nesting of loops. |
10 /// | 10 /// |
11 /// The effective nesting of loops is different from the lexical nesting, since | 11 /// The effective nesting of loops is different from the lexical nesting, since |
12 /// recursive continuations can generally contain all the code following | 12 /// recursive continuations can generally contain all the code following |
13 /// after the loop in addition to the looping code itself. | 13 /// after the loop in addition to the looping code itself. |
14 /// | 14 /// |
15 /// For example, the 'else' branch below is not effectively part of the loop: | 15 /// For example, the 'else' branch below is not effectively part of the loop: |
16 /// | 16 /// |
17 /// let rec kont x = | 17 /// let rec kont x = |
18 /// if (<loop condition>) | 18 /// if (<loop condition>) |
19 /// <loop body> | 19 /// <loop body> |
20 /// InvokeContinuation kont x' | 20 /// InvokeContinuation kont x' |
21 /// else | 21 /// else |
22 /// <after loop> | 22 /// <after loop> |
23 /// return p.foo() | 23 /// return p.foo() |
24 /// | 24 /// |
25 /// We use the term "loop" to mean recursive continuation. | 25 /// We use the term "loop" to mean recursive continuation. |
26 /// The `null` value is used to represent a context not part of any loop. | 26 /// The `null` value is used to represent a context not part of any loop. |
27 class LoopHierarchy { | 27 class LoopHierarchy { |
28 /// Nesting depth of the given loop. | 28 /// Nesting depth of the given loop. |
29 Map<Continuation, int> loopDepth = <Continuation, int>{}; | 29 Map<Continuation, int> loopDepth = <Continuation, int>{}; |
30 | 30 |
31 /// The innermost loop (other than itself) that may be invoked recursively | 31 /// The innermost loop (other than itself) that may be invoked recursively |
32 /// as a result of invoking the given continuation. | 32 /// as a result of invoking the given continuation. |
33 Map<Continuation, Continuation> loopTarget = <Continuation, Continuation>{}; | 33 Map<Continuation, Continuation> loopTarget = <Continuation, Continuation>{}; |
34 | 34 |
35 /// Current nesting depth. | 35 /// Current nesting depth. |
36 int currentDepth = 0; | 36 int currentDepth = 0; |
37 | 37 |
38 /// Computes the loop hierarchy for the given function. | 38 /// Computes the loop hierarchy for the given function. |
39 /// | 39 /// |
40 /// Parent pointers must be computed for [node]. | 40 /// Parent pointers must be computed for [node]. |
41 LoopHierarchy(FunctionDefinition node) { | 41 LoopHierarchy(FunctionDefinition node) { |
42 _processBlock(node.body, null); | 42 _processBlock(node.body, null); |
43 } | 43 } |
44 | 44 |
45 /// Returns the innermost loop which [cont] is effectively part of. | 45 /// Returns the innermost loop which [cont] is effectively part of. |
46 Continuation getLoopHeader(Continuation cont) { | 46 Continuation getLoopHeader(Continuation cont) { |
47 return cont.isRecursive ? cont : loopTarget[cont]; | 47 return cont.isRecursive ? cont : loopTarget[cont]; |
48 } | 48 } |
49 | 49 |
50 /// Returns the innermost loop which the given loop is part of, other | 50 /// Returns the innermost loop which the given continuation is part of, other |
51 /// than itself. | 51 /// than itself. |
52 Continuation getEnclosingLoop(Continuation loop) { | 52 Continuation getEnclosingLoop(Continuation cont) { |
53 return loopTarget[loop]; | 53 return loopTarget[cont]; |
asgerf
2015/11/05 12:13:42
The only "change" here is that we may now ask for
| |
54 } | 54 } |
55 | 55 |
56 /// Marks the innermost loop as a subloop of the other loop. | 56 /// Marks the innermost loop as a subloop of the other loop. |
57 /// | 57 /// |
58 /// Returns the innermost loop. | 58 /// Returns the innermost loop. |
59 /// | 59 /// |
60 /// Both continuations, [c1] and [c2] may be null (i.e. no loop). | 60 /// Both continuations, [c1] and [c2] may be null (i.e. no loop). |
61 /// | 61 /// |
62 /// A loop is said to be a subloop of an enclosing loop if it can invoke | 62 /// A loop is said to be a subloop of an enclosing loop if it can invoke |
63 /// that loop recursively. This information is stored in [loopTarget]. | 63 /// that loop recursively. This information is stored in [loopTarget]. |
64 /// | 64 /// |
65 /// This method is only invoked with two distinct loops if there is a | 65 /// This method is only invoked with two distinct loops if there is a |
66 /// point that can reach a recursive invocation of both loops. | 66 /// point that can reach a recursive invocation of both loops. |
67 /// This implies that one loop is nested in the other, because they must | 67 /// This implies that one loop is nested in the other, because they must |
68 /// both be in scope at that point. | 68 /// both be in scope at that point. |
69 Continuation _markInnerLoop(Continuation c1, Continuation c2) { | 69 Continuation _markInnerLoop(Continuation c1, Continuation c2) { |
70 assert(c1 == null || c1.isRecursive); | 70 assert(c1 == null || c1.isRecursive); |
71 assert(c2 == null || c2.isRecursive); | 71 assert(c2 == null || c2.isRecursive); |
72 if (c1 == null) return c2; | 72 if (c1 == null) return c2; |
73 if (c2 == null) return c1; | 73 if (c2 == null) return c1; |
74 if (c1 == c2) return c1; | 74 if (c1 == c2) return c1; |
75 if (loopDepth[c1] > loopDepth[c2]) { | 75 if (loopDepth[c1] > loopDepth[c2]) { |
76 loopTarget[c1] = _markInnerLoop(loopTarget[c1], c2); | 76 loopTarget[c1] = _markInnerLoop(loopTarget[c1], c2); |
77 return c1; | 77 return c1; |
78 } else { | 78 } else { |
79 loopTarget[c2] = _markInnerLoop(loopTarget[c2], c1); | 79 loopTarget[c2] = _markInnerLoop(loopTarget[c2], c1); |
80 return c2; | 80 return c2; |
81 } | 81 } |
82 } | 82 } |
83 | 83 |
84 /// Analyzes the body of [cont] and returns the innermost loop | 84 /// Analyzes the body of [cont] and returns the innermost loop |
85 /// that can be invoked recursively from [cont] (other than [cont] itself). | 85 /// that can be invoked recursively from [cont] (other than [cont] itself). |
86 /// | 86 /// |
87 /// [catchLoop] is the innermost loop that can be invoked recursively | 87 /// [catchLoop] is the innermost loop that can be invoked recursively |
88 /// from the current exception handler. | 88 /// from the current exception handler. |
89 Continuation _processContinuation(Continuation cont, Continuation catchLoop) { | 89 Continuation _processContinuation(Continuation cont, Continuation catchLoop) { |
90 if (cont.isRecursive) { | 90 if (cont.isRecursive) { |
91 ++currentDepth; | 91 ++currentDepth; |
92 loopDepth[cont] = currentDepth; | 92 loopDepth[cont] = currentDepth; |
93 Continuation target = _processBlock(cont.body, catchLoop); | 93 Continuation target = _processBlock(cont.body, catchLoop); |
94 _markInnerLoop(loopTarget[cont], target); | 94 _markInnerLoop(loopTarget[cont], target); |
95 --currentDepth; | 95 --currentDepth; |
96 } else { | 96 } else { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 target = _markInnerLoop(target, catchLoop); | 144 target = _markInnerLoop(target, catchLoop); |
145 for (Continuation cont in callContinuations) { | 145 for (Continuation cont in callContinuations) { |
146 // Store the loop target on each call continuation in the basic block. | 146 // Store the loop target on each call continuation in the basic block. |
147 // Because we walk over call continuations as part of the basic block | 147 // Because we walk over call continuations as part of the basic block |
148 // traversal, these do not get their loop target set otherwise. | 148 // traversal, these do not get their loop target set otherwise. |
149 loopTarget[cont] = target; | 149 loopTarget[cont] = target; |
150 } | 150 } |
151 return target; | 151 return target; |
152 } | 152 } |
153 } | 153 } |
OLD | NEW |