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

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

Issue 12330135: Make instance methods whose names collide with intercepted methods have the interceptor calling con… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 | Annotate | Revision Log
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 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 result.element = target; 310 result.element = target;
311 return result; 311 return result;
312 } 312 }
313 } else if (selector.isGetter()) { 313 } else if (selector.isGetter()) {
314 if (selector.applies(backend.jsArrayLength, compiler)) { 314 if (selector.applies(backend.jsArrayLength, compiler)) {
315 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node); 315 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
316 if (optimized != null) return optimized; 316 if (optimized != null) return optimized;
317 } 317 }
318 } 318 }
319 319
320 // Check if this call does not need to be intercepted.
321 HType type = input.instructionType;
322 // TODO(kasperl): Get rid of this refinement once the receiver
323 // specialization phase takes care of it.
324 Selector refined = type.refine(selector, compiler);
325 Set<ClassElement> classes = backend.getInterceptedClassesOn(
326 refined, canBeNull: type.canBeNull());
327 if (classes == null) {
328 if (selector.isGetter()) {
329 // Change the call to a regular invoke dynamic call.
330 return new HInvokeDynamicGetter(selector, null, input, false);
331 } else if (selector.isSetter()) {
332 return new HInvokeDynamicSetter(
333 selector, null, input, node.inputs[2], false);
334 } else {
335 // Change the call to a regular invoke dynamic call.
336 return new HInvokeDynamicMethod(
337 selector, node.inputs.getRange(1, node.inputs.length - 1));
338 }
339 }
340
341 // If the intercepted call is through a constant interceptor, we 320 // If the intercepted call is through a constant interceptor, we
342 // know which element to call. 321 // know which element to call.
343 if (node is !HOneShotInterceptor 322 if (node is !HOneShotInterceptor
344 && interceptor.isConstant() 323 && interceptor.isConstant()
345 && selector.isCall()) { 324 && selector.isCall()) {
346 DartType type = interceptor.instructionType.computeType(compiler); 325 DartType type = interceptor.instructionType.computeType(compiler);
347 ClassElement cls = type.element; 326 ClassElement cls = type.element;
348 node.element = cls.lookupSelector(selector); 327 node.element = cls.lookupSelector(selector);
349 } 328 }
350 return node; 329 return node;
(...skipping 16 matching lines...) Expand all
367 } 346 }
368 347
369 HInstruction visitInvokeStatic(HInvokeStatic node) { 348 HInstruction visitInvokeStatic(HInvokeStatic node) {
370 if (isFixedSizeListConstructor(node)) { 349 if (isFixedSizeListConstructor(node)) {
371 node.instructionType = HType.FIXED_ARRAY; 350 node.instructionType = HType.FIXED_ARRAY;
372 } 351 }
373 return node; 352 return node;
374 } 353 }
375 354
376 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 355 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
377 if (node.isInterceptorCall) return handleInterceptorCall(node); 356 if (node.isCallOnInterceptor) return handleInterceptorCall(node);
378 HType receiverType = node.receiver.instructionType; 357 HType receiverType = node.receiver.instructionType;
379 Selector selector = receiverType.refine(node.selector, compiler); 358 Selector selector = receiverType.refine(node.selector, compiler);
380 Element element = compiler.world.locateSingleElement(selector); 359 Element element = compiler.world.locateSingleElement(selector);
381 // TODO(ngeoffray): Also fold if it's a getter or variable. 360 // TODO(ngeoffray): Also fold if it's a getter or variable.
382 if (element != null && element.isFunction()) { 361 if (element != null && element.isFunction()) {
383 FunctionElement method = element; 362 FunctionElement method = element;
384 FunctionSignature parameters = method.computeSignature(compiler); 363 FunctionSignature parameters = method.computeSignature(compiler);
385 // TODO(ngeoffray): If the method has optional parameters, 364 // TODO(ngeoffray): If the method has optional parameters,
386 // we should pass the default values. 365 // we should pass the default values.
387 if (parameters.optionalParameterCount == 0 366 if (parameters.optionalParameterCount == 0
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 HInvokeStatic call = node.receiver; 580 HInvokeStatic call = node.receiver;
602 if (isFixedSizeListConstructor(call)) { 581 if (isFixedSizeListConstructor(call)) {
603 return call.inputs[1]; 582 return call.inputs[1];
604 } 583 }
605 } 584 }
606 } 585 }
607 return node; 586 return node;
608 } 587 }
609 588
610 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 589 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
611 if (node.isInterceptorCall) return handleInterceptorCall(node); 590 if (node.isCallOnInterceptor) return handleInterceptorCall(node);
612 591
613 Element field = 592 Element field =
614 findConcreteFieldForDynamicAccess(node.receiver, node.selector); 593 findConcreteFieldForDynamicAccess(node.receiver, node.selector);
615 if (field == null) return node; 594 if (field == null) return node;
616 595
617 Modifiers modifiers = field.modifiers; 596 Modifiers modifiers = field.modifiers;
618 bool isFinalOrConst = modifiers.isFinal() || modifiers.isConst(); 597 bool isFinalOrConst = modifiers.isFinal() || modifiers.isConst();
619 if (!compiler.resolverWorld.hasInvokedSetter(field, compiler)) { 598 if (!compiler.resolverWorld.hasInvokedSetter(field, compiler)) {
620 // If no setter is ever used for this field it is only initialized in the 599 // If no setter is ever used for this field it is only initialized in the
621 // initializer list. 600 // initializer list.
(...skipping 15 matching lines...) Expand all
637 } 616 }
638 } 617 }
639 if (type != null) { 618 if (type != null) {
640 result.instructionType = type; 619 result.instructionType = type;
641 } 620 }
642 } 621 }
643 return result; 622 return result;
644 } 623 }
645 624
646 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 625 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
647 if (node.isInterceptorCall) return handleInterceptorCall(node); 626 if (node.isCallOnInterceptor) return handleInterceptorCall(node);
648 627
649 Element field = 628 Element field =
650 findConcreteFieldForDynamicAccess(node.receiver, node.selector); 629 findConcreteFieldForDynamicAccess(node.receiver, node.selector);
651 if (field == null || !field.isAssignable()) return node; 630 if (field == null || !field.isAssignable()) return node;
652 HInstruction value = node.inputs[1]; 631 // Use [:node.inputs.last:] in case the call follows the
632 // interceptor calling convention, but is not a call on an
633 // interceptor.
634 HInstruction value = node.inputs.last;
653 if (compiler.enableTypeAssertions) { 635 if (compiler.enableTypeAssertions) {
654 HInstruction other = value.convertType( 636 HInstruction other = value.convertType(
655 compiler, 637 compiler,
656 field.computeType(compiler), 638 field.computeType(compiler),
657 HTypeConversion.CHECKED_MODE_CHECK); 639 HTypeConversion.CHECKED_MODE_CHECK);
658 if (other != value) { 640 if (other != value) {
659 node.block.addBefore(node, other); 641 node.block.addBefore(node, other);
660 value = other; 642 value = other;
661 } 643 }
662 } 644 }
663 return new HFieldSet(field, node.inputs[0], value); 645 return new HFieldSet(field, node.inputs[0], value);
664 } 646 }
665 647
666 HInstruction visitStringConcat(HStringConcat node) { 648 HInstruction visitStringConcat(HStringConcat node) {
667 DartString folded = const LiteralDartString(""); 649 DartString folded = const LiteralDartString("");
668 for (int i = 0; i < node.inputs.length; i++) { 650 for (int i = 0; i < node.inputs.length; i++) {
669 HInstruction part = node.inputs[i]; 651 HInstruction part = node.inputs[i];
670 if (!part.isConstant()) return node; 652 if (!part.isConstant()) return node;
671 HConstant constant = part; 653 HConstant constant = part;
672 if (!constant.constant.isPrimitive()) return node; 654 if (!constant.constant.isPrimitive()) return node;
673 PrimitiveConstant primitive = constant.constant; 655 PrimitiveConstant primitive = constant.constant;
674 folded = new DartString.concat(folded, primitive.toDartString()); 656 folded = new DartString.concat(folded, primitive.toDartString());
675 } 657 }
676 return graph.addConstant(constantSystem.createString(folded, node.node)); 658 return graph.addConstant(constantSystem.createString(folded, node.node));
677 } 659 }
678 660
679 HInstruction visitInterceptor(HInterceptor node) { 661 HInstruction visitInterceptor(HInterceptor node) {
680 if (node.isConstant()) return node; 662 if (node.isConstant()) return node;
663 // If the intercepted object does not need to be intercepted, just
664 // return the object (the [:getInterceptor:] method would have
665 // returned the object).
666 HType type = node.receiver.instructionType;
667 if (!type.canBePrimitive()) {
668
669 if (!(type.canBeNull()
670 && node.interceptedClasses.contains(compiler.objectClass))) {
671 return node.receiver;
672 }
673 }
681 HInstruction constant = tryComputeConstantInterceptor( 674 HInstruction constant = tryComputeConstantInterceptor(
682 node.inputs[0], node.interceptedClasses); 675 node.inputs[0], node.interceptedClasses);
683 if (constant == null) return node; 676 if (constant == null) return node;
677
684 return constant; 678 return constant;
685 } 679 }
686 680
687 HInstruction tryComputeConstantInterceptor(HInstruction input, 681 HInstruction tryComputeConstantInterceptor(HInstruction input,
688 Set<ClassElement> intercepted) { 682 Set<ClassElement> intercepted) {
689 HType type = input.instructionType; 683 HType type = input.instructionType;
690 ClassElement constantInterceptor; 684 ClassElement constantInterceptor;
691 if (type.isInteger()) { 685 if (type.isInteger()) {
692 constantInterceptor = backend.jsIntClass; 686 constantInterceptor = backend.jsIntClass;
693 } else if (type.isDouble()) { 687 } else if (type.isDouble()) {
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 HBasicBlock block = user.block; 1528 HBasicBlock block = user.block;
1535 block.addAfter(user, interceptor); 1529 block.addAfter(user, interceptor);
1536 block.rewrite(user, interceptor); 1530 block.rewrite(user, interceptor);
1537 block.remove(user); 1531 block.remove(user);
1538 1532
1539 // The interceptor will be removed in the dead code elimination 1533 // The interceptor will be removed in the dead code elimination
1540 // phase. Note that removing it here would not work because of how 1534 // phase. Note that removing it here would not work because of how
1541 // the [visitBasicBlock] is implemented. 1535 // the [visitBasicBlock] is implemented.
1542 } 1536 }
1543 } 1537 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698