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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/loop_hierarchy.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
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.loop_hierarchy;
6 6
7 import 'cps_ir_nodes.dart'; 7 import 'cps_ir_nodes.dart';
8 import 'optimizers.dart';
9
10 /// Sinks single-use primitives to the use when this is safe and profitable.
11 ///
12 /// To avoid sinking non-constant primitives into loops, this pass performs a
13 /// control-flow analysis to determine the effective nesting of loops.
14 ///
15 /// 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 /// despite being lexically nested in a recursive continuation.
18 ///
19 /// let prim p = getInterceptor(<something>)
20 /// let rec kont x =
21 /// if (<loop condition>)
22 /// <loop body>
23 /// InvokeContinuation kont x'
24 /// else
25 /// <after loop>
26 /// return p.foo()
27 ///
28 class LetSinker extends RecursiveVisitor implements Pass {
29 String get passName => 'Let sinking';
30
31 LoopHierarchy loopHierarchy;
32 List<Continuation> stack = <Continuation>[];
33
34 /// Maps a sinkable primitive to its loop header.
35 Map<Primitive, Continuation> loopHeaderForPrimitive =
36 <Primitive, Continuation>{};
37
38 Continuation currentLoopHeader;
39
40 void rewrite(FunctionDefinition node) {
41 new ParentVisitor().visit(node);
42 loopHierarchy = new LoopHierarchy(node);
43 visit(node.body);
44 }
45
46 @override
47 Expression traverseLetPrim(LetPrim node) {
48 Primitive prim = node.primitive;
49 if (prim.hasExactlyOneUse && prim.isSafeForReordering) {
50 // This can potentially be sunk. Register the loop header, so when we
51 // find the use site, we can check if they are in the same loop.
52 loopHeaderForPrimitive[prim] = currentLoopHeader;
53 pushAction(() {
54 if (node.primitive != null) {
55 // The primitive could not be sunk. Try to sink dependencies here.
56 visit(node.primitive);
57 } else {
58 // The primitive was sunk. Destroy the old LetPrim.
59 InteriorNode parent = node.parent;
60 parent.body = node.body;
61 node.body.parent = parent;
62 }
63 });
64 } else {
65 visit(node.primitive);
66 }
67
68 // Visit the body, wherein this primitive may be sunk to its use site.
69 return node.body;
70 }
71
72 @override
73 Expression traverseContinuation(Continuation cont) {
74 Continuation oldLoopHeader = currentLoopHeader;
75 pushAction(() {
76 currentLoopHeader = oldLoopHeader;
77 });
78 currentLoopHeader = loopHierarchy.getLoopHeader(cont);
79 return cont.body;
80 }
81
82 void processReference(Reference ref) {
83 Definition definition = ref.definition;
84 if (definition is Primitive &&
85 definition is! Parameter &&
86 definition.hasExactlyOneUse &&
87 definition.isSafeForReordering) {
88 // Check if use is in the same loop.
89 Continuation bindingLoop = loopHeaderForPrimitive.remove(definition);
90 if (bindingLoop == currentLoopHeader || definition is Constant) {
91 // Sink the definition.
92
93 Expression use = getEnclosingExpression(ref.parent);
94 LetPrim binding = definition.parent;
95 binding.primitive = null; // Mark old binding for deletion.
96 LetPrim newBinding = new LetPrim(definition);
97 definition.parent = newBinding;
98 InteriorNode useParent = use.parent;
99 useParent.body = newBinding;
100 newBinding.body = use;
101 use.parent = newBinding;
102 newBinding.parent = useParent;
103
104 // Now that the final binding location has been found, sink the
105 // dependencies of the definition down here as well.
106 visit(definition);
107 }
108 }
109 }
110
111 Expression getEnclosingExpression(Node node) {
112 while (node is! Expression) {
113 node = node.parent;
114 }
115 return node;
116 }
117 }
118 8
119 /// Determines the effective nesting of loops. 9 /// Determines the effective nesting of loops.
120 /// 10 ///
121 /// 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
122 /// recursive continuations can generally contain all the code following 12 /// recursive continuations can generally contain all the code following
123 /// after the loop in addition to the looping code itself. 13 /// after the loop in addition to the looping code itself.
124 /// 14 ///
125 /// 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:
126 /// 16 ///
127 /// let rec kont x = 17 /// let rec kont x =
(...skipping 22 matching lines...) Expand all
150 /// Parent pointers must be computed for [node]. 40 /// Parent pointers must be computed for [node].
151 LoopHierarchy(FunctionDefinition node) { 41 LoopHierarchy(FunctionDefinition node) {
152 _processBlock(node.body, null); 42 _processBlock(node.body, null);
153 } 43 }
154 44
155 /// Returns the innermost loop which [cont] is effectively part of. 45 /// Returns the innermost loop which [cont] is effectively part of.
156 Continuation getLoopHeader(Continuation cont) { 46 Continuation getLoopHeader(Continuation cont) {
157 return cont.isRecursive ? cont : loopTarget[cont]; 47 return cont.isRecursive ? cont : loopTarget[cont];
158 } 48 }
159 49
50 /// Returns the innermost loop which the given loop is part of, other
51 /// than itself.
52 Continuation getEnclosingLoop(Continuation loop) {
53 return loopTarget[loop];
54 }
55
160 /// Marks the innermost loop as a subloop of the other loop. 56 /// Marks the innermost loop as a subloop of the other loop.
161 /// 57 ///
162 /// Returns the innermost loop. 58 /// Returns the innermost loop.
163 /// 59 ///
164 /// 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).
165 /// 61 ///
166 /// 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
167 /// that loop recursively. This information is stored in [loopTarget]. 63 /// that loop recursively. This information is stored in [loopTarget].
168 /// 64 ///
169 /// 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
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 target = _markInnerLoop(target, catchLoop); 144 target = _markInnerLoop(target, catchLoop);
249 for (Continuation cont in callContinuations) { 145 for (Continuation cont in callContinuations) {
250 // 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.
251 // 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
252 // traversal, these do not get their loop target set otherwise. 148 // traversal, these do not get their loop target set otherwise.
253 loopTarget[cont] = target; 149 loopTarget[cont] = target;
254 } 150 }
255 return target; 151 return target;
256 } 152 }
257 } 153 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/let_sinking.dart ('k') | pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698