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

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: Rebase Created 5 years 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 117 // Do not try to refine the receiver of closure calls; the class world
111 // here is also in scope inside the continuations. 118 // does not know about closure classes.
112 sinkContinuationToUse(cont, node); 119 if (!node.selector.isClosureCall) {
113
114 if (node.selector.isClosureCall) {
115 // Do not try to refine the receiver of closure calls; the class world
116 // does not know about closure classes.
117 push(cont);
118 } else {
119 // Filter away receivers that throw on this selector. 120 // Filter away receivers that throw on this selector.
120 TypeMask type = types.receiverTypeFor(node.selector, node.mask); 121 TypeMask type = types.receiverTypeFor(node.selector, node.mask);
121 Refinement refinement = new Refinement(receiver, type); 122 Refinement refinement = new Refinement(receiver, type);
122 pushRefinement(cont, refinement); 123 LetPrim letPrim = node.parent;
124 applyRefinement(letPrim, refinement);
123 } 125 }
124 } 126 }
125 127
126 void visitTypeCast(TypeCast node) { 128 void visitTypeCast(TypeCast node) {
127 Continuation cont = node.continuation.definition;
128 Primitive value = node.value.definition; 129 Primitive value = node.value.definition;
129 130
130 processReference(node.value); 131 processReference(node.value);
131 node.typeArguments.forEach(processReference); 132 node.typeArguments.forEach(processReference);
132 133
133 // Refine the type of the input. 134 // Refine the type of the input.
134 sinkContinuationToUse(cont, node);
135 TypeMask type = types.subtypesOf(node.dartType).nullable(); 135 TypeMask type = types.subtypesOf(node.dartType).nullable();
136 Refinement refinement = new Refinement(value, type); 136 Refinement refinement = new Refinement(value, type);
137 pushRefinement(cont, refinement); 137 LetPrim letPrim = node.parent;
138 applyRefinement(letPrim, refinement);
138 } 139 }
139 140
140 void visitRefinement(Refinement node) { 141 void visitRefinement(Refinement node) {
141 // We found a pre-existing refinement node. These are generated by the 142 // We found a pre-existing refinement node. These are generated by the
142 // IR builder to hold information from --trust-type-annotations. 143 // IR builder to hold information from --trust-type-annotations.
143 // Update its input to use our own current refinement, then update the 144 // Update its input to use our own current refinement, then update the
144 // environment to use this refinement. 145 // environment to use this refinement.
145 processReference(node.value); 146 processReference(node.value);
146 Primitive value = node.value.definition.effectiveDefinition; 147 Primitive value = node.value.definition.effectiveDefinition;
147 Primitive oldRefinement = refinementFor[value]; 148 Primitive oldRefinement = refinementFor[value];
148 refinementFor[value] = node; 149 refinementFor[value] = node;
149 pushAction(() { 150 pushAction(() {
150 refinementFor[value] = oldRefinement; 151 refinementFor[value] = oldRefinement;
151 }); 152 });
152 } 153 }
153 154
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) { 155 bool isTrue(Primitive prim) {
165 return prim is Constant && prim.value.isTrue; 156 return prim is Constant && prim.value.isTrue;
166 } 157 }
167 158
168 void visitBranch(Branch node) { 159 void visitBranch(Branch node) {
169 processReference(node.condition); 160 processReference(node.condition);
170 Primitive condition = node.condition.definition; 161 Primitive condition = node.condition.definition;
171 CallExpression call = getCallWithResult(condition);
172 162
173 Continuation trueCont = node.trueContinuation.definition; 163 Continuation trueCont = node.trueContinuation.definition;
174 Continuation falseCont = node.falseContinuation.definition; 164 Continuation falseCont = node.falseContinuation.definition;
175 165
176 // Sink both continuations to the Branch to ensure everything in scope 166 // Sink both continuations to the Branch to ensure everything in scope
177 // here is also in scope inside the continuations. 167 // here is also in scope inside the continuations.
178 sinkContinuationToUse(trueCont, node); 168 sinkContinuationToUse(trueCont, node);
179 sinkContinuationToUse(falseCont, node); 169 sinkContinuationToUse(falseCont, node);
180 170
181 // If the condition is an 'is' check, promote the checked value. 171 // 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); 195 Refinement refinedTrue = new Refinement(second, types.nullType);
206 Refinement refinedFalse = new Refinement(second, types.nonNullType); 196 Refinement refinedFalse = new Refinement(second, types.nonNullType);
207 pushRefinement(trueCont, refinedTrue); 197 pushRefinement(trueCont, refinedTrue);
208 pushRefinement(falseCont, refinedFalse); 198 pushRefinement(falseCont, refinedFalse);
209 } else { 199 } else {
210 push(trueCont); 200 push(trueCont);
211 push(falseCont); 201 push(falseCont);
212 } 202 }
213 } 203 }
214 204
215 if (call is InvokeMethod && call.selector == Selectors.equals) { 205 if (condition is InvokeMethod && condition.selector == Selectors.equals) {
216 refineEquality(call.arguments[0].definition, 206 refineEquality(condition.dartReceiver,
217 call.arguments[1].definition, 207 condition.dartArgument(0),
218 trueCont, 208 trueCont,
219 falseCont); 209 falseCont);
220 return; 210 return;
221 } 211 }
222 212
223 if (condition is ApplyBuiltinOperator && 213 if (condition is ApplyBuiltinOperator &&
224 condition.operator == BuiltinOperator.Identical) { 214 condition.operator == BuiltinOperator.Identical) {
225 refineEquality(condition.arguments[0].definition, 215 refineEquality(condition.arguments[0].definition,
226 condition.arguments[1].definition, 216 condition.arguments[1].definition,
227 trueCont, 217 trueCont,
228 falseCont); 218 falseCont);
229 return; 219 return;
230 } 220 }
231 221
232 push(trueCont); 222 push(trueCont);
233 push(falseCont); 223 push(falseCont);
234 } 224 }
235 225
236 @override 226 @override
237 Expression traverseLetCont(LetCont node) { 227 Expression traverseLetCont(LetCont node) {
238 for (Continuation cont in node.continuations) { 228 for (Continuation cont in node.continuations) {
239 if (cont.hasExactlyOneUse && 229 // Do not push the branch continuations here. visitBranch will do that.
240 (cont.firstRef.parent is InvokeMethod || 230 if (!(cont.hasExactlyOneUse && cont.firstRef.parent is Branch)) {
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 {
246 push(cont); 231 push(cont);
247 } 232 }
248 } 233 }
249 return node.body; 234 return node.body;
250 } 235 }
251 } 236 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart ('k') | pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698