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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/optimize.dart

Issue 11308169: GVN getInterceptor and use the interceptor constant when the type is known. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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 | Annotate | Revision Log
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/nodes.dart ('k') | no next file » | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of ssa; 5 part of ssa;
6 6
7 abstract class OptimizationPhase { 7 abstract class OptimizationPhase {
8 String get name; 8 String get name;
9 void visitGraph(HGraph graph); 9 void visitGraph(HGraph graph);
10 } 10 }
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 } 204 }
205 return node; 205 return node;
206 } 206 }
207 207
208 HInstruction handleInterceptorCall(HInvokeDynamic node) { 208 HInstruction handleInterceptorCall(HInvokeDynamic node) {
209 HInstruction input = node.inputs[1]; 209 HInstruction input = node.inputs[1];
210 if (input.isString(types) 210 if (input.isString(types)
211 && node.selector.name == const SourceString('toString')) { 211 && node.selector.name == const SourceString('toString')) {
212 return node.inputs[1]; 212 return node.inputs[1];
213 } 213 }
214 // Check if this call does not need to be intercepted.
215 HType type = types[input];
216 var interceptor = node.inputs[0];
217 if (node is HInvokeDynamicMethod
218 && interceptor is !HThis
219 && !type.canBePrimitive()) {
220 // If the type can be null, and the intercepted method can be in
221 // the object class, keep the interceptor.
222 if (type.canBeNull()
223 && interceptor.interceptedClasses.contains(compiler.objectClass)) {
224 return node;
225 }
226 // Change the call to a regular invoke dynamic call.
227 return new HInvokeDynamicMethod(
228 node.selector, node.inputs.getRange(1, node.inputs.length - 1));
229 }
214 return node; 230 return node;
215 } 231 }
216 232
217 bool isFixedSizeListConstructor(HInvokeStatic node) { 233 bool isFixedSizeListConstructor(HInvokeStatic node) {
218 Element element = node.target.element; 234 Element element = node.target.element;
219 return element.getEnclosingClass() == compiler.listClass 235 return element.getEnclosingClass() == compiler.listClass
220 && node.inputs.length == 2 236 && node.inputs.length == 2
221 && node.inputs[1].isInteger(types); 237 && node.inputs[1].isInteger(types);
222 } 238 }
223 239
(...skipping 19 matching lines...) Expand all
243 node.element = element; 259 node.element = element;
244 } 260 }
245 // TODO(ngeoffray): If the method has optional parameters, 261 // TODO(ngeoffray): If the method has optional parameters,
246 // we should pass the default values here. 262 // we should pass the default values here.
247 } 263 }
248 } 264 }
249 } 265 }
250 return node; 266 return node;
251 } 267 }
252 268
253 HInstruction fromInterceptorToDynamicInvocation(HInvokeStatic node, 269 HInstruction fromNativeToDynamicInvocation(HInvokeStatic node,
254 Selector selector) { 270 Selector selector) {
255 HBoundedType type = types[node.inputs[1]]; 271 HBoundedType type = types[node.inputs[1]];
256 HInvokeDynamicMethod result = new HInvokeDynamicMethod( 272 HInvokeDynamicMethod result = new HInvokeDynamicMethod(
257 selector, 273 selector,
258 node.inputs.getRange(1, node.inputs.length - 1)); 274 node.inputs.getRange(1, node.inputs.length - 1));
259 if (type.isExact()) { 275 if (type.isExact()) {
260 HBoundedType concrete = type; 276 HBoundedType concrete = type;
261 result.element = concrete.lookupMember(selector.name); 277 result.element = concrete.lookupMember(selector.name);
262 } 278 }
263 return result; 279 return result;
264 } 280 }
265 281
266 HInstruction visitIntegerCheck(HIntegerCheck node) { 282 HInstruction visitIntegerCheck(HIntegerCheck node) {
267 HInstruction value = node.value; 283 HInstruction value = node.value;
268 if (value.isInteger(types)) return value; 284 if (value.isInteger(types)) return value;
269 if (value.isConstant()) { 285 if (value.isConstant()) {
270 HConstant constantInstruction = value; 286 HConstant constantInstruction = value;
271 assert(!constantInstruction.constant.isInt()); 287 assert(!constantInstruction.constant.isInt());
272 if (!constantSystem.isInt(constantInstruction.constant)) { 288 if (!constantSystem.isInt(constantInstruction.constant)) {
273 // -0.0 is a double but will pass the runtime integer check. 289 // -0.0 is a double but will pass the runtime integer check.
274 node.alwaysFalse = true; 290 node.alwaysFalse = true;
275 } 291 }
276 } 292 }
277 return node; 293 return node;
278 } 294 }
279 295
280 296
281 HInstruction visitIndex(HIndex node) { 297 HInstruction visitIndex(HIndex node) {
282 if (!node.receiver.canBePrimitive(types)) { 298 if (!node.receiver.canBePrimitive(types)) {
283 Selector selector = new Selector.index(); 299 Selector selector = new Selector.index();
284 return fromInterceptorToDynamicInvocation(node, selector); 300 return fromNativeToDynamicInvocation(node, selector);
285 } 301 }
286 return node; 302 return node;
287 } 303 }
288 304
289 HInstruction visitIndexAssign(HIndexAssign node) { 305 HInstruction visitIndexAssign(HIndexAssign node) {
290 if (!node.receiver.canBePrimitive(types)) { 306 if (!node.receiver.canBePrimitive(types)) {
291 Selector selector = new Selector.indexSet(); 307 Selector selector = new Selector.indexSet();
292 return fromInterceptorToDynamicInvocation(node, selector); 308 return fromNativeToDynamicInvocation(node, selector);
293 } 309 }
294 return node; 310 return node;
295 } 311 }
296 312
297 HInstruction visitInvokeBinary(HInvokeBinary node) { 313 HInstruction visitInvokeBinary(HInvokeBinary node) {
298 HInstruction left = node.left; 314 HInstruction left = node.left;
299 HInstruction right = node.right; 315 HInstruction right = node.right;
300 BinaryOperation operation = node.operation(constantSystem); 316 BinaryOperation operation = node.operation(constantSystem);
301 if (left is HConstant && right is HConstant) { 317 if (left is HConstant && right is HConstant) {
302 HConstant op1 = left; 318 HConstant op1 = left;
303 HConstant op2 = right; 319 HConstant op2 = right;
304 Constant folded = operation.fold(op1.constant, op2.constant); 320 Constant folded = operation.fold(op1.constant, op2.constant);
305 if (folded != null) return graph.addConstant(folded); 321 if (folded != null) return graph.addConstant(folded);
306 } 322 }
307 323
308 if (!left.canBePrimitive(types) 324 if (!left.canBePrimitive(types)
309 && operation.isUserDefinable() 325 && operation.isUserDefinable()
310 // The equals operation is being optimized in visitEquals. 326 // The equals operation is being optimized in visitEquals.
311 && node is! HEquals) { 327 && node is! HEquals) {
312 Selector selector = new Selector.binaryOperator(operation.name); 328 Selector selector = new Selector.binaryOperator(operation.name);
313 return fromInterceptorToDynamicInvocation(node, selector); 329 return fromNativeToDynamicInvocation(node, selector);
314 } 330 }
315 return node; 331 return node;
316 } 332 }
317 333
318 bool allUsersAreBoolifies(HInstruction instruction) { 334 bool allUsersAreBoolifies(HInstruction instruction) {
319 List<HInstruction> users = instruction.usedBy; 335 List<HInstruction> users = instruction.usedBy;
320 int length = users.length; 336 int length = users.length;
321 for (int i = 0; i < length; i++) { 337 for (int i = 0; i < length; i++) {
322 if (users[i] is! HBoolify) return false; 338 if (users[i] is! HBoolify) return false;
323 } 339 }
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 for (int i = 0; i < node.inputs.length; i++) { 665 for (int i = 0; i < node.inputs.length; i++) {
650 HInstruction part = node.inputs[i]; 666 HInstruction part = node.inputs[i];
651 if (!part.isConstant()) return node; 667 if (!part.isConstant()) return node;
652 HConstant constant = part; 668 HConstant constant = part;
653 if (!constant.constant.isPrimitive()) return node; 669 if (!constant.constant.isPrimitive()) return node;
654 PrimitiveConstant primitive = constant.constant; 670 PrimitiveConstant primitive = constant.constant;
655 folded = new DartString.concat(folded, primitive.toDartString()); 671 folded = new DartString.concat(folded, primitive.toDartString());
656 } 672 }
657 return graph.addConstant(constantSystem.createString(folded, node.node)); 673 return graph.addConstant(constantSystem.createString(folded, node.node));
658 } 674 }
675
676 HInstruction visitInterceptor(HInterceptor node) {
677 if (node.isConstant()) return node;
678 HType type = types[node.inputs[0]];
679 Element constantInterceptor;
680 if (type.isInteger()) {
681 constantInterceptor = backend.intInterceptor;
682 } else if (type.isDouble()) {
683 constantInterceptor = backend.doubleInterceptor;
684 } else if (type.isBoolean()) {
685 constantInterceptor = backend.boolInterceptor;
686 } else if (type.isString()) {
687 constantInterceptor = backend.stringInterceptor;
688 } else if (type.isArray()) {
689 constantInterceptor = backend.arrayInterceptor;
690 } else if (type.isNull()) {
691 constantInterceptor = backend.nullInterceptor;
692 } else if (type.isNumber()) {
693 Set<ClassElement> intercepted = node.interceptedClasses;
694 // If the method being intercepted is not defined in [int] or
695 // [double] we can safely use the number interceptor.
696 if (!intercepted.contains(compiler.intClass)
697 && !intercepted.contains(compiler.doubleClass)) {
698 constantInterceptor = backend.numberInterceptor;
699 }
700 }
701
702 if (constantInterceptor == null) return node;
703
704 ConstantHandler handler = compiler.constantHandler;
705 return graph.addConstant(handler.compileVariable(constantInterceptor));
706 }
659 } 707 }
660 708
661 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { 709 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
662 final HTypeMap types; 710 final HTypeMap types;
663 final ConstantSystem constantSystem; 711 final ConstantSystem constantSystem;
664 final Set<HInstruction> boundsChecked; 712 final Set<HInstruction> boundsChecked;
665 final WorkItem work; 713 final WorkItem work;
666 final String name = "SsaCheckInserter"; 714 final String name = "SsaCheckInserter";
667 HGraph graph; 715 HGraph graph;
668 Element lengthInterceptor; 716 Element lengthInterceptor;
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 } 1401 }
1354 1402
1355 // For other fields having setters in the generative constructor body, set 1403 // For other fields having setters in the generative constructor body, set
1356 // the type to UNKNOWN to avoid relying on the type set in the initializer 1404 // the type to UNKNOWN to avoid relying on the type set in the initializer
1357 // list. 1405 // list.
1358 allSetters.forEach((Element element) { 1406 allSetters.forEach((Element element) {
1359 backend.registerFieldConstructor(element, HType.UNKNOWN); 1407 backend.registerFieldConstructor(element, HType.UNKNOWN);
1360 }); 1408 });
1361 } 1409 }
1362 } 1410 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/nodes.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698