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

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

Issue 1458703007: dart2js cps: Refactor CallExpressions into Primitives. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Another minor fix Created 5 years, 1 month 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 cps_ir.optimization.insert_refinements; 5 library cps_ir.optimization.insert_refinements;
6 6
7 import 'optimizers.dart' show Pass; 7 import 'optimizers.dart' show Pass;
8 import 'cps_ir_nodes.dart'; 8 import 'cps_ir_nodes.dart';
9 import '../common/names.dart'; 9 import '../common/names.dart';
10 import '../types/types.dart' show TypeMask; 10 import '../types/types.dart' show TypeMask;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 } else { 68 } else {
69 let.remove(); // Reuse the existing LetCont. 69 let.remove(); // Reuse the existing LetCont.
70 } 70 }
71 let.insertAbove(use); 71 let.insertAbove(use);
72 } 72 }
73 73
74 Primitive unfoldInterceptor(Primitive prim) { 74 Primitive unfoldInterceptor(Primitive prim) {
75 return prim is Interceptor ? prim.input.definition : prim; 75 return prim is Interceptor ? prim.input.definition : prim;
76 } 76 }
77 77
78 /// Enqueues [cont] for processing in a context where [refined] is the 78 /// Sets [refined] to be the current refinement for its value, and pushes an
79 /// current refinement for its value. 79 /// action that will restore the original scope again.
80 void pushRefinement(Continuation cont, Refinement refined) { 80 ///
81 /// The refinement is inserted as the child of [insertionParent] if it has
82 /// at least one use after its scope has been processed.
83 void applyRefinement(InteriorNode insertionParent, Refinement refined) {
81 Primitive value = refined.effectiveDefinition; 84 Primitive value = refined.effectiveDefinition;
82 Primitive currentRefinement = refinementFor[value]; 85 Primitive currentRefinement = refinementFor[value];
86 refinementFor[value] = refined;
83 pushAction(() { 87 pushAction(() {
84 refinementFor[value] = currentRefinement; 88 refinementFor[value] = currentRefinement;
85 if (refined.hasNoUses) { 89 if (refined.hasNoUses) {
86 // Clean up refinements that are not used. 90 // Clean up refinements that are not used.
87 refined.destroy(); 91 refined.destroy();
88 } else { 92 } else {
89 LetPrim let = new LetPrim(refined); 93 LetPrim let = new LetPrim(refined);
90 let.insertBelow(cont); 94 let.insertBelow(insertionParent);
91 } 95 }
92 }); 96 });
93 push(cont); 97 }
98
99 /// Enqueues [cont] for processing in a context where [refined] is the
100 /// current refinement for its value.
101 void pushRefinement(Continuation cont, Refinement refined) {
94 pushAction(() { 102 pushAction(() {
95 refinementFor[value] = refined; 103 applyRefinement(cont, refined);
104 push(cont);
96 }); 105 });
97 } 106 }
98 107
99 void visitInvokeMethod(InvokeMethod node) { 108 void visitInvokeMethod(InvokeMethod node) {
100 Continuation cont = node.continuation.definition;
101
102 // Update references to their current refined values. 109 // Update references to their current refined values.
103 processReference(node.receiver); 110 processReference(node.receiver);
104 node.arguments.forEach(processReference); 111 node.arguments.forEach(processReference);
105 112
106 // If the call is intercepted, we want to refine the actual receiver, 113 // If the call is intercepted, we want to refine the actual receiver,
107 // not the interceptor. 114 // not the interceptor.
108 Primitive receiver = unfoldInterceptor(node.receiver.definition); 115 Primitive receiver = unfoldInterceptor(node.receiver.definition);
109 116
110 // Sink the continuation to the call to ensure everything in scope
111 // here is also in scope inside the continuations.
112 sinkContinuationToUse(cont, node);
113
114 if (node.selector.isClosureCall) { 117 if (node.selector.isClosureCall) {
115 // Do not try to refine the receiver of closure calls; the class world 118 // Do not try to refine the receiver of closure calls; the class world
Kevin Millikin (Google) 2015/11/23 10:22:44 Let's negate the condition of the if, get rid of t
asgerf 2015/11/23 10:48:57 Done.
116 // does not know about closure classes. 119 // does not know about closure classes.
117 push(cont);
118 } else { 120 } else {
119 // Filter away receivers that throw on this selector. 121 // Filter away receivers that throw on this selector.
120 TypeMask type = types.receiverTypeFor(node.selector, node.mask); 122 TypeMask type = types.receiverTypeFor(node.selector, node.mask);
121 Refinement refinement = new Refinement(receiver, type); 123 Refinement refinement = new Refinement(receiver, type);
122 pushRefinement(cont, refinement); 124 LetPrim letPrim = node.parent;
125 applyRefinement(letPrim, refinement);
123 } 126 }
124 } 127 }
125 128
126 void visitTypeCast(TypeCast node) { 129 void visitTypeCast(TypeCast node) {
127 Continuation cont = node.continuation.definition;
128 Primitive value = node.value.definition; 130 Primitive value = node.value.definition;
129 131
130 processReference(node.value); 132 processReference(node.value);
131 node.typeArguments.forEach(processReference); 133 node.typeArguments.forEach(processReference);
132 134
133 // Refine the type of the input. 135 // Refine the type of the input.
134 sinkContinuationToUse(cont, node);
135 TypeMask type = types.subtypesOf(node.dartType).nullable(); 136 TypeMask type = types.subtypesOf(node.dartType).nullable();
136 Refinement refinement = new Refinement(value, type); 137 Refinement refinement = new Refinement(value, type);
137 pushRefinement(cont, refinement); 138 LetPrim letPrim = node.parent;
139 applyRefinement(letPrim, refinement);
138 } 140 }
139 141
140 void visitRefinement(Refinement node) { 142 void visitRefinement(Refinement node) {
141 // We found a pre-existing refinement node. These are generated by the 143 // We found a pre-existing refinement node. These are generated by the
142 // IR builder to hold information from --trust-type-annotations. 144 // IR builder to hold information from --trust-type-annotations.
143 // Update its input to use our own current refinement, then update the 145 // Update its input to use our own current refinement, then update the
144 // environment to use this refinement. 146 // environment to use this refinement.
145 processReference(node.value); 147 processReference(node.value);
146 Primitive value = node.value.definition.effectiveDefinition; 148 Primitive value = node.value.definition.effectiveDefinition;
147 Primitive oldRefinement = refinementFor[value]; 149 Primitive oldRefinement = refinementFor[value];
148 refinementFor[value] = node; 150 refinementFor[value] = node;
149 pushAction(() { 151 pushAction(() {
150 refinementFor[value] = oldRefinement; 152 refinementFor[value] = oldRefinement;
151 }); 153 });
152 } 154 }
153 155
154 CallExpression getCallWithResult(Primitive prim) {
155 if (prim is Parameter && prim.parent is Continuation) {
156 Continuation cont = prim.parent;
157 if (cont.hasExactlyOneUse && cont.firstRef.parent is CallExpression) {
158 return cont.firstRef.parent;
159 }
160 }
161 return null;
162 }
163
164 bool isTrue(Primitive prim) { 156 bool isTrue(Primitive prim) {
165 return prim is Constant && prim.value.isTrue; 157 return prim is Constant && prim.value.isTrue;
166 } 158 }
167 159
168 void visitBranch(Branch node) { 160 void visitBranch(Branch node) {
169 processReference(node.condition); 161 processReference(node.condition);
170 Primitive condition = node.condition.definition; 162 Primitive condition = node.condition.definition;
171 CallExpression call = getCallWithResult(condition);
172 163
173 Continuation trueCont = node.trueContinuation.definition; 164 Continuation trueCont = node.trueContinuation.definition;
174 Continuation falseCont = node.falseContinuation.definition; 165 Continuation falseCont = node.falseContinuation.definition;
175 166
176 // Sink both continuations to the Branch to ensure everything in scope 167 // Sink both continuations to the Branch to ensure everything in scope
177 // here is also in scope inside the continuations. 168 // here is also in scope inside the continuations.
178 sinkContinuationToUse(trueCont, node); 169 sinkContinuationToUse(trueCont, node);
179 sinkContinuationToUse(falseCont, node); 170 sinkContinuationToUse(falseCont, node);
180 171
181 // If the condition is an 'is' check, promote the checked value. 172 // If the condition is an 'is' check, promote the checked value.
(...skipping 23 matching lines...) Expand all
205 Refinement refinedTrue = new Refinement(second, types.nullType); 196 Refinement refinedTrue = new Refinement(second, types.nullType);
206 Refinement refinedFalse = new Refinement(second, types.nonNullType); 197 Refinement refinedFalse = new Refinement(second, types.nonNullType);
207 pushRefinement(trueCont, refinedTrue); 198 pushRefinement(trueCont, refinedTrue);
208 pushRefinement(falseCont, refinedFalse); 199 pushRefinement(falseCont, refinedFalse);
209 } else { 200 } else {
210 push(trueCont); 201 push(trueCont);
211 push(falseCont); 202 push(falseCont);
212 } 203 }
213 } 204 }
214 205
215 if (call is InvokeMethod && call.selector == Selectors.equals) { 206 if (condition is InvokeMethod && condition.selector == Selectors.equals) {
216 refineEquality(call.arguments[0].definition, 207 refineEquality(condition.dartReceiver,
217 call.arguments[1].definition, 208 condition.dartArgument(0),
218 trueCont, 209 trueCont,
219 falseCont); 210 falseCont);
220 return; 211 return;
221 } 212 }
222 213
223 if (condition is ApplyBuiltinOperator && 214 if (condition is ApplyBuiltinOperator &&
224 condition.operator == BuiltinOperator.Identical) { 215 condition.operator == BuiltinOperator.Identical) {
225 refineEquality(condition.arguments[0].definition, 216 refineEquality(condition.arguments[0].definition,
226 condition.arguments[1].definition, 217 condition.arguments[1].definition,
227 trueCont, 218 trueCont,
228 falseCont); 219 falseCont);
229 return; 220 return;
230 } 221 }
231 222
232 push(trueCont); 223 push(trueCont);
233 push(falseCont); 224 push(falseCont);
234 } 225 }
235 226
236 @override 227 @override
237 Expression traverseLetCont(LetCont node) { 228 Expression traverseLetCont(LetCont node) {
238 for (Continuation cont in node.continuations) { 229 for (Continuation cont in node.continuations) {
239 if (cont.hasExactlyOneUse && 230 if (cont.hasExactlyOneUse && cont.firstRef.parent is Branch) {
240 (cont.firstRef.parent is InvokeMethod || 231 // Do not push the branch continuations here. visitBranch will do that.
Kevin Millikin (Google) 2015/11/23 10:22:44 Let's negate the condition, swap then and else, el
asgerf 2015/11/23 10:48:57 Done.
241 cont.firstRef.parent is TypeCast ||
242 cont.firstRef.parent is Branch)) {
243 // Do not push the continuation here.
244 // visitInvokeMethod, visitBranch, and visitTypeCast will do that.
245 } else { 232 } else {
246 push(cont); 233 push(cont);
247 } 234 }
248 } 235 }
249 return node.body; 236 return node.body;
250 } 237 }
251 } 238 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698