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

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

Issue 1313783003: dart2js cps: Generate interceptors at use-site and share afterwards. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Revert patch #3. I read Golem results backwards. Created 5 years, 3 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.let_sinking; 5 library dart2js.cps_ir.let_sinking;
6 6
7 import 'cps_ir_nodes.dart'; 7 import 'cps_ir_nodes.dart';
8 import 'optimizers.dart'; 8 import 'optimizers.dart';
9 import 'loop_hierarchy.dart';
9 10
10 /// Sinks single-use primitives to the use when this is safe and profitable. 11 /// Sinks single-use primitives to the use when this is safe and profitable.
11 /// 12 ///
12 /// To avoid sinking non-constant primitives into loops, this pass performs a 13 /// To avoid sinking non-constant primitives into loops, this pass performs a
13 /// control-flow analysis to determine the effective nesting of loops. 14 /// control-flow analysis to determine the effective nesting of loops.
14 /// 15 ///
15 /// In the example below, the value 'p' can be sunk to its use site in the 16 /// In the example below, the value 'p' can be sunk to its use site in the
16 /// 'else' branch because that branch is not effectively part of a loop, 17 /// 'else' branch because that branch is not effectively part of a loop,
17 /// despite being lexically nested in a recursive continuation. 18 /// despite being lexically nested in a recursive continuation.
18 /// 19 ///
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } 110 }
110 111
111 Expression getEnclosingExpression(Node node) { 112 Expression getEnclosingExpression(Node node) {
112 while (node is! Expression) { 113 while (node is! Expression) {
113 node = node.parent; 114 node = node.parent;
114 } 115 }
115 return node; 116 return node;
116 } 117 }
117 } 118 }
118 119
119 /// Determines the effective nesting of loops.
120 ///
121 /// The effective nesting of loops is different from the lexical nesting, since
122 /// recursive continuations can generally contain all the code following
123 /// after the loop in addition to the looping code itself.
124 ///
125 /// For example, the 'else' branch below is not effectively part of the loop:
126 ///
127 /// let rec kont x =
128 /// if (<loop condition>)
129 /// <loop body>
130 /// InvokeContinuation kont x'
131 /// else
132 /// <after loop>
133 /// return p.foo()
134 ///
135 /// We use the term "loop" to mean recursive continuation.
136 /// The `null` value is used to represent a context not part of any loop.
137 class LoopHierarchy {
138 /// Nesting depth of the given loop.
139 Map<Continuation, int> loopDepth = <Continuation, int>{};
140
141 /// The innermost loop (other than itself) that may be invoked recursively
142 /// as a result of invoking the given continuation.
143 Map<Continuation, Continuation> loopTarget = <Continuation, Continuation>{};
144
145 /// Current nesting depth.
146 int currentDepth = 0;
147
148 /// Computes the loop hierarchy for the given function.
149 ///
150 /// Parent pointers must be computed for [node].
151 LoopHierarchy(FunctionDefinition node) {
152 _processBlock(node.body, null);
153 }
154
155 /// Returns the innermost loop which [cont] is effectively part of.
156 Continuation getLoopHeader(Continuation cont) {
157 return cont.isRecursive ? cont : loopTarget[cont];
158 }
159
160 /// Marks the innermost loop as a subloop of the other loop.
161 ///
162 /// Returns the innermost loop.
163 ///
164 /// Both continuations, [c1] and [c2] may be null (i.e. no loop).
165 ///
166 /// A loop is said to be a subloop of an enclosing loop if it can invoke
167 /// that loop recursively. This information is stored in [loopTarget].
168 ///
169 /// This method is only invoked with two distinct loops if there is a
170 /// point that can reach a recursive invocation of both loops.
171 /// This implies that one loop is nested in the other, because they must
172 /// both be in scope at that point.
173 Continuation _markInnerLoop(Continuation c1, Continuation c2) {
174 assert(c1 == null || c1.isRecursive);
175 assert(c2 == null || c2.isRecursive);
176 if (c1 == null) return c2;
177 if (c2 == null) return c1;
178 if (c1 == c2) return c1;
179 if (loopDepth[c1] > loopDepth[c2]) {
180 loopTarget[c1] = _markInnerLoop(loopTarget[c1], c2);
181 return c1;
182 } else {
183 loopTarget[c2] = _markInnerLoop(loopTarget[c2], c1);
184 return c2;
185 }
186 }
187
188 /// Analyzes the body of [cont] and returns the innermost loop
189 /// that can be invoked recursively from [cont] (other than [cont] itself).
190 ///
191 /// [catchLoop] is the innermost loop that can be invoked recursively
192 /// from the current exception handler.
193 Continuation _processContinuation(Continuation cont, Continuation catchLoop) {
194 if (cont.isRecursive) {
195 ++currentDepth;
196 loopDepth[cont] = currentDepth;
197 Continuation target = _processBlock(cont.body, catchLoop);
198 _markInnerLoop(loopTarget[cont], target);
199 --currentDepth;
200 } else {
201 loopTarget[cont] = _processBlock(cont.body, catchLoop);
202 }
203 return loopTarget[cont];
204 }
205
206 bool _isCallContinuation(Continuation cont) {
207 return cont.hasExactlyOneUse && cont.firstRef.parent is CallExpression;
208 }
209
210 /// Analyzes a basic block and returns the innermost loop that
211 /// can be invoked recursively from that block.
212 Continuation _processBlock(Expression node, Continuation catchLoop) {
213 List<Continuation> callContinuations = <Continuation>[];
214 for (; node is! TailExpression; node = node.next) {
215 if (node is LetCont) {
216 for (Continuation cont in node.continuations) {
217 if (!_isCallContinuation(cont)) {
218 // Process non-call continuations at the binding site, so they
219 // their loop target is known at all use sites.
220 _processContinuation(cont, catchLoop);
221 } else {
222 // To avoid deep recursion, do not analyze call continuations
223 // recursively. This basic block traversal steps into the
224 // call contiunation after visiting its use site. We store the
225 // continuations in a list so we can set the loop target once
226 // it is known.
227 callContinuations.add(cont);
228 }
229 }
230 } else if (node is LetHandler) {
231 catchLoop = _processContinuation(node.handler, catchLoop);
232 }
233 }
234 Continuation target;
235 if (node is InvokeContinuation) {
236 if (node.isRecursive) {
237 target = node.continuation.definition;
238 } else {
239 target = loopTarget[node.continuation.definition];
240 }
241 } else if (node is Branch) {
242 target = _markInnerLoop(
243 loopTarget[node.trueContinuation.definition],
244 loopTarget[node.falseContinuation.definition]);
245 } else {
246 assert(node is Unreachable || node is Throw);
247 }
248 target = _markInnerLoop(target, catchLoop);
249 for (Continuation cont in callContinuations) {
250 // Store the loop target on each call continuation in the basic block.
251 // Because we walk over call continuations as part of the basic block
252 // traversal, these do not get their loop target set otherwise.
253 loopTarget[cont] = target;
254 }
255 return target;
256 }
257 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698