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

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 1175393004: Refactor SsaBuilder.handleSendSet; handle simple assignments directly. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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
« no previous file with comments | « no previous file | 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 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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698