Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../closure.dart'; | 7 import '../closure.dart'; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 10 import '../common/names.dart'; | 10 import '../common/names.dart'; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 import '../js_backend/backend.dart' show JavaScriptBackend; | 24 import '../js_backend/backend.dart' show JavaScriptBackend; |
| 25 import '../kernel/kernel.dart'; | 25 import '../kernel/kernel.dart'; |
| 26 import '../native/native.dart' as native; | 26 import '../native/native.dart' as native; |
| 27 import '../resolution/tree_elements.dart'; | 27 import '../resolution/tree_elements.dart'; |
| 28 import '../tree/dartstring.dart'; | 28 import '../tree/dartstring.dart'; |
| 29 import '../tree/nodes.dart' show Node; | 29 import '../tree/nodes.dart' show Node; |
| 30 import '../types/masks.dart'; | 30 import '../types/masks.dart'; |
| 31 import '../universe/call_structure.dart' show CallStructure; | 31 import '../universe/call_structure.dart' show CallStructure; |
| 32 import '../universe/selector.dart'; | 32 import '../universe/selector.dart'; |
| 33 import '../universe/side_effects.dart' show SideEffects; | 33 import '../universe/side_effects.dart' show SideEffects; |
| 34 import '../universe/use.dart' show StaticUse; | 34 import '../universe/use.dart' show DynamicUse, StaticUse; |
| 35 import '../world.dart'; | 35 import '../world.dart'; |
| 36 import 'graph_builder.dart'; | 36 import 'graph_builder.dart'; |
| 37 import 'jump_handler.dart'; | 37 import 'jump_handler.dart'; |
| 38 import 'kernel_ast_adapter.dart'; | 38 import 'kernel_ast_adapter.dart'; |
| 39 import 'kernel_string_builder.dart'; | 39 import 'kernel_string_builder.dart'; |
| 40 import 'locals_handler.dart'; | 40 import 'locals_handler.dart'; |
| 41 import 'loop_handler.dart'; | 41 import 'loop_handler.dart'; |
| 42 import 'nodes.dart'; | 42 import 'nodes.dart'; |
| 43 import 'ssa_branch_builder.dart'; | 43 import 'ssa_branch_builder.dart'; |
| 44 import 'switch_continue_analysis.dart'; | 44 import 'switch_continue_analysis.dart'; |
| (...skipping 1847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1892 _pushDynamicInvocation( | 1892 _pushDynamicInvocation( |
| 1893 propertySet, | 1893 propertySet, |
| 1894 astAdapter.typeOfSet(propertySet, closedWorld), | 1894 astAdapter.typeOfSet(propertySet, closedWorld), |
| 1895 <HInstruction>[receiver, value]); | 1895 <HInstruction>[receiver, value]); |
| 1896 | 1896 |
| 1897 pop(); | 1897 pop(); |
| 1898 stack.add(value); | 1898 stack.add(value); |
| 1899 } | 1899 } |
| 1900 | 1900 |
| 1901 @override | 1901 @override |
| 1902 void visitSuperPropertySet(ir.SuperPropertySet propertySet) { | |
| 1903 propertySet.value.accept(this); | |
| 1904 HInstruction value = pop(); | |
| 1905 | |
| 1906 if (propertySet.interfaceTarget == null) { | |
| 1907 _generateSuperNoSuchMethod( | |
| 1908 propertySet, | |
| 1909 astAdapter.getSelector(propertySet).name + "=", | |
| 1910 <HInstruction>[value]); | |
| 1911 } else { | |
| 1912 _buildInvokeSuper( | |
| 1913 astAdapter.getSelector(propertySet), | |
| 1914 _containingClass(propertySet), | |
| 1915 propertySet.interfaceTarget, | |
| 1916 <HInstruction>[value]); | |
| 1917 } | |
| 1918 } | |
| 1919 | |
| 1920 @override | |
| 1902 void visitVariableSet(ir.VariableSet variableSet) { | 1921 void visitVariableSet(ir.VariableSet variableSet) { |
| 1903 variableSet.value.accept(this); | 1922 variableSet.value.accept(this); |
| 1904 HInstruction value = pop(); | 1923 HInstruction value = pop(); |
| 1905 _visitLocalSetter(variableSet.variable, value); | 1924 _visitLocalSetter(variableSet.variable, value); |
| 1906 } | 1925 } |
| 1907 | 1926 |
| 1908 @override | 1927 @override |
| 1909 void visitVariableDeclaration(ir.VariableDeclaration declaration) { | 1928 void visitVariableDeclaration(ir.VariableDeclaration declaration) { |
| 1910 Local local = astAdapter.getLocal(declaration); | 1929 Local local = astAdapter.getLocal(declaration); |
| 1911 if (declaration.initializer == null) { | 1930 if (declaration.initializer == null) { |
| (...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2618 } | 2637 } |
| 2619 | 2638 |
| 2620 static ir.Class _containingClass(ir.TreeNode node) { | 2639 static ir.Class _containingClass(ir.TreeNode node) { |
| 2621 while (node != null) { | 2640 while (node != null) { |
| 2622 if (node is ir.Class) return node; | 2641 if (node is ir.Class) return node; |
| 2623 node = node.parent; | 2642 node = node.parent; |
| 2624 } | 2643 } |
| 2625 return null; | 2644 return null; |
| 2626 } | 2645 } |
| 2627 | 2646 |
| 2628 HInstruction _buildInvokeSuper( | 2647 /// Find the applicable NoSuchMethod method for an object of this particular |
| 2629 ir.Expression invocation, List<HInstruction> arguments) { | 2648 /// class. |
| 2630 // Invocation is either a method invocation or a property get/set. | 2649 ir.Procedure _findNoSuchMethodInClass(ir.Class cls) { |
|
sra1
2017/02/03 21:07:41
Can closedWorld.locateSingleElement be used to do
Emily Fortuna
2017/02/03 21:53:06
Per offline discussion we decided to keep this sin
| |
| 2631 // TODO(efortuna): Common interface? | 2650 ir.Procedure noSuchMethod = null; |
| 2651 while (cls != null && cls != astAdapter.objectClass) { | |
| 2652 for (ir.Procedure procedure in cls.procedures) { | |
| 2653 // TODO(efortuna): Do we need to check mixin classes as well? | |
| 2654 if (procedure.name.name == Identifiers.noSuchMethod_ && | |
| 2655 Selectors.noSuchMethod_ | |
| 2656 .signatureApplies(astAdapter.getElement(procedure))) { | |
| 2657 noSuchMethod = procedure; | |
| 2658 } | |
| 2659 } | |
| 2660 cls = cls.superclass; | |
| 2661 } | |
| 2662 | |
| 2663 if (noSuchMethod == null) { | |
| 2664 // There is no matching overloaded NoSuchMethod function in the containing | |
| 2665 // class. Look on the Object class itself. | |
| 2666 for (ir.Procedure procedure in astAdapter.objectClass.procedures) { | |
| 2667 if (procedure.name.name == Identifiers.noSuchMethod_) { | |
| 2668 noSuchMethod = procedure; | |
| 2669 } | |
| 2670 } | |
| 2671 } | |
| 2672 assert(noSuchMethod != null); | |
| 2673 return noSuchMethod; | |
| 2674 } | |
| 2675 | |
| 2676 void _generateSuperNoSuchMethod(ir.Expression invocation, String publicName, | |
| 2677 List<HInstruction> arguments) { | |
| 2678 Selector selector = astAdapter.getSelector(invocation); | |
| 2679 ir.Class cls = _containingClass(invocation).superclass; | |
| 2680 assert(cls != null); | |
| 2681 ir.Procedure noSuchMethod = _findNoSuchMethodInClass(cls); | |
| 2682 if (backend.hasInvokeOnSupport && | |
| 2683 _containingClass(noSuchMethod) != astAdapter.objectClass) { | |
| 2684 // Register the call as dynamic if [noSuchMethod] on the super | |
| 2685 // class is _not_ the default implementation from [Object] (it might be | |
| 2686 // overridden in the super class, but it might have a different number of | |
| 2687 // arguments), in case the [noSuchMethod] implementation calls | |
| 2688 // [JSInvocationMirror._invokeOn]. | |
| 2689 // TODO(johnniwinther): Register this more precisely. | |
| 2690 registry?.registerDynamicUse(new DynamicUse(selector, null)); | |
| 2691 } | |
| 2692 | |
| 2693 ConstantValue nameConstant = | |
| 2694 backend.constantSystem.createString(new DartString.literal(publicName)); | |
|
sra1
2017/02/03 21:07:41
Check that we generate the same code under --minif
Emily Fortuna
2017/02/03 21:53:06
looks good!
| |
| 2695 | |
| 2696 js.Name internalName = backend.namer.invocationName(selector); | |
| 2697 | |
| 2698 var argumentsInstruction = | |
| 2699 new HLiteralList(arguments, commonMasks.extendableArrayType); | |
| 2700 add(argumentsInstruction); | |
| 2701 | |
| 2702 var argumentNames = new List<HInstruction>(); | |
| 2703 for (String argumentName in selector.namedArguments) { | |
| 2704 ConstantValue argumentNameConstant = backend.constantSystem | |
| 2705 .createString(new DartString.literal(argumentName)); | |
| 2706 argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld)); | |
| 2707 } | |
| 2708 var argumentNamesInstruction = | |
| 2709 new HLiteralList(argumentNames, commonMasks.extendableArrayType); | |
| 2710 add(argumentNamesInstruction); | |
| 2711 | |
| 2712 ConstantValue kindConstant = | |
| 2713 backend.constantSystem.createInt(selector.invocationMirrorKind); | |
| 2714 | |
| 2715 _pushStaticInvocation( | |
| 2716 astAdapter.createInvocationMirror, | |
| 2717 [ | |
| 2718 graph.addConstant(nameConstant, closedWorld), | |
| 2719 graph.addConstantStringFromName(internalName, closedWorld), | |
| 2720 graph.addConstant(kindConstant, closedWorld), | |
| 2721 argumentsInstruction, | |
| 2722 argumentNamesInstruction | |
| 2723 ], | |
| 2724 commonMasks.dynamicType); | |
| 2725 | |
| 2726 _buildInvokeSuper(Selectors.noSuchMethod_, _containingClass(invocation), | |
| 2727 noSuchMethod, <HInstruction>[pop()]); | |
| 2728 } | |
| 2729 | |
| 2730 HInstruction _buildInvokeSuper(Selector selector, ir.Class containingClass, | |
| 2731 ir.Member interfaceTarget, List<HInstruction> arguments) { | |
| 2632 // TODO(efortuna): Add source information. | 2732 // TODO(efortuna): Add source information. |
| 2633 Selector selector = astAdapter.getSelector(invocation); | |
| 2634 HInstruction receiver = localsHandler.readThis(); | 2733 HInstruction receiver = localsHandler.readThis(); |
| 2635 ir.Class surroundingClass = _containingClass(invocation); | |
| 2636 | 2734 |
| 2637 List<HInstruction> inputs = <HInstruction>[]; | 2735 List<HInstruction> inputs = <HInstruction>[]; |
| 2638 if (astAdapter.isIntercepted(invocation)) { | 2736 if (astAdapter.isInterceptedSelector(selector)) { |
| 2639 inputs.add(_interceptorFor(receiver)); | 2737 inputs.add(_interceptorFor(receiver)); |
| 2640 } | 2738 } |
| 2641 inputs.add(receiver); | 2739 inputs.add(receiver); |
| 2642 inputs.addAll(arguments); | 2740 inputs.addAll(arguments); |
| 2643 | 2741 |
| 2644 ir.Member interfaceTarget = invocation is ir.SuperMethodInvocation | |
| 2645 ? (invocation as ir.SuperMethodInvocation).interfaceTarget | |
| 2646 : (invocation as ir.SuperPropertyGet).interfaceTarget; | |
| 2647 | |
| 2648 HInstruction instruction = new HInvokeSuper( | 2742 HInstruction instruction = new HInvokeSuper( |
| 2649 astAdapter.getMember(interfaceTarget), | 2743 astAdapter.getMember(interfaceTarget), |
| 2650 astAdapter.getClass(surroundingClass), | 2744 astAdapter.getClass(containingClass), |
| 2651 selector, | 2745 selector, |
| 2652 inputs, | 2746 inputs, |
| 2653 astAdapter.returnTypeOf(interfaceTarget), | 2747 astAdapter.returnTypeOf(interfaceTarget), |
| 2654 null, | 2748 null, |
| 2655 isSetter: selector.isSetter || selector.isIndexSet); | 2749 isSetter: selector.isSetter || selector.isIndexSet); |
| 2656 instruction.sideEffects = | 2750 instruction.sideEffects = |
| 2657 closedWorld.getSideEffectsOfSelector(selector, null); | 2751 closedWorld.getSideEffectsOfSelector(selector, null); |
| 2658 push(instruction); | 2752 push(instruction); |
| 2659 return instruction; | 2753 return instruction; |
| 2660 } | 2754 } |
| 2661 | 2755 |
| 2662 @override | 2756 @override |
| 2663 void visitSuperPropertyGet(ir.SuperPropertyGet propertyGet) { | 2757 void visitSuperPropertyGet(ir.SuperPropertyGet propertyGet) { |
| 2664 _buildInvokeSuper(propertyGet, const <HInstruction>[]); | 2758 if (propertyGet.interfaceTarget == null) { |
| 2759 _generateSuperNoSuchMethod(propertyGet, | |
| 2760 astAdapter.getSelector(propertyGet).name, const <HInstruction>[]); | |
| 2761 } else { | |
| 2762 _buildInvokeSuper( | |
| 2763 astAdapter.getSelector(propertyGet), | |
| 2764 _containingClass(propertyGet), | |
| 2765 propertyGet.interfaceTarget, const <HInstruction>[]); | |
| 2766 } | |
| 2665 } | 2767 } |
| 2666 | 2768 |
| 2667 @override | 2769 @override |
| 2668 void visitSuperMethodInvocation(ir.SuperMethodInvocation invocation) { | 2770 void visitSuperMethodInvocation(ir.SuperMethodInvocation invocation) { |
| 2669 List<HInstruction> arguments = _visitArgumentsForStaticTarget( | 2771 List<HInstruction> arguments = _visitArgumentsForStaticTarget( |
| 2670 invocation.interfaceTarget.function, invocation.arguments); | 2772 invocation.interfaceTarget.function, invocation.arguments); |
| 2671 _buildInvokeSuper(invocation, arguments); | 2773 _buildInvokeSuper(astAdapter.getSelector(invocation), |
| 2774 _containingClass(invocation), invocation.interfaceTarget, arguments); | |
| 2672 } | 2775 } |
| 2673 | 2776 |
| 2674 @override | 2777 @override |
| 2675 void visitConstructorInvocation(ir.ConstructorInvocation invocation) { | 2778 void visitConstructorInvocation(ir.ConstructorInvocation invocation) { |
| 2676 ir.Constructor target = invocation.target; | 2779 ir.Constructor target = invocation.target; |
| 2677 // TODO(sra): For JS-interop targets, process arguments differently. | 2780 // TODO(sra): For JS-interop targets, process arguments differently. |
| 2678 List<HInstruction> arguments = | 2781 List<HInstruction> arguments = |
| 2679 _visitArgumentsForStaticTarget(target.function, invocation.arguments); | 2782 _visitArgumentsForStaticTarget(target.function, invocation.arguments); |
| 2680 TypeMask typeMask = new TypeMask.nonNullExact( | 2783 TypeMask typeMask = new TypeMask.nonNullExact( |
| 2681 astAdapter.getClass(target.enclosingClass), closedWorld); | 2784 astAdapter.getClass(target.enclosingClass), closedWorld); |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3106 enterBlock.setBlockFlow( | 3209 enterBlock.setBlockFlow( |
| 3107 new HTryBlockInformation( | 3210 new HTryBlockInformation( |
| 3108 kernelBuilder.wrapStatementGraph(bodyGraph), | 3211 kernelBuilder.wrapStatementGraph(bodyGraph), |
| 3109 exception, | 3212 exception, |
| 3110 kernelBuilder.wrapStatementGraph(catchGraph), | 3213 kernelBuilder.wrapStatementGraph(catchGraph), |
| 3111 kernelBuilder.wrapStatementGraph(finallyGraph)), | 3214 kernelBuilder.wrapStatementGraph(finallyGraph)), |
| 3112 exitBlock); | 3215 exitBlock); |
| 3113 kernelBuilder.inTryStatement = previouslyInTryStatement; | 3216 kernelBuilder.inTryStatement = previouslyInTryStatement; |
| 3114 } | 3217 } |
| 3115 } | 3218 } |
| OLD | NEW |