Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
| 9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
| 10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
| (...skipping 3490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3501 } | 3501 } |
| 3502 | 3502 |
| 3503 @override | 3503 @override |
| 3504 void visitTopLevelGetterGet( | 3504 void visitTopLevelGetterGet( |
| 3505 ast.Send node, | 3505 ast.Send node, |
| 3506 FunctionElement getter, | 3506 FunctionElement getter, |
| 3507 _) { | 3507 _) { |
| 3508 generateStaticGetterGet(node, getter); | 3508 generateStaticGetterGet(node, getter); |
| 3509 } | 3509 } |
| 3510 | 3510 |
| 3511 void generatePossiblyConditionalInstanceSetter(ast.Send send, | |
| 3512 HInstruction pushReceiver(), | |
| 3513 HInstruction pushValue(), | |
| 3514 {Selector selector, | |
| 3515 ast.Node location}) { | |
| 3516 if (send.isConditional) { | |
| 3517 SsaBranchBuilder brancher = new SsaBranchBuilder(this, send); | |
| 3518 // compile e?.x = e2 to: | |
| 3519 // | |
| 3520 // t1 = e | |
| 3521 // if (t1 == null) | |
| 3522 // result = t1 // same as result = null | |
| 3523 // else | |
| 3524 // result = e.x = e2 | |
| 3525 HInstruction receiver; | |
| 3526 brancher.handleConditional( | |
| 3527 () { | |
| 3528 receiver = pushReceiver(); | |
| 3529 pushCheckNull(receiver); | |
| 3530 }, | |
| 3531 () => stack.add(receiver), | |
| 3532 () => generateInstanceSetterWithCompiledReceiver( | |
| 3533 send, receiver, pushValue(), | |
| 3534 selector: selector, location: location)); | |
| 3535 } else { | |
| 3536 generateInstanceSetterWithCompiledReceiver( | |
| 3537 send, pushReceiver(), pushValue(), | |
| 3538 selector: selector, location: location); | |
| 3539 } | |
| 3540 } | |
| 3541 | |
| 3542 void generateInstanceSetterWithCompiledReceiver(ast.Send send, | 3511 void generateInstanceSetterWithCompiledReceiver(ast.Send send, |
| 3543 HInstruction receiver, | 3512 HInstruction receiver, |
| 3544 HInstruction value, | 3513 HInstruction value, |
| 3545 {Selector selector, | 3514 {Selector selector, |
| 3546 ast.Node location}) { | 3515 ast.Node location}) { |
| 3547 assert(send == null || Elements.isInstanceSend(send, elements)); | 3516 assert(send == null || Elements.isInstanceSend(send, elements)); |
| 3548 if (selector == null) { | 3517 if (selector == null) { |
| 3549 assert(send != null); | 3518 assert(send != null); |
| 3550 selector = elements.getSelector(send); | 3519 selector = elements.getSelector(send); |
| 3551 } | 3520 } |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3979 // Leg's isolate. | 3948 // Leg's isolate. |
| 3980 Element element = backend.isolateHelperLibrary.find('_currentIsolate'); | 3949 Element element = backend.isolateHelperLibrary.find('_currentIsolate'); |
| 3981 if (element == null) { | 3950 if (element == null) { |
| 3982 compiler.internalError(node, | 3951 compiler.internalError(node, |
| 3983 'Isolate library and compiler mismatch.'); | 3952 'Isolate library and compiler mismatch.'); |
| 3984 } | 3953 } |
| 3985 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); | 3954 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); |
| 3986 } | 3955 } |
| 3987 } | 3956 } |
| 3988 | 3957 |
| 3989 void handleForeingJsGetFlag(ast.Send node) { | 3958 void handleForeignJsGetFlag(ast.Send node) { |
| 3990 List<ast.Node> arguments = node.arguments.toList(); | 3959 List<ast.Node> arguments = node.arguments.toList(); |
| 3991 ast.Node argument; | 3960 ast.Node argument; |
| 3992 switch (arguments.length) { | 3961 switch (arguments.length) { |
| 3993 case 0: | 3962 case 0: |
| 3994 compiler.reportError( | 3963 compiler.reportError( |
| 3995 node, MessageKind.GENERIC, | 3964 node, MessageKind.GENERIC, |
| 3996 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); | 3965 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); |
| 3997 return; | 3966 return; |
| 3998 case 1: | 3967 case 1: |
| 3999 argument = arguments[0]; | 3968 argument = arguments[0]; |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4278 handleForeignSetCurrentIsolate(node); | 4247 handleForeignSetCurrentIsolate(node); |
| 4279 } else if (name == 'JS_CURRENT_ISOLATE') { | 4248 } else if (name == 'JS_CURRENT_ISOLATE') { |
| 4280 handleForeignJsCurrentIsolate(node); | 4249 handleForeignJsCurrentIsolate(node); |
| 4281 } else if (name == 'JS_GET_NAME') { | 4250 } else if (name == 'JS_GET_NAME') { |
| 4282 handleForeignJsGetName(node); | 4251 handleForeignJsGetName(node); |
| 4283 } else if (name == 'JS_EMBEDDED_GLOBAL') { | 4252 } else if (name == 'JS_EMBEDDED_GLOBAL') { |
| 4284 handleForeignJsEmbeddedGlobal(node); | 4253 handleForeignJsEmbeddedGlobal(node); |
| 4285 } else if (name == 'JS_BUILTIN') { | 4254 } else if (name == 'JS_BUILTIN') { |
| 4286 handleForeignJsBuiltin(node); | 4255 handleForeignJsBuiltin(node); |
| 4287 } else if (name == 'JS_GET_FLAG') { | 4256 } else if (name == 'JS_GET_FLAG') { |
| 4288 handleForeingJsGetFlag(node); | 4257 handleForeignJsGetFlag(node); |
| 4289 } else if (name == 'JS_EFFECT') { | 4258 } else if (name == 'JS_EFFECT') { |
| 4290 stack.add(graph.addConstantNull(compiler)); | 4259 stack.add(graph.addConstantNull(compiler)); |
| 4291 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 4260 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
| 4292 handleJsInterceptorConstant(node); | 4261 handleJsInterceptorConstant(node); |
| 4293 } else if (name == 'JS_STRING_CONCAT') { | 4262 } else if (name == 'JS_STRING_CONCAT') { |
| 4294 handleJsStringConcat(node); | 4263 handleJsStringConcat(node); |
| 4295 } else { | 4264 } else { |
| 4296 compiler.internalError(node, "Unknown foreign: ${element}"); | 4265 compiler.internalError(node, "Unknown foreign: ${element}"); |
| 4297 } | 4266 } |
| 4298 } | 4267 } |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5618 visit(arguments.head); | 5587 visit(arguments.head); |
| 5619 assert(arguments.tail.isEmpty); | 5588 assert(arguments.tail.isEmpty); |
| 5620 rhs = pop(); | 5589 rhs = pop(); |
| 5621 } | 5590 } |
| 5622 visitBinarySend(receiver, rhs, | 5591 visitBinarySend(receiver, rhs, |
| 5623 elements.getOperatorSelectorInComplexSendSet(node), | 5592 elements.getOperatorSelectorInComplexSendSet(node), |
| 5624 node, | 5593 node, |
| 5625 location: node.assignmentOperator); | 5594 location: node.assignmentOperator); |
| 5626 } | 5595 } |
| 5627 | 5596 |
| 5597 void handleSuperSendSet(ast.SendSet node) { | |
| 5598 Element element = elements[node]; | |
| 5599 List<HInstruction> setterInputs = <HInstruction>[]; | |
| 5600 void generateSuperSendSet() { | |
| 5601 Selector setterSelector = elements.getSelector(node); | |
| 5602 if (Elements.isUnresolved(element) | |
| 5603 || !setterSelector.applies(element, compiler.world)) { | |
| 5604 generateSuperNoSuchMethodSend( | |
| 5605 node, setterSelector, setterInputs); | |
| 5606 pop(); | |
| 5607 } else { | |
| 5608 add(buildInvokeSuper(setterSelector, element, setterInputs)); | |
| 5609 } | |
| 5610 } | |
| 5611 if (identical(node.assignmentOperator.source, '=')) { | |
| 5612 addDynamicSendArgumentsToList(node, setterInputs); | |
| 5613 generateSuperSendSet(); | |
| 5614 stack.add(setterInputs.last); | |
| 5615 } else { | |
| 5616 Element getter = elements[node.selector]; | |
| 5617 List<HInstruction> getterInputs = <HInstruction>[]; | |
| 5618 Link<ast.Node> arguments = node.arguments; | |
| 5619 if (node.isIndex) { | |
| 5620 // If node is of the from [:super.foo[0] += 2:], the send has | |
|
karlklose
2015/06/17 07:51:01
'from' -> 'from'.
Johnni Winther
2015/06/17 09:36:28
Done.
| |
| 5621 // two arguments: the index and the left hand side. We get | |
| 5622 // the index and add it as input of the getter and the | |
| 5623 // setter. | |
| 5624 visit(arguments.head); | |
| 5625 arguments = arguments.tail; | |
| 5626 HInstruction index = pop(); | |
| 5627 getterInputs.add(index); | |
| 5628 setterInputs.add(index); | |
| 5629 } | |
| 5630 HInstruction getterInstruction; | |
| 5631 Selector getterSelector = | |
| 5632 elements.getGetterSelectorInComplexSendSet(node); | |
| 5633 if (Elements.isUnresolved(getter)) { | |
| 5634 generateSuperNoSuchMethodSend( | |
| 5635 node, | |
| 5636 getterSelector, | |
| 5637 getterInputs); | |
| 5638 getterInstruction = pop(); | |
| 5639 } else { | |
| 5640 getterInstruction = buildInvokeSuper( | |
| 5641 getterSelector, getter, getterInputs); | |
| 5642 add(getterInstruction); | |
| 5643 } | |
| 5644 | |
| 5645 if (node.isIfNullAssignment) { | |
| 5646 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5647 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5648 () { | |
| 5649 addDynamicSendArgumentsToList(node, setterInputs); | |
| 5650 generateSuperSendSet(); | |
| 5651 stack.add(setterInputs.last); | |
| 5652 }); | |
| 5653 } else { | |
| 5654 handleComplexOperatorSend(node, getterInstruction, arguments); | |
| 5655 setterInputs.add(pop()); | |
| 5656 generateSuperSendSet(); | |
| 5657 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); | |
| 5658 } | |
| 5659 } | |
| 5660 } | |
| 5661 | |
| 5662 @override | |
| 5663 void visitIndexSet( | |
| 5664 ast.SendSet node, | |
| 5665 ast.Node receiver, | |
| 5666 ast.Node index, | |
| 5667 ast.Node rhs, | |
| 5668 _) { | |
| 5669 generateDynamicSend(node); | |
| 5670 } | |
| 5671 | |
| 5672 void handleIndexSendSet(ast.SendSet node) { | |
| 5673 ast.Operator op = node.assignmentOperator; | |
| 5674 if ("=" == op.source) { | |
| 5675 internalError(node, "Unexpected index set."); | |
| 5676 } else { | |
| 5677 visit(node.receiver); | |
| 5678 HInstruction receiver = pop(); | |
| 5679 Link<ast.Node> arguments = node.arguments; | |
| 5680 HInstruction index; | |
| 5681 if (node.isIndex) { | |
| 5682 visit(arguments.head); | |
| 5683 arguments = arguments.tail; | |
| 5684 index = pop(); | |
| 5685 } | |
| 5686 | |
| 5687 pushInvokeDynamic( | |
| 5688 node, | |
| 5689 elements.getGetterSelectorInComplexSendSet(node), | |
| 5690 [receiver, index]); | |
| 5691 HInstruction getterInstruction = pop(); | |
| 5692 if (node.isIfNullAssignment) { | |
| 5693 // Compile x[i] ??= e as: | |
| 5694 // t1 = x[i] | |
| 5695 // if (t1 == null) | |
| 5696 // t1 = x[i] = e; | |
| 5697 // result = t1 | |
| 5698 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5699 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5700 () { | |
| 5701 visit(arguments.head); | |
| 5702 HInstruction value = pop(); | |
| 5703 pushInvokeDynamic( | |
| 5704 node, elements.getSelector(node), [receiver, index, value]); | |
| 5705 pop(); | |
| 5706 stack.add(value); | |
| 5707 }); | |
| 5708 } else { | |
| 5709 handleComplexOperatorSend(node, getterInstruction, arguments); | |
| 5710 HInstruction value = pop(); | |
| 5711 pushInvokeDynamic( | |
| 5712 node, elements.getSelector(node), [receiver, index, value]); | |
| 5713 pop(); | |
| 5714 if (node.isPostfix) { | |
| 5715 stack.add(getterInstruction); | |
| 5716 } else { | |
| 5717 stack.add(value); | |
| 5718 } | |
| 5719 } | |
| 5720 } | |
| 5721 } | |
| 5722 | |
| 5723 @override | |
| 5724 void visitThisPropertySet( | |
| 5725 ast.SendSet node, | |
| 5726 Selector selector, | |
| 5727 ast.Node rhs, | |
| 5728 _) { | |
| 5729 generateInstanceSetterWithCompiledReceiver( | |
| 5730 node, | |
| 5731 localsHandler.readThis(), | |
| 5732 visitAndPop(rhs)); | |
| 5733 } | |
| 5734 | |
| 5735 @override | |
| 5736 void visitDynamicPropertySet( | |
| 5737 ast.SendSet node, | |
| 5738 ast.Node receiver, | |
| 5739 Selector selector, | |
| 5740 ast.Node rhs, | |
| 5741 _) { | |
| 5742 generateInstanceSetterWithCompiledReceiver( | |
| 5743 node, | |
| 5744 generateInstanceSendReceiver(node), | |
| 5745 visitAndPop(rhs)); | |
| 5746 } | |
| 5747 | |
| 5748 @override | |
| 5749 void visitIfNotNullDynamicPropertySet( | |
| 5750 ast.SendSet node, | |
| 5751 ast.Node receiver, | |
| 5752 Selector selector, | |
| 5753 ast.Node rhs, | |
| 5754 _) { | |
| 5755 // compile e?.x = e2 to: | |
| 5756 // | |
| 5757 // t1 = e | |
| 5758 // if (t1 == null) | |
| 5759 // result = t1 // same as result = null | |
| 5760 // else | |
| 5761 // result = e.x = e2 | |
| 5762 HInstruction receiverInstruction; | |
| 5763 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5764 brancher.handleConditional( | |
| 5765 () { | |
| 5766 receiverInstruction = generateInstanceSendReceiver(node); | |
| 5767 pushCheckNull(receiverInstruction); | |
| 5768 }, | |
| 5769 () => stack.add(receiverInstruction), | |
| 5770 () { | |
| 5771 generateInstanceSetterWithCompiledReceiver( | |
| 5772 node, | |
| 5773 receiverInstruction, | |
| 5774 visitAndPop(rhs)); | |
| 5775 }); | |
| 5776 } | |
| 5777 | |
| 5778 @override | |
| 5779 void visitParameterSet( | |
| 5780 ast.SendSet node, | |
| 5781 ParameterElement parameter, | |
| 5782 ast.Node rhs, | |
| 5783 _) { | |
| 5784 generateNonInstanceSetter(node, parameter, visitAndPop(rhs)); | |
| 5785 } | |
| 5786 | |
| 5787 @override | |
| 5788 void visitFinalParameterSet( | |
| 5789 ast.SendSet node, | |
| 5790 ParameterElement parameter, | |
| 5791 ast.Node rhs, | |
| 5792 _) { | |
| 5793 generateNonInstanceSetter(node, parameter, visitAndPop(rhs)); | |
| 5794 } | |
| 5795 | |
| 5796 @override | |
| 5797 void visitLocalVariableSet( | |
| 5798 ast.SendSet node, | |
| 5799 LocalVariableElement variable, | |
| 5800 ast.Node rhs, | |
| 5801 _) { | |
| 5802 generateNonInstanceSetter(node, variable, visitAndPop(rhs)); | |
| 5803 } | |
| 5804 | |
| 5805 @override | |
| 5806 void visitFinalLocalVariableSet( | |
| 5807 ast.SendSet node, | |
| 5808 LocalVariableElement variable, | |
| 5809 ast.Node rhs, | |
| 5810 _) { | |
| 5811 generateNonInstanceSetter(node, variable, visitAndPop(rhs)); | |
| 5812 } | |
| 5813 | |
| 5814 @override | |
| 5815 void visitLocalFunctionSet( | |
| 5816 ast.SendSet node, | |
| 5817 LocalFunctionElement function, | |
| 5818 ast.Node rhs, | |
| 5819 _) { | |
| 5820 generateNonInstanceSetter(node, function, visitAndPop(rhs)); | |
| 5821 } | |
| 5822 | |
| 5823 @override | |
| 5824 void visitTopLevelFieldSet( | |
| 5825 ast.SendSet node, | |
| 5826 FieldElement field, | |
| 5827 ast.Node rhs, | |
| 5828 _) { | |
| 5829 generateNonInstanceSetter(node, field, visitAndPop(rhs)); | |
| 5830 } | |
| 5831 | |
| 5832 @override | |
| 5833 void visitFinalTopLevelFieldSet( | |
| 5834 ast.SendSet node, | |
| 5835 FieldElement field, | |
| 5836 ast.Node rhs, | |
| 5837 _) { | |
| 5838 generateNonInstanceSetter(node, field, visitAndPop(rhs)); | |
| 5839 } | |
| 5840 | |
| 5841 @override | |
| 5842 void visitTopLevelGetterSet( | |
| 5843 ast.SendSet node, | |
| 5844 GetterElement getter, | |
| 5845 ast.Node rhs, | |
| 5846 _) { | |
| 5847 generateNonInstanceSetter(node, getter, visitAndPop(rhs)); | |
| 5848 } | |
| 5849 | |
| 5850 @override | |
| 5851 void visitTopLevelSetterSet( | |
| 5852 ast.SendSet node, | |
| 5853 SetterElement setter, | |
| 5854 ast.Node rhs, | |
| 5855 _) { | |
| 5856 generateNonInstanceSetter(node, setter, visitAndPop(rhs)); | |
| 5857 } | |
| 5858 | |
| 5859 @override | |
| 5860 void visitTopLevelFunctionSet( | |
| 5861 ast.SendSet node, | |
| 5862 MethodElement function, | |
| 5863 ast.Node rhs, | |
| 5864 _) { | |
| 5865 generateNonInstanceSetter(node, function, visitAndPop(rhs)); | |
| 5866 } | |
| 5867 | |
| 5868 @override | |
| 5869 void visitStaticFieldSet( | |
| 5870 ast.SendSet node, | |
| 5871 FieldElement field, | |
| 5872 ast.Node rhs, | |
| 5873 _) { | |
| 5874 generateNonInstanceSetter(node, field, visitAndPop(rhs)); | |
| 5875 } | |
| 5876 | |
| 5877 @override | |
| 5878 void visitFinalStaticFieldSet( | |
| 5879 ast.SendSet node, | |
| 5880 FieldElement field, | |
| 5881 ast.Node rhs, | |
| 5882 _) { | |
| 5883 generateNonInstanceSetter(node, field, visitAndPop(rhs)); | |
| 5884 } | |
| 5885 | |
| 5886 @override | |
| 5887 void visitStaticGetterSet( | |
| 5888 ast.SendSet node, | |
| 5889 GetterElement getter, | |
| 5890 ast.Node rhs, | |
| 5891 _) { | |
| 5892 generateNonInstanceSetter(node, getter, visitAndPop(rhs)); | |
| 5893 } | |
| 5894 | |
| 5895 @override | |
| 5896 void visitStaticSetterSet( | |
| 5897 ast.SendSet node, | |
| 5898 SetterElement setter, | |
| 5899 ast.Node rhs, | |
| 5900 _) { | |
| 5901 generateNonInstanceSetter(node, setter, visitAndPop(rhs)); | |
| 5902 } | |
| 5903 | |
| 5904 @override | |
| 5905 void visitStaticFunctionSet( | |
| 5906 ast.SendSet node, | |
| 5907 MethodElement function, | |
| 5908 ast.Node rhs, | |
| 5909 _) { | |
| 5910 generateNonInstanceSetter(node, function, visitAndPop(rhs)); | |
| 5911 } | |
| 5912 | |
| 5913 @override | |
| 5914 void visitUnresolvedSet( | |
| 5915 ast.SendSet node, | |
| 5916 Element element, | |
| 5917 ast.Node rhs, | |
| 5918 _) { | |
| 5919 if (node.isSuperCall) { | |
| 5920 // TODO(johnniwinther): Remove this when final super field assignment is | |
| 5921 // not an unresolved set. | |
| 5922 handleSuperSendSet(node); | |
| 5923 } else { | |
| 5924 generateNonInstanceSetter(node, element, visitAndPop(rhs)); | |
| 5925 } | |
| 5926 } | |
| 5927 | |
| 5928 @override | |
| 5929 void visitClassTypeLiteralSet( | |
| 5930 ast.SendSet node, | |
| 5931 TypeConstantExpression constant, | |
| 5932 ast.Node rhs, | |
| 5933 _) { | |
| 5934 generateThrowNoSuchMethod(node, constant.type.name, | |
| 5935 argumentNodes: node.arguments); | |
| 5936 } | |
| 5937 | |
| 5938 @override | |
| 5939 void visitTypedefTypeLiteralSet( | |
| 5940 ast.SendSet node, | |
| 5941 TypeConstantExpression constant, | |
| 5942 ast.Node rhs, | |
| 5943 _) { | |
| 5944 generateThrowNoSuchMethod(node, constant.type.name, | |
| 5945 argumentNodes: node.arguments); | |
| 5946 } | |
| 5947 | |
| 5948 @override | |
| 5949 void visitDynamicTypeLiteralSet( | |
| 5950 ast.SendSet node, | |
| 5951 TypeConstantExpression constant, | |
| 5952 ast.Node rhs, | |
| 5953 _) { | |
| 5954 generateThrowNoSuchMethod(node, constant.type.name, | |
| 5955 argumentNodes: node.arguments); | |
| 5956 } | |
| 5957 | |
| 5958 @override | |
| 5959 void visitTypeVariableTypeLiteralSet( | |
| 5960 ast.SendSet node, | |
| 5961 TypeVariableElement element, | |
| 5962 ast.Node rhs, | |
| 5963 _) { | |
| 5964 generateThrowNoSuchMethod(node, element.name, | |
| 5965 argumentNodes: node.arguments); | |
| 5966 } | |
| 5967 | |
| 5968 void handleCompoundSendSet(ast.SendSet node) { | |
| 5969 Element element = elements[node]; | |
| 5970 Element getter = elements[node.selector]; | |
| 5971 | |
| 5972 if (!Elements.isUnresolved(getter) && getter.impliesType) { | |
| 5973 if (node.isIfNullAssignment) { | |
| 5974 // C ??= x is compiled just as C. | |
| 5975 stack.add(addConstant(node.selector)); | |
| 5976 } else { | |
| 5977 ast.Identifier selector = node.selector; | |
| 5978 generateThrowNoSuchMethod(node, selector.source, | |
| 5979 argumentNodes: node.arguments); | |
| 5980 } | |
| 5981 return; | |
| 5982 } | |
| 5983 | |
| 5984 if (Elements.isInstanceSend(node, elements)) { | |
| 5985 void generateAssignment(HInstruction receiver) { | |
| 5986 // desugars `e.x op= e2` to `e.x = e.x op e2` | |
| 5987 generateInstanceGetterWithCompiledReceiver( | |
| 5988 node, elements.getGetterSelectorInComplexSendSet(node), receiver); | |
| 5989 HInstruction getterInstruction = pop(); | |
| 5990 if (node.isIfNullAssignment) { | |
| 5991 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5992 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5993 () { | |
| 5994 visit(node.arguments.head); | |
| 5995 generateInstanceSetterWithCompiledReceiver( | |
| 5996 node, receiver, pop()); | |
| 5997 }); | |
| 5998 } else { | |
| 5999 handleComplexOperatorSend(node, getterInstruction, node.arguments); | |
| 6000 HInstruction value = pop(); | |
| 6001 generateInstanceSetterWithCompiledReceiver(node, receiver, value); | |
| 6002 } | |
| 6003 if (node.isPostfix) { | |
| 6004 pop(); | |
| 6005 stack.add(getterInstruction); | |
| 6006 } | |
| 6007 } | |
| 6008 if (node.isConditional) { | |
| 6009 // generate `e?.x op= e2` as: | |
| 6010 // t1 = e | |
| 6011 // t1 == null ? t1 : (t1.x = t1.x op e2); | |
| 6012 HInstruction receiver; | |
| 6013 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 6014 brancher.handleConditional( | |
| 6015 () { | |
| 6016 receiver = generateInstanceSendReceiver(node); | |
| 6017 pushCheckNull(receiver); | |
| 6018 }, | |
| 6019 () => stack.add(receiver), | |
| 6020 () => generateAssignment(receiver)); | |
| 6021 } else { | |
| 6022 generateAssignment(generateInstanceSendReceiver(node)); | |
| 6023 } | |
| 6024 return; | |
| 6025 } | |
| 6026 | |
| 6027 if (getter.isErroneous) { | |
| 6028 generateStaticUnresolvedGet(node, getter); | |
| 6029 } else if (getter.isField) { | |
| 6030 generateStaticFieldGet(node, getter); | |
| 6031 } else if (getter.isGetter) { | |
| 6032 generateStaticGetterGet(node, getter); | |
| 6033 } else if (getter.isFunction) { | |
| 6034 generateStaticFunctionGet(node, getter); | |
| 6035 } else if (getter.isLocal) { | |
| 6036 handleLocalGet(getter); | |
| 6037 } else { | |
| 6038 internalError(node, "Unexpected getter: $getter"); | |
| 6039 } | |
| 6040 HInstruction getterInstruction = pop(); | |
| 6041 if (node.isIfNullAssignment) { | |
| 6042 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 6043 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 6044 () { | |
| 6045 visit(node.arguments.head); | |
| 6046 generateNonInstanceSetter(node, element, pop()); | |
| 6047 }); | |
| 6048 } else { | |
| 6049 handleComplexOperatorSend(node, getterInstruction, node.arguments); | |
| 6050 HInstruction value = pop(); | |
| 6051 generateNonInstanceSetter(node, element, value); | |
| 6052 } | |
| 6053 if (node.isPostfix) { | |
| 6054 pop(); | |
| 6055 stack.add(getterInstruction); | |
| 6056 } | |
| 6057 } | |
| 6058 | |
| 5628 @override | 6059 @override |
| 5629 handleSendSet(ast.SendSet node) { | 6060 handleSendSet(ast.SendSet node) { |
| 6061 ast.Operator op = node.assignmentOperator; | |
| 5630 generateIsDeferredLoadedCheckOfSend(node); | 6062 generateIsDeferredLoadedCheckOfSend(node); |
| 5631 Element element = elements[node]; | 6063 Element element = elements[node]; |
| 5632 if (!Elements.isUnresolved(element) && element.impliesType) { | 6064 if (!Elements.isUnresolved(element) && element.impliesType) { |
| 5633 ast.Identifier selector = node.selector; | 6065 ast.Identifier selector = node.selector; |
| 5634 generateThrowNoSuchMethod(node, selector.source, | 6066 generateThrowNoSuchMethod(node, selector.source, |
| 5635 argumentNodes: node.arguments); | 6067 argumentNodes: node.arguments); |
| 5636 return; | 6068 } else if (node.isSuperCall) { |
| 5637 } | 6069 handleSuperSendSet(node); |
| 5638 ast.Operator op = node.assignmentOperator; | |
| 5639 if (node.isSuperCall) { | |
| 5640 List<HInstruction> setterInputs = <HInstruction>[]; | |
| 5641 void generateSuperSendSet() { | |
| 5642 Selector setterSelector = elements.getSelector(node); | |
| 5643 if (Elements.isUnresolved(element) | |
| 5644 || !setterSelector.applies(element, compiler.world)) { | |
| 5645 generateSuperNoSuchMethodSend( | |
| 5646 node, setterSelector, setterInputs); | |
| 5647 pop(); | |
| 5648 } else { | |
| 5649 add(buildInvokeSuper(setterSelector, element, setterInputs)); | |
| 5650 } | |
| 5651 } | |
| 5652 if (identical(node.assignmentOperator.source, '=')) { | |
| 5653 addDynamicSendArgumentsToList(node, setterInputs); | |
| 5654 generateSuperSendSet(); | |
| 5655 stack.add(setterInputs.last); | |
| 5656 } else { | |
| 5657 Element getter = elements[node.selector]; | |
| 5658 List<HInstruction> getterInputs = <HInstruction>[]; | |
| 5659 Link<ast.Node> arguments = node.arguments; | |
| 5660 if (node.isIndex) { | |
| 5661 // If node is of the from [:super.foo[0] += 2:], the send has | |
| 5662 // two arguments: the index and the left hand side. We get | |
| 5663 // the index and add it as input of the getter and the | |
| 5664 // setter. | |
| 5665 visit(arguments.head); | |
| 5666 arguments = arguments.tail; | |
| 5667 HInstruction index = pop(); | |
| 5668 getterInputs.add(index); | |
| 5669 setterInputs.add(index); | |
| 5670 } | |
| 5671 HInstruction getterInstruction; | |
| 5672 Selector getterSelector = | |
| 5673 elements.getGetterSelectorInComplexSendSet(node); | |
| 5674 if (Elements.isUnresolved(getter)) { | |
| 5675 generateSuperNoSuchMethodSend( | |
| 5676 node, | |
| 5677 getterSelector, | |
| 5678 getterInputs); | |
| 5679 getterInstruction = pop(); | |
| 5680 } else { | |
| 5681 getterInstruction = buildInvokeSuper( | |
| 5682 getterSelector, getter, getterInputs); | |
| 5683 add(getterInstruction); | |
| 5684 } | |
| 5685 | |
| 5686 if (node.isIfNullAssignment) { | |
| 5687 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5688 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5689 () { | |
| 5690 addDynamicSendArgumentsToList(node, setterInputs); | |
| 5691 generateSuperSendSet(); | |
| 5692 stack.add(setterInputs.last); | |
| 5693 }); | |
| 5694 } else { | |
| 5695 handleComplexOperatorSend(node, getterInstruction, arguments); | |
| 5696 setterInputs.add(pop()); | |
| 5697 generateSuperSendSet(); | |
| 5698 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); | |
| 5699 } | |
| 5700 } | |
| 5701 } else if (node.isIndex) { | 6070 } else if (node.isIndex) { |
| 5702 if ("=" == op.source) { | 6071 handleIndexSendSet(node); |
| 5703 generateDynamicSend(node); | |
| 5704 } else { | |
| 5705 visit(node.receiver); | |
| 5706 HInstruction receiver = pop(); | |
| 5707 Link<ast.Node> arguments = node.arguments; | |
| 5708 HInstruction index; | |
| 5709 if (node.isIndex) { | |
| 5710 visit(arguments.head); | |
| 5711 arguments = arguments.tail; | |
| 5712 index = pop(); | |
| 5713 } | |
| 5714 | |
| 5715 pushInvokeDynamic( | |
| 5716 node, | |
| 5717 elements.getGetterSelectorInComplexSendSet(node), | |
| 5718 [receiver, index]); | |
| 5719 HInstruction getterInstruction = pop(); | |
| 5720 if (node.isIfNullAssignment) { | |
| 5721 // Compile x[i] ??= e as: | |
| 5722 // t1 = x[i] | |
| 5723 // if (t1 == null) | |
| 5724 // t1 = x[i] = e; | |
| 5725 // result = t1 | |
| 5726 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5727 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5728 () { | |
| 5729 visit(arguments.head); | |
| 5730 HInstruction value = pop(); | |
| 5731 pushInvokeDynamic( | |
| 5732 node, elements.getSelector(node), [receiver, index, value]); | |
| 5733 pop(); | |
| 5734 stack.add(value); | |
| 5735 }); | |
| 5736 } else { | |
| 5737 handleComplexOperatorSend(node, getterInstruction, arguments); | |
| 5738 HInstruction value = pop(); | |
| 5739 pushInvokeDynamic( | |
| 5740 node, elements.getSelector(node), [receiver, index, value]); | |
| 5741 pop(); | |
| 5742 if (node.isPostfix) { | |
| 5743 stack.add(getterInstruction); | |
| 5744 } else { | |
| 5745 stack.add(value); | |
| 5746 } | |
| 5747 } | |
| 5748 } | |
| 5749 } else if ("=" == op.source) { | 6072 } else if ("=" == op.source) { |
| 5750 Link<ast.Node> link = node.arguments; | 6073 internalError(node, "Unexpected assignment."); |
| 5751 assert(!link.isEmpty && link.tail.isEmpty); | |
| 5752 if (Elements.isInstanceSend(node, elements)) { | |
| 5753 generatePossiblyConditionalInstanceSetter(node, | |
| 5754 () => generateInstanceSendReceiver(node), | |
| 5755 () => visitAndPop(link.head)); | |
| 5756 } else { | |
| 5757 visit(link.head); | |
| 5758 generateNonInstanceSetter(node, element, pop()); | |
| 5759 } | |
| 5760 } else if (identical(op.source, "is")) { | 6074 } else if (identical(op.source, "is")) { |
| 5761 compiler.internalError(op, "is-operator as SendSet."); | 6075 compiler.internalError(op, "is-operator as SendSet."); |
| 5762 } else { | 6076 } else { |
| 5763 assert("++" == op.source || "--" == op.source || | 6077 assert("++" == op.source || "--" == op.source || |
| 5764 node.assignmentOperator.source.endsWith("=")); | 6078 node.assignmentOperator.source.endsWith("=")); |
| 5765 | 6079 handleCompoundSendSet(node); |
| 5766 Element getter = elements[node.selector]; | 6080 } |
| 5767 | 6081 } |
| 5768 if (!Elements.isUnresolved(getter) && getter.impliesType) { | 6082 |
| 5769 if (node.isIfNullAssignment) { | |
| 5770 // C ??= x is compiled just as C. | |
| 5771 stack.add(addConstant(node.selector)); | |
| 5772 } else { | |
| 5773 ast.Identifier selector = node.selector; | |
| 5774 generateThrowNoSuchMethod(node, selector.source, | |
| 5775 argumentNodes: node.arguments); | |
| 5776 } | |
| 5777 return; | |
| 5778 } | |
| 5779 | |
| 5780 if (Elements.isInstanceSend(node, elements)) { | |
| 5781 void generateAssignment(HInstruction receiver) { | |
| 5782 // desugars `e.x op= e2` to `e.x = e.x op e2` | |
| 5783 generateInstanceGetterWithCompiledReceiver( | |
| 5784 node, elements.getGetterSelectorInComplexSendSet(node), receiver); | |
| 5785 HInstruction getterInstruction = pop(); | |
| 5786 if (node.isIfNullAssignment) { | |
| 5787 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5788 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5789 () { | |
| 5790 visit(node.arguments.head); | |
| 5791 generateInstanceSetterWithCompiledReceiver( | |
| 5792 node, receiver, pop()); | |
| 5793 }); | |
| 5794 } else { | |
| 5795 handleComplexOperatorSend(node, getterInstruction, node.arguments); | |
| 5796 HInstruction value = pop(); | |
| 5797 generateInstanceSetterWithCompiledReceiver(node, receiver, value); | |
| 5798 } | |
| 5799 if (node.isPostfix) { | |
| 5800 pop(); | |
| 5801 stack.add(getterInstruction); | |
| 5802 } | |
| 5803 } | |
| 5804 if (node.isConditional) { | |
| 5805 // generate `e?.x op= e2` as: | |
| 5806 // t1 = e | |
| 5807 // t1 == null ? t1 : (t1.x = t1.x op e2); | |
| 5808 HInstruction receiver; | |
| 5809 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5810 brancher.handleConditional( | |
| 5811 () { | |
| 5812 receiver = generateInstanceSendReceiver(node); | |
| 5813 pushCheckNull(receiver); | |
| 5814 }, | |
| 5815 () => stack.add(receiver), | |
| 5816 () => generateAssignment(receiver)); | |
| 5817 } else { | |
| 5818 generateAssignment(generateInstanceSendReceiver(node)); | |
| 5819 } | |
| 5820 return; | |
| 5821 } | |
| 5822 | |
| 5823 if (getter.isErroneous) { | |
| 5824 generateStaticUnresolvedGet(node, getter); | |
| 5825 } else if (getter.isField) { | |
| 5826 generateStaticFieldGet(node, getter); | |
| 5827 } else if (getter.isGetter) { | |
| 5828 generateStaticGetterGet(node, getter); | |
| 5829 } else if (getter.isFunction) { | |
| 5830 generateStaticFunctionGet(node, getter); | |
| 5831 } else if (getter.isLocal) { | |
| 5832 handleLocalGet(getter); | |
| 5833 } else { | |
| 5834 internalError(node, "Unexpected getter: $getter"); | |
| 5835 } | |
| 5836 HInstruction getterInstruction = pop(); | |
| 5837 if (node.isIfNullAssignment) { | |
| 5838 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5839 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5840 () { | |
| 5841 visit(node.arguments.head); | |
| 5842 generateNonInstanceSetter(node, element, pop()); | |
| 5843 }); | |
| 5844 } else { | |
| 5845 handleComplexOperatorSend(node, getterInstruction, node.arguments); | |
| 5846 HInstruction value = pop(); | |
| 5847 generateNonInstanceSetter(node, element, value); | |
| 5848 } | |
| 5849 if (node.isPostfix) { | |
| 5850 pop(); | |
| 5851 stack.add(getterInstruction); | |
| 5852 } | |
| 5853 } | |
| 5854 } | |
| 5855 | |
| 5856 void visitLiteralInt(ast.LiteralInt node) { | 6083 void visitLiteralInt(ast.LiteralInt node) { |
| 5857 stack.add(graph.addConstantInt(node.value, compiler)); | 6084 stack.add(graph.addConstantInt(node.value, compiler)); |
| 5858 } | 6085 } |
| 5859 | 6086 |
| 5860 void visitLiteralDouble(ast.LiteralDouble node) { | 6087 void visitLiteralDouble(ast.LiteralDouble node) { |
| 5861 stack.add(graph.addConstantDouble(node.value, compiler)); | 6088 stack.add(graph.addConstantDouble(node.value, compiler)); |
| 5862 } | 6089 } |
| 5863 | 6090 |
| 5864 void visitLiteralBool(ast.LiteralBool node) { | 6091 void visitLiteralBool(ast.LiteralBool node) { |
| 5865 stack.add(graph.addConstantBool(node.value, compiler)); | 6092 stack.add(graph.addConstantBool(node.value, compiler)); |
| (...skipping 2006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7872 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8099 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 7873 unaliased.accept(this, builder); | 8100 unaliased.accept(this, builder); |
| 7874 } | 8101 } |
| 7875 | 8102 |
| 7876 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8103 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 7877 JavaScriptBackend backend = builder.compiler.backend; | 8104 JavaScriptBackend backend = builder.compiler.backend; |
| 7878 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8105 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 7879 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8106 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 7880 } | 8107 } |
| 7881 } | 8108 } |
| OLD | NEW |