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

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

Issue 1743283002: dart2js cps: Use definitions by default, not references. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix long lines and use helpers that we already have Created 4 years, 9 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.optimize_interceptors; 5 library dart2js.cps_ir.optimize_interceptors;
6 6
7 import 'optimizers.dart'; 7 import 'optimizers.dart';
8 import 'cps_ir_nodes.dart'; 8 import 'cps_ir_nodes.dart';
9 import 'loop_hierarchy.dart'; 9 import 'loop_hierarchy.dart';
10 import 'cps_fragment.dart'; 10 import 'cps_fragment.dart';
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 130
131 /// True if [node] may return [JSNumber] instead of [JSInt] or [JSDouble]. 131 /// True if [node] may return [JSNumber] instead of [JSInt] or [JSDouble].
132 bool jsNumberClassSuffices(Interceptor node) { 132 bool jsNumberClassSuffices(Interceptor node) {
133 // No methods on JSNumber call 'down' to methods on JSInt or JSDouble. If 133 // No methods on JSNumber call 'down' to methods on JSInt or JSDouble. If
134 // all uses of the interceptor are for methods is defined only on JSNumber 134 // all uses of the interceptor are for methods is defined only on JSNumber
135 // then JSNumber will suffice in place of choosing between JSInt or 135 // then JSNumber will suffice in place of choosing between JSInt or
136 // JSDouble. 136 // JSDouble.
137 for (Reference ref = node.firstRef; ref != null; ref = ref.next) { 137 for (Reference ref = node.firstRef; ref != null; ref = ref.next) {
138 if (ref.parent is InvokeMethod) { 138 if (ref.parent is InvokeMethod) {
139 InvokeMethod invoke = ref.parent; 139 InvokeMethod invoke = ref.parent;
140 if (invoke.receiver != ref) return false; 140 if (invoke.receiverRef != ref) return false;
141 var interceptedClasses = 141 var interceptedClasses =
142 backend.getInterceptedClassesOn(invoke.selector.name); 142 backend.getInterceptedClassesOn(invoke.selector.name);
143 if (interceptedClasses.contains(helpers.jsDoubleClass)) return false; 143 if (interceptedClasses.contains(helpers.jsDoubleClass)) return false;
144 if (interceptedClasses.contains(helpers.jsIntClass)) return false; 144 if (interceptedClasses.contains(helpers.jsIntClass)) return false;
145 continue; 145 continue;
146 } 146 }
147 // Other uses need full distinction. 147 // Other uses need full distinction.
148 return false; 148 return false;
149 } 149 }
150 return true; 150 return true;
(...skipping 15 matching lines...) Expand all
166 } 166 }
167 return false; 167 return false;
168 } 168 }
169 169
170 /// Returns the only interceptor class that may be returned by [node], or 170 /// Returns the only interceptor class that may be returned by [node], or
171 /// `null` if no such class could be found. 171 /// `null` if no such class could be found.
172 ClassElement getSingleInterceptorClass(Interceptor node) { 172 ClassElement getSingleInterceptorClass(Interceptor node) {
173 // TODO(asgerf): This could be more precise if we used the use-site type, 173 // TODO(asgerf): This could be more precise if we used the use-site type,
174 // since the interceptor may have been hoisted out of a loop, where a less 174 // since the interceptor may have been hoisted out of a loop, where a less
175 // precise type is known. 175 // precise type is known.
176 Primitive input = node.input.definition; 176 Primitive input = node.input;
177 TypeMask type = input.type; 177 TypeMask type = input.type;
178 if (canInterceptNull(node)) return null; 178 if (canInterceptNull(node)) return null;
179 type = type.nonNullable(); 179 type = type.nonNullable();
180 if (typeSystem.isDefinitelyArray(type)) { 180 if (typeSystem.isDefinitelyArray(type)) {
181 return backend.helpers.jsArrayClass; 181 return backend.helpers.jsArrayClass;
182 } 182 }
183 if (typeSystem.isDefinitelyInt(type)) { 183 if (typeSystem.isDefinitelyInt(type)) {
184 return backend.helpers.jsIntClass; 184 return backend.helpers.jsIntClass;
185 } 185 }
186 if (typeSystem.isDefinitelyNum(type) && jsNumberClassSuffices(node)) { 186 if (typeSystem.isDefinitelyNum(type) && jsNumberClassSuffices(node)) {
187 return backend.helpers.jsNumberClass; 187 return backend.helpers.jsNumberClass;
188 } 188 }
189 ClassElement singleClass = type.singleClass(classWorld); 189 ClassElement singleClass = type.singleClass(classWorld);
190 if (singleClass != null && 190 if (singleClass != null &&
191 singleClass.isSubclassOf(backend.helpers.jsInterceptorClass)) { 191 singleClass.isSubclassOf(backend.helpers.jsInterceptorClass)) {
192 return singleClass; 192 return singleClass;
193 } 193 }
194 return null; 194 return null;
195 } 195 }
196 196
197 /// Try to replace [interceptor] with a constant, and return `true` if 197 /// Try to replace [interceptor] with a constant, and return `true` if
198 /// successful. 198 /// successful.
199 bool constifyInterceptor(Interceptor interceptor) { 199 bool constifyInterceptor(Interceptor interceptor) {
200 LetPrim let = interceptor.parent; 200 LetPrim let = interceptor.parent;
201 Primitive input = interceptor.input.definition; 201 Primitive input = interceptor.input;
202 ClassElement classElement = getSingleInterceptorClass(interceptor); 202 ClassElement classElement = getSingleInterceptorClass(interceptor);
203 203
204 if (classElement == null) return false; 204 if (classElement == null) return false;
205 ConstantValue constant = new InterceptorConstantValue(classElement.rawType); 205 ConstantValue constant = new InterceptorConstantValue(classElement.rawType);
206 206
207 if (!input.type.isNullable) { 207 if (!input.type.isNullable) {
208 Primitive constantPrim = makeConstantFor(constant, 208 Primitive constantPrim = makeConstantFor(constant,
209 useSite: let, 209 useSite: let,
210 type: interceptor.type, 210 type: interceptor.type,
211 sourceInformation: interceptor.sourceInformation); 211 sourceInformation: interceptor.sourceInformation);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 if (node.hasExactlyOneUse) { 254 if (node.hasExactlyOneUse) {
255 // Set the loop header on single-use interceptors so [visitInvokeMethod] 255 // Set the loop header on single-use interceptors so [visitInvokeMethod]
256 // can determine if it should become a one-shot interceptor. 256 // can determine if it should become a one-shot interceptor.
257 loopHeaderFor[node] = currentLoopHeader; 257 loopHeaderFor[node] = currentLoopHeader;
258 } 258 }
259 } 259 }
260 260
261 @override 261 @override
262 void visitInvokeMethod(InvokeMethod node) { 262 void visitInvokeMethod(InvokeMethod node) {
263 if (node.callingConvention != CallingConvention.Intercepted) return; 263 if (node.callingConvention != CallingConvention.Intercepted) return;
264 Primitive interceptor = node.receiver.definition; 264 Primitive interceptor = node.receiver;
265 if (interceptor is! Interceptor || 265 if (interceptor is! Interceptor ||
266 interceptor.hasMultipleUses || 266 interceptor.hasMultipleUses ||
267 loopHeaderFor[interceptor] != currentLoopHeader) { 267 loopHeaderFor[interceptor] != currentLoopHeader) {
268 return; 268 return;
269 } 269 }
270 // TODO(asgerf): Consider heuristics for when to use one-shot interceptors. 270 // TODO(asgerf): Consider heuristics for when to use one-shot interceptors.
271 // E.g. using only one-shot interceptors with a fast path. 271 // E.g. using only one-shot interceptors with a fast path.
272 node.callingConvention = CallingConvention.OneShotIntercepted; 272 node.callingConvention = CallingConvention.OneShotIntercepted;
273 node..receiver.unlink()..receiver = node.arguments.removeAt(0); 273 node..receiverRef.unlink()..receiverRef = node.argumentRefs.removeAt(0);
274 } 274 }
275 275
276 @override 276 @override
277 void visitTypeTestViaFlag(TypeTestViaFlag node) { 277 void visitTypeTestViaFlag(TypeTestViaFlag node) {
278 Primitive interceptor = node.interceptor.definition; 278 Primitive interceptor = node.interceptor;
279 if (interceptor is! Interceptor || 279 if (interceptor is! Interceptor ||
280 interceptor.hasMultipleUses || 280 interceptor.hasMultipleUses ||
281 loopHeaderFor[interceptor] != currentLoopHeader || 281 loopHeaderFor[interceptor] != currentLoopHeader ||
282 !backend.mayGenerateInstanceofCheck(node.dartType)) { 282 !backend.mayGenerateInstanceofCheck(node.dartType)) {
283 return; 283 return;
284 } 284 }
285 Interceptor inter = interceptor; 285 Interceptor inter = interceptor;
286 Primitive value = inter.input.definition; 286 Primitive value = inter.input;
287 node.replaceWith(new TypeTest(value, node.dartType, [])..type = node.type); 287 node.replaceWith(new TypeTest(value, node.dartType, [])..type = node.type);
288 } 288 }
289 } 289 }
290 290
291 /// Shares interceptor constants when one is in scope of another. 291 /// Shares interceptor constants when one is in scope of another.
292 /// 292 ///
293 /// Interceptor optimization runs after GVN, hence this clean-up step is needed. 293 /// Interceptor optimization runs after GVN, hence this clean-up step is needed.
294 /// 294 ///
295 /// TODO(asgerf): Handle in separate constant optimization pass? With some other 295 /// TODO(asgerf): Handle in separate constant optimization pass? With some other
296 /// constant-related optimizations, like cloning small constants at use-site. 296 /// constant-related optimizations, like cloning small constants at use-site.
(...skipping 17 matching lines...) Expand all
314 sharedConstantFor.remove(prim.value); 314 sharedConstantFor.remove(prim.value);
315 }); 315 });
316 } 316 }
317 return next; 317 return next;
318 } 318 }
319 319
320 bool shouldShareConstant(Constant constant) { 320 bool shouldShareConstant(Constant constant) {
321 return constant.value.isInterceptor; 321 return constant.value.isInterceptor;
322 } 322 }
323 } 323 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698