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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart

Issue 1573693002: dart2js cps: Hoist loop-invariant branches from loop entry. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Remove self-import Created 4 years, 11 months 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 unified diff | Download patch
OLDNEW
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 import 'cps_fragment.dart';
8 9
9 /// Determines the effective nesting of loops. 10 /// Determines the effective nesting of loops.
10 /// 11 ///
11 /// The effective nesting of loops is different from the lexical nesting, since 12 /// The effective nesting of loops is different from the lexical nesting, since
12 /// recursive continuations can generally contain all the code following 13 /// recursive continuations can generally contain all the code following
13 /// after the loop in addition to the looping code itself. 14 /// after the loop in addition to the looping code itself.
14 /// 15 ///
15 /// For example, the 'else' branch below is not effectively part of the loop: 16 /// For example, the 'else' branch below is not effectively part of the loop:
16 /// 17 ///
17 /// let rec kont x = 18 /// let rec kont x =
18 /// if (<loop condition>) 19 /// if (<loop condition>)
19 /// <loop body> 20 /// <loop body>
20 /// InvokeContinuation kont x' 21 /// InvokeContinuation kont x'
21 /// else 22 /// else
22 /// <after loop> 23 /// <after loop>
23 /// return p.foo() 24 /// return p.foo()
24 /// 25 ///
25 /// We use the term "loop" to mean recursive continuation. 26 /// We use the term "loop" to mean recursive continuation.
26 /// The `null` value is used to represent a context not part of any loop. 27 /// The `null` value is used to represent a context not part of any loop.
27 class LoopHierarchy { 28 class LoopHierarchy {
28 /// Nesting depth of the given loop. 29 /// Nesting depth of the given loop.
29 Map<Continuation, int> loopDepth = <Continuation, int>{}; 30 Map<Continuation, int> loopDepth = <Continuation, int>{};
30 31
31 /// The innermost loop (other than itself) that may be invoked recursively 32 /// The innermost loop (other than itself) that may be invoked recursively
32 /// as a result of invoking the given continuation. 33 /// as a result of invoking the given continuation.
33 Map<Continuation, Continuation> loopTarget = <Continuation, Continuation>{}; 34 Map<Continuation, Continuation> loopTarget = <Continuation, Continuation>{};
34 35
35 /// Current nesting depth. 36 /// Current nesting depth.
36 int currentDepth = 0; 37 int _currentDepth = 0;
38
39 /// The loop target to use for missing code. Used by [update].
40 Continuation _exitLoop;
37 41
38 /// Computes the loop hierarchy for the given function. 42 /// Computes the loop hierarchy for the given function.
39 /// 43 ///
40 /// Parent pointers must be computed for [node]. 44 /// Parent pointers must be computed for [node].
41 LoopHierarchy(FunctionDefinition node) { 45 LoopHierarchy(FunctionDefinition node) {
42 _processBlock(node.body, null); 46 _processBlock(node.body, null);
43 } 47 }
44 48
45 /// Returns the innermost loop which [cont] is effectively part of. 49 /// Returns the innermost loop which [cont] is effectively part of.
46 Continuation getLoopHeader(Continuation cont) { 50 Continuation getLoopHeader(Continuation cont) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 } 85 }
82 } 86 }
83 87
84 /// Analyzes the body of [cont] and returns the innermost loop 88 /// Analyzes the body of [cont] and returns the innermost loop
85 /// that can be invoked recursively from [cont] (other than [cont] itself). 89 /// that can be invoked recursively from [cont] (other than [cont] itself).
86 /// 90 ///
87 /// [catchLoop] is the innermost loop that can be invoked recursively 91 /// [catchLoop] is the innermost loop that can be invoked recursively
88 /// from the current exception handler. 92 /// from the current exception handler.
89 Continuation _processContinuation(Continuation cont, Continuation catchLoop) { 93 Continuation _processContinuation(Continuation cont, Continuation catchLoop) {
90 if (cont.isRecursive) { 94 if (cont.isRecursive) {
91 ++currentDepth; 95 ++_currentDepth;
92 loopDepth[cont] = currentDepth; 96 loopDepth[cont] = _currentDepth;
93 Continuation target = _processBlock(cont.body, catchLoop); 97 Continuation target = _processBlock(cont.body, catchLoop);
94 _markInnerLoop(loopTarget[cont], target); 98 _markInnerLoop(loopTarget[cont], target);
95 --currentDepth; 99 --_currentDepth;
96 } else { 100 } else {
97 loopTarget[cont] = _processBlock(cont.body, catchLoop); 101 loopTarget[cont] = _processBlock(cont.body, catchLoop);
98 } 102 }
99 return loopTarget[cont]; 103 return loopTarget[cont];
100 } 104 }
101 105
102 /// Analyzes a basic block and returns the innermost loop that 106 /// Analyzes a basic block and returns the innermost loop that
103 /// can be invoked recursively from that block. 107 /// can be invoked recursively from that block.
104 Continuation _processBlock(Expression node, Continuation catchLoop) { 108 Continuation _processBlock(Expression node, Continuation catchLoop) {
105 for (; node is! TailExpression; node = node.next) { 109 for (; node != null && node is! TailExpression; node = node.next) {
106 if (node is LetCont) { 110 if (node is LetCont) {
107 for (Continuation cont in node.continuations) { 111 for (Continuation cont in node.continuations) {
108 _processContinuation(cont, catchLoop); 112 _processContinuation(cont, catchLoop);
109 } 113 }
110 } else if (node is LetHandler) { 114 } else if (node is LetHandler) {
111 catchLoop = _processContinuation(node.handler, catchLoop); 115 catchLoop = _processContinuation(node.handler, catchLoop);
112 } 116 }
113 } 117 }
114 Continuation target; 118 Continuation target;
115 if (node is InvokeContinuation) { 119 if (node is InvokeContinuation) {
116 if (node.isRecursive) { 120 if (node.isRecursive) {
117 target = node.continuation.definition; 121 target = node.continuation.definition;
118 } else { 122 } else {
119 target = loopTarget[node.continuation.definition]; 123 target = loopTarget[node.continuation.definition];
120 } 124 }
121 } else if (node is Branch) { 125 } else if (node is Branch) {
122 target = _markInnerLoop( 126 target = _markInnerLoop(
123 loopTarget[node.trueContinuation.definition], 127 loopTarget[node.trueContinuation.definition],
124 loopTarget[node.falseContinuation.definition]); 128 loopTarget[node.falseContinuation.definition]);
129 } else if (node == null) {
130 // If the code ends abruptly, use the exit loop provided in [update].
131 target = _exitLoop;
125 } else { 132 } else {
126 assert(node is Unreachable || node is Throw); 133 assert(node is Unreachable || node is Throw || node == null);
127 } 134 }
128 return _markInnerLoop(target, catchLoop); 135 return _markInnerLoop(target, catchLoop);
129 } 136 }
130 137
131 /// Returns the the innermost loop that effectively encloses both 138 /// Returns the the innermost loop that effectively encloses both
132 /// c1 and c2 (or `null` if there is no such loop). 139 /// c1 and c2 (or `null` if there is no such loop).
133 Continuation lowestCommonAncestor(Continuation c1, Continuation c2) { 140 Continuation lowestCommonAncestor(Continuation c1, Continuation c2) {
134 int d1 = getDepth(c1), d2 = getDepth(c2); 141 int d1 = getDepth(c1), d2 = getDepth(c2);
135 while (c1 != c2) { 142 while (c1 != c2) {
136 if (d1 <= d2) { 143 if (d1 <= d2) {
137 c2 = getEnclosingLoop(c2); 144 c2 = getEnclosingLoop(c2);
138 d2 = getDepth(c2); 145 d2 = getDepth(c2);
139 } else { 146 } else {
140 c1 = getEnclosingLoop(c1); 147 c1 = getEnclosingLoop(c1);
141 d1 = getDepth(c1); 148 d1 = getDepth(c1);
142 } 149 }
143 } 150 }
144 return c1; 151 return c1;
145 } 152 }
146 153
147 /// Returns the lexical nesting depth of [loop]. 154 /// Returns the lexical nesting depth of [loop].
148 int getDepth(Continuation loop) { 155 int getDepth(Continuation loop) {
149 if (loop == null) return 0; 156 if (loop == null) return 0;
150 return loopDepth[loop]; 157 return loopDepth[loop];
151 } 158 }
159
160 /// Sets the loop header for each continuation bound inside the given
161 /// fragment.
162 ///
163 /// If the fragment is open, [exitLoop] denotes the loop header for
164 /// the code that will occur after the fragment.
165 ///
166 /// [catchLoop] is the loop target for the catch clause of the try/catch
167 /// surrounding the inserted fragment.
168 void update(CpsFragment fragment,
169 {Continuation exitLoop,
170 Continuation catchLoop}) {
171 if (fragment.isEmpty) return;
172 _exitLoop = exitLoop;
173 _currentDepth = getDepth(exitLoop);
174 _processBlock(fragment.root, catchLoop);
175 _exitLoop = null;
176 }
152 } 177 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart ('k') | pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698