| 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 3124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3135 node.elsePart != null ? () => visit(node.elsePart) : null); | 3135 node.elsePart != null ? () => visit(node.elsePart) : null); |
| 3136 } | 3136 } |
| 3137 | 3137 |
| 3138 void handleIf(ast.Node diagnosticNode, | 3138 void handleIf(ast.Node diagnosticNode, |
| 3139 void visitCondition(), void visitThen(), void visitElse()) { | 3139 void visitCondition(), void visitThen(), void visitElse()) { |
| 3140 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); | 3140 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); |
| 3141 branchBuilder.handleIf(visitCondition, visitThen, visitElse); | 3141 branchBuilder.handleIf(visitCondition, visitThen, visitElse); |
| 3142 } | 3142 } |
| 3143 | 3143 |
| 3144 @override | 3144 @override |
| 3145 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { |
| 3146 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 3147 brancher.handleIfNull(() => visit(left), () => visit(right)); |
| 3148 } |
| 3149 |
| 3150 @override |
| 3145 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { | 3151 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { |
| 3146 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); | 3152 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); |
| 3147 branchBuilder.handleLogicalAndOrWithLeftNode( | 3153 branchBuilder.handleLogicalAndOrWithLeftNode( |
| 3148 left, | 3154 left, |
| 3149 () { visit(right); }, | 3155 () { visit(right); }, |
| 3150 isAnd: true); | 3156 isAnd: true); |
| 3151 } | 3157 } |
| 3152 | 3158 |
| 3153 @override | 3159 @override |
| 3154 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) { | 3160 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) { |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3391 @override | 3397 @override |
| 3392 void visitDynamicPropertyGet( | 3398 void visitDynamicPropertyGet( |
| 3393 ast.Send node, | 3399 ast.Send node, |
| 3394 ast.Node receiver, | 3400 ast.Node receiver, |
| 3395 Selector selector, | 3401 Selector selector, |
| 3396 _) { | 3402 _) { |
| 3397 generateDynamicGet(node); | 3403 generateDynamicGet(node); |
| 3398 } | 3404 } |
| 3399 | 3405 |
| 3400 @override | 3406 @override |
| 3407 void visitIfNotNullDynamicPropertyGet( |
| 3408 ast.Send node, |
| 3409 ast.Node receiver, |
| 3410 Selector selector, |
| 3411 _) { |
| 3412 // exp?.x compiled as: |
| 3413 // t1 = exp; |
| 3414 // result = t1 == null ? t1 : t1.x; |
| 3415 // This is equivalent to t1 == null ? null : t1.x, but in the current form |
| 3416 // we will be able to later compress it as: |
| 3417 // t1 || t1.x |
| 3418 HInstruction expression; |
| 3419 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 3420 brancher.handleConditional( |
| 3421 () { |
| 3422 expression = visitAndPop(receiver); |
| 3423 pushCheckNull(expression); |
| 3424 }, |
| 3425 () => stack.add(expression), |
| 3426 () => generateInstanceGetterWithCompiledReceiver( |
| 3427 node, elements.getSelector(node), expression)); |
| 3428 } |
| 3429 |
| 3430 /// Pushes a boolean checking [expression] against null. |
| 3431 pushCheckNull(HInstruction expression) { |
| 3432 push(new HIdentity(expression, graph.addConstantNull(compiler), |
| 3433 null, backend.boolType)); |
| 3434 } |
| 3435 |
| 3436 @override |
| 3401 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { | 3437 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { |
| 3402 handleLocalGet(variable); | 3438 handleLocalGet(variable); |
| 3403 } | 3439 } |
| 3404 | 3440 |
| 3405 @override | 3441 @override |
| 3406 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { | 3442 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { |
| 3407 handleLocalGet(parameter); | 3443 handleLocalGet(parameter); |
| 3408 } | 3444 } |
| 3409 | 3445 |
| 3410 @override | 3446 @override |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3461 } | 3497 } |
| 3462 | 3498 |
| 3463 @override | 3499 @override |
| 3464 void visitTopLevelGetterGet( | 3500 void visitTopLevelGetterGet( |
| 3465 ast.Send node, | 3501 ast.Send node, |
| 3466 FunctionElement getter, | 3502 FunctionElement getter, |
| 3467 _) { | 3503 _) { |
| 3468 generateStaticGetterGet(node, getter); | 3504 generateStaticGetterGet(node, getter); |
| 3469 } | 3505 } |
| 3470 | 3506 |
| 3507 void generatePossiblyConditionalInstanceSetter(ast.Send send, |
| 3508 HInstruction pushReceiver(), |
| 3509 HInstruction pushValue(), |
| 3510 {Selector selector, |
| 3511 ast.Node location}) { |
| 3512 if (send.isConditional) { |
| 3513 SsaBranchBuilder brancher = new SsaBranchBuilder(this, send); |
| 3514 // compile e?.x = e2 to: |
| 3515 // |
| 3516 // t1 = e |
| 3517 // if (t1 == null) |
| 3518 // result = t1 // same as result = null |
| 3519 // else |
| 3520 // result = e.x = e2 |
| 3521 HInstruction receiver; |
| 3522 brancher.handleConditional( |
| 3523 () { |
| 3524 receiver = pushReceiver(); |
| 3525 pushCheckNull(receiver); |
| 3526 }, |
| 3527 () => stack.add(receiver), |
| 3528 () => generateInstanceSetterWithCompiledReceiver( |
| 3529 send, receiver, pushValue(), |
| 3530 selector: selector, location: location)); |
| 3531 } else { |
| 3532 generateInstanceSetterWithCompiledReceiver( |
| 3533 send, pushReceiver(), pushValue(), |
| 3534 selector: selector, location: location); |
| 3535 } |
| 3536 } |
| 3537 |
| 3471 void generateInstanceSetterWithCompiledReceiver(ast.Send send, | 3538 void generateInstanceSetterWithCompiledReceiver(ast.Send send, |
| 3472 HInstruction receiver, | 3539 HInstruction receiver, |
| 3473 HInstruction value, | 3540 HInstruction value, |
| 3474 {Selector selector, | 3541 {Selector selector, |
| 3475 ast.Node location}) { | 3542 ast.Node location}) { |
| 3476 assert(send == null || Elements.isInstanceSend(send, elements)); | 3543 assert(send == null || Elements.isInstanceSend(send, elements)); |
| 3477 if (selector == null) { | 3544 if (selector == null) { |
| 3478 assert(send != null); | 3545 assert(send != null); |
| 3479 selector = elements.getSelector(send); | 3546 selector = elements.getSelector(send); |
| 3480 } | 3547 } |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3723 | 3790 |
| 3724 void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> lis
t) { | 3791 void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> lis
t) { |
| 3725 for (; !link.isEmpty; link = link.tail) { | 3792 for (; !link.isEmpty; link = link.tail) { |
| 3726 visit(link.head); | 3793 visit(link.head); |
| 3727 list.add(pop()); | 3794 list.add(pop()); |
| 3728 } | 3795 } |
| 3729 } | 3796 } |
| 3730 | 3797 |
| 3731 /// Generate a dynamic method, getter or setter invocation. | 3798 /// Generate a dynamic method, getter or setter invocation. |
| 3732 void generateDynamicSend(ast.Send node) { | 3799 void generateDynamicSend(ast.Send node) { |
| 3800 HInstruction receiver = generateInstanceSendReceiver(node); |
| 3801 _generateDynamicSend(node, receiver); |
| 3802 } |
| 3803 |
| 3804 void _generateDynamicSend(ast.Send node, HInstruction receiver) { |
| 3733 Selector selector = elements.getSelector(node); | 3805 Selector selector = elements.getSelector(node); |
| 3734 | 3806 |
| 3735 List<HInstruction> inputs = <HInstruction>[]; | 3807 List<HInstruction> inputs = <HInstruction>[]; |
| 3736 HInstruction receiver = generateInstanceSendReceiver(node); | |
| 3737 inputs.add(receiver); | 3808 inputs.add(receiver); |
| 3738 addDynamicSendArgumentsToList(node, inputs); | 3809 addDynamicSendArgumentsToList(node, inputs); |
| 3739 | 3810 |
| 3740 pushInvokeDynamic(node, selector, inputs); | 3811 pushInvokeDynamic(node, selector, inputs); |
| 3741 if (selector.isSetter || selector.isIndexSet) { | 3812 if (selector.isSetter || selector.isIndexSet) { |
| 3742 pop(); | 3813 pop(); |
| 3743 stack.add(inputs.last); | 3814 stack.add(inputs.last); |
| 3744 } | 3815 } |
| 3745 } | 3816 } |
| 3746 | 3817 |
| 3747 @override | 3818 @override |
| 3748 visitDynamicPropertyInvoke( | 3819 visitDynamicPropertyInvoke( |
| 3749 ast.Send node, | 3820 ast.Send node, |
| 3750 ast.Node receiver, | 3821 ast.Node receiver, |
| 3751 ast.NodeList arguments, | 3822 ast.NodeList arguments, |
| 3752 Selector selector, | 3823 Selector selector, |
| 3753 _) { | 3824 _) { |
| 3754 generateDynamicSend(node); | 3825 generateDynamicSend(node); |
| 3755 } | 3826 } |
| 3756 | 3827 |
| 3757 @override | 3828 @override |
| 3829 visitIfNotNullDynamicPropertyInvoke( |
| 3830 ast.Send node, |
| 3831 ast.Node receiver, |
| 3832 ast.NodeList arguments, |
| 3833 Selector selector, |
| 3834 _) { |
| 3835 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()` |
| 3836 HInstruction receiver; |
| 3837 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 3838 brancher.handleConditional( |
| 3839 () { |
| 3840 receiver = generateInstanceSendReceiver(node); |
| 3841 pushCheckNull(receiver); |
| 3842 }, |
| 3843 () => stack.add(receiver), |
| 3844 () => _generateDynamicSend(node, receiver)); |
| 3845 } |
| 3846 |
| 3847 @override |
| 3758 visitThisPropertyInvoke( | 3848 visitThisPropertyInvoke( |
| 3759 ast.Send node, | 3849 ast.Send node, |
| 3760 ast.NodeList arguments, | 3850 ast.NodeList arguments, |
| 3761 Selector selector, | 3851 Selector selector, |
| 3762 _) { | 3852 _) { |
| 3763 generateDynamicSend(node); | 3853 generateDynamicSend(node); |
| 3764 } | 3854 } |
| 3765 | 3855 |
| 3766 @override | 3856 @override |
| 3767 visitExpressionInvoke( | 3857 visitExpressionInvoke( |
| (...skipping 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5498 generateIsDeferredLoadedCheckOfSend(node); | 5588 generateIsDeferredLoadedCheckOfSend(node); |
| 5499 Element element = elements[node]; | 5589 Element element = elements[node]; |
| 5500 if (!Elements.isUnresolved(element) && element.impliesType) { | 5590 if (!Elements.isUnresolved(element) && element.impliesType) { |
| 5501 ast.Identifier selector = node.selector; | 5591 ast.Identifier selector = node.selector; |
| 5502 generateThrowNoSuchMethod(node, selector.source, | 5592 generateThrowNoSuchMethod(node, selector.source, |
| 5503 argumentNodes: node.arguments); | 5593 argumentNodes: node.arguments); |
| 5504 return; | 5594 return; |
| 5505 } | 5595 } |
| 5506 ast.Operator op = node.assignmentOperator; | 5596 ast.Operator op = node.assignmentOperator; |
| 5507 if (node.isSuperCall) { | 5597 if (node.isSuperCall) { |
| 5508 HInstruction result; | |
| 5509 List<HInstruction> setterInputs = <HInstruction>[]; | 5598 List<HInstruction> setterInputs = <HInstruction>[]; |
| 5599 void generateSuperSendSet() { |
| 5600 Selector setterSelector = elements.getSelector(node); |
| 5601 if (Elements.isUnresolved(element) |
| 5602 || !setterSelector.applies(element, compiler.world)) { |
| 5603 generateSuperNoSuchMethodSend( |
| 5604 node, setterSelector, setterInputs); |
| 5605 pop(); |
| 5606 } else { |
| 5607 add(buildInvokeSuper(setterSelector, element, setterInputs)); |
| 5608 } |
| 5609 } |
| 5510 if (identical(node.assignmentOperator.source, '=')) { | 5610 if (identical(node.assignmentOperator.source, '=')) { |
| 5511 addDynamicSendArgumentsToList(node, setterInputs); | 5611 addDynamicSendArgumentsToList(node, setterInputs); |
| 5512 result = setterInputs.last; | 5612 generateSuperSendSet(); |
| 5613 stack.add(setterInputs.last); |
| 5513 } else { | 5614 } else { |
| 5514 Element getter = elements[node.selector]; | 5615 Element getter = elements[node.selector]; |
| 5515 List<HInstruction> getterInputs = <HInstruction>[]; | 5616 List<HInstruction> getterInputs = <HInstruction>[]; |
| 5516 Link<ast.Node> arguments = node.arguments; | 5617 Link<ast.Node> arguments = node.arguments; |
| 5517 if (node.isIndex) { | 5618 if (node.isIndex) { |
| 5518 // If node is of the from [:super.foo[0] += 2:], the send has | 5619 // If node is of the from [:super.foo[0] += 2:], the send has |
| 5519 // two arguments: the index and the left hand side. We get | 5620 // two arguments: the index and the left hand side. We get |
| 5520 // the index and add it as input of the getter and the | 5621 // the index and add it as input of the getter and the |
| 5521 // setter. | 5622 // setter. |
| 5522 visit(arguments.head); | 5623 visit(arguments.head); |
| 5523 arguments = arguments.tail; | 5624 arguments = arguments.tail; |
| 5524 HInstruction index = pop(); | 5625 HInstruction index = pop(); |
| 5525 getterInputs.add(index); | 5626 getterInputs.add(index); |
| 5526 setterInputs.add(index); | 5627 setterInputs.add(index); |
| 5527 } | 5628 } |
| 5528 HInstruction getterInstruction; | 5629 HInstruction getterInstruction; |
| 5529 Selector getterSelector = | 5630 Selector getterSelector = |
| 5530 elements.getGetterSelectorInComplexSendSet(node); | 5631 elements.getGetterSelectorInComplexSendSet(node); |
| 5531 if (Elements.isUnresolved(getter)) { | 5632 if (Elements.isUnresolved(getter)) { |
| 5532 generateSuperNoSuchMethodSend( | 5633 generateSuperNoSuchMethodSend( |
| 5533 node, | 5634 node, |
| 5534 getterSelector, | 5635 getterSelector, |
| 5535 getterInputs); | 5636 getterInputs); |
| 5536 getterInstruction = pop(); | 5637 getterInstruction = pop(); |
| 5537 } else { | 5638 } else { |
| 5538 getterInstruction = buildInvokeSuper( | 5639 getterInstruction = buildInvokeSuper( |
| 5539 getterSelector, getter, getterInputs); | 5640 getterSelector, getter, getterInputs); |
| 5540 add(getterInstruction); | 5641 add(getterInstruction); |
| 5541 } | 5642 } |
| 5542 handleComplexOperatorSend(node, getterInstruction, arguments); | |
| 5543 setterInputs.add(pop()); | |
| 5544 | 5643 |
| 5545 if (node.isPostfix) { | 5644 if (node.isIfNullAssignment) { |
| 5546 result = getterInstruction; | 5645 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5646 brancher.handleIfNull(() => stack.add(getterInstruction), |
| 5647 () { |
| 5648 addDynamicSendArgumentsToList(node, setterInputs); |
| 5649 generateSuperSendSet(); |
| 5650 stack.add(setterInputs.last); |
| 5651 }); |
| 5547 } else { | 5652 } else { |
| 5548 result = setterInputs.last; | 5653 handleComplexOperatorSend(node, getterInstruction, arguments); |
| 5654 setterInputs.add(pop()); |
| 5655 generateSuperSendSet(); |
| 5656 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); |
| 5549 } | 5657 } |
| 5550 } | 5658 } |
| 5551 Selector setterSelector = elements.getSelector(node); | |
| 5552 if (Elements.isUnresolved(element) | |
| 5553 || !setterSelector.applies(element, compiler.world)) { | |
| 5554 generateSuperNoSuchMethodSend( | |
| 5555 node, setterSelector, setterInputs); | |
| 5556 pop(); | |
| 5557 } else { | |
| 5558 add(buildInvokeSuper(setterSelector, element, setterInputs)); | |
| 5559 } | |
| 5560 stack.add(result); | |
| 5561 } else if (node.isIndex) { | 5659 } else if (node.isIndex) { |
| 5562 if ("=" == op.source) { | 5660 if ("=" == op.source) { |
| 5563 generateDynamicSend(node); | 5661 generateDynamicSend(node); |
| 5564 } else { | 5662 } else { |
| 5565 visit(node.receiver); | 5663 visit(node.receiver); |
| 5566 HInstruction receiver = pop(); | 5664 HInstruction receiver = pop(); |
| 5567 Link<ast.Node> arguments = node.arguments; | 5665 Link<ast.Node> arguments = node.arguments; |
| 5568 HInstruction index; | 5666 HInstruction index; |
| 5569 if (node.isIndex) { | 5667 if (node.isIndex) { |
| 5570 visit(arguments.head); | 5668 visit(arguments.head); |
| 5571 arguments = arguments.tail; | 5669 arguments = arguments.tail; |
| 5572 index = pop(); | 5670 index = pop(); |
| 5573 } | 5671 } |
| 5574 | 5672 |
| 5575 pushInvokeDynamic( | 5673 pushInvokeDynamic( |
| 5576 node, | 5674 node, |
| 5577 elements.getGetterSelectorInComplexSendSet(node), | 5675 elements.getGetterSelectorInComplexSendSet(node), |
| 5578 [receiver, index]); | 5676 [receiver, index]); |
| 5579 HInstruction getterInstruction = pop(); | 5677 HInstruction getterInstruction = pop(); |
| 5580 | 5678 if (node.isIfNullAssignment) { |
| 5581 handleComplexOperatorSend(node, getterInstruction, arguments); | 5679 // Compile x[i] ??= e as: |
| 5582 HInstruction value = pop(); | 5680 // t1 = x[i] |
| 5583 | 5681 // if (t1 == null) |
| 5584 pushInvokeDynamic( | 5682 // t1 = x[i] = e; |
| 5585 node, elements.getSelector(node), [receiver, index, value]); | 5683 // result = t1 |
| 5586 pop(); | 5684 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5587 | 5685 brancher.handleIfNull(() => stack.add(getterInstruction), |
| 5588 if (node.isPostfix) { | 5686 () { |
| 5589 stack.add(getterInstruction); | 5687 visit(arguments.head); |
| 5688 HInstruction value = pop(); |
| 5689 pushInvokeDynamic( |
| 5690 node, elements.getSelector(node), [receiver, index, value]); |
| 5691 pop(); |
| 5692 stack.add(value); |
| 5693 }); |
| 5590 } else { | 5694 } else { |
| 5591 stack.add(value); | 5695 handleComplexOperatorSend(node, getterInstruction, arguments); |
| 5696 HInstruction value = pop(); |
| 5697 pushInvokeDynamic( |
| 5698 node, elements.getSelector(node), [receiver, index, value]); |
| 5699 pop(); |
| 5700 if (node.isPostfix) { |
| 5701 stack.add(getterInstruction); |
| 5702 } else { |
| 5703 stack.add(value); |
| 5704 } |
| 5592 } | 5705 } |
| 5593 } | 5706 } |
| 5594 } else if ("=" == op.source) { | 5707 } else if ("=" == op.source) { |
| 5595 Link<ast.Node> link = node.arguments; | 5708 Link<ast.Node> link = node.arguments; |
| 5596 assert(!link.isEmpty && link.tail.isEmpty); | 5709 assert(!link.isEmpty && link.tail.isEmpty); |
| 5597 if (Elements.isInstanceSend(node, elements)) { | 5710 if (Elements.isInstanceSend(node, elements)) { |
| 5598 HInstruction receiver = generateInstanceSendReceiver(node); | 5711 generatePossiblyConditionalInstanceSetter(node, |
| 5599 visit(link.head); | 5712 () => generateInstanceSendReceiver(node), |
| 5600 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); | 5713 () => visitAndPop(link.head)); |
| 5601 } else { | 5714 } else { |
| 5602 visit(link.head); | 5715 visit(link.head); |
| 5603 generateNonInstanceSetter(node, element, pop()); | 5716 generateNonInstanceSetter(node, element, pop()); |
| 5604 } | 5717 } |
| 5605 } else if (identical(op.source, "is")) { | 5718 } else if (identical(op.source, "is")) { |
| 5606 compiler.internalError(op, "is-operator as SendSet."); | 5719 compiler.internalError(op, "is-operator as SendSet."); |
| 5607 } else { | 5720 } else { |
| 5608 assert("++" == op.source || "--" == op.source || | 5721 assert("++" == op.source || "--" == op.source || |
| 5609 node.assignmentOperator.source.endsWith("=")); | 5722 node.assignmentOperator.source.endsWith("=")); |
| 5610 | 5723 |
| 5611 // [receiver] is only used if the node is an instance send. | |
| 5612 HInstruction receiver = null; | |
| 5613 Element getter = elements[node.selector]; | 5724 Element getter = elements[node.selector]; |
| 5614 | 5725 |
| 5615 if (!Elements.isUnresolved(getter) && getter.impliesType) { | 5726 if (!Elements.isUnresolved(getter) && getter.impliesType) { |
| 5616 ast.Identifier selector = node.selector; | 5727 if (node.isIfNullAssignment) { |
| 5617 generateThrowNoSuchMethod(node, selector.source, | 5728 // C ??= x is compiled just as C. |
| 5618 argumentNodes: node.arguments); | 5729 stack.add(addConstant(node.selector)); |
| 5730 } else { |
| 5731 ast.Identifier selector = node.selector; |
| 5732 generateThrowNoSuchMethod(node, selector.source, |
| 5733 argumentNodes: node.arguments); |
| 5734 } |
| 5619 return; | 5735 return; |
| 5620 } else if (Elements.isInstanceSend(node, elements)) { | 5736 } |
| 5621 receiver = generateInstanceSendReceiver(node); | 5737 |
| 5622 generateInstanceGetterWithCompiledReceiver( | 5738 if (Elements.isInstanceSend(node, elements)) { |
| 5623 node, elements.getGetterSelectorInComplexSendSet(node), receiver); | 5739 void generateAssignment(HInstruction receiver) { |
| 5624 } else if (getter.isErroneous) { | 5740 // desugars `e.x op= e2` to `e.x = e.x op e2` |
| 5741 generateInstanceGetterWithCompiledReceiver( |
| 5742 node, elements.getGetterSelectorInComplexSendSet(node), receiver); |
| 5743 HInstruction getterInstruction = pop(); |
| 5744 if (node.isIfNullAssignment) { |
| 5745 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5746 brancher.handleIfNull(() => stack.add(getterInstruction), |
| 5747 () { |
| 5748 visit(node.arguments.head); |
| 5749 generateInstanceSetterWithCompiledReceiver( |
| 5750 node, receiver, pop()); |
| 5751 }); |
| 5752 } else { |
| 5753 handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| 5754 HInstruction value = pop(); |
| 5755 generateInstanceSetterWithCompiledReceiver(node, receiver, value); |
| 5756 } |
| 5757 if (node.isPostfix) { |
| 5758 pop(); |
| 5759 stack.add(getterInstruction); |
| 5760 } |
| 5761 } |
| 5762 if (node.isConditional) { |
| 5763 // generate `e?.x op= e2` as: |
| 5764 // t1 = e |
| 5765 // t1 == null ? t1 : (t1.x = t1.x op e2); |
| 5766 HInstruction receiver; |
| 5767 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5768 brancher.handleConditional( |
| 5769 () { |
| 5770 receiver = generateInstanceSendReceiver(node); |
| 5771 pushCheckNull(receiver); |
| 5772 }, |
| 5773 () => stack.add(receiver), |
| 5774 () => generateAssignment(receiver)); |
| 5775 } else { |
| 5776 generateAssignment(generateInstanceSendReceiver(node)); |
| 5777 } |
| 5778 return; |
| 5779 } |
| 5780 |
| 5781 if (getter.isErroneous) { |
| 5625 generateStaticUnresolvedGet(node, getter); | 5782 generateStaticUnresolvedGet(node, getter); |
| 5626 } else if (getter.isField) { | 5783 } else if (getter.isField) { |
| 5627 generateStaticFieldGet(node, getter); | 5784 generateStaticFieldGet(node, getter); |
| 5628 } else if (getter.isGetter) { | 5785 } else if (getter.isGetter) { |
| 5629 generateStaticGetterGet(node, getter); | 5786 generateStaticGetterGet(node, getter); |
| 5630 } else if (getter.isFunction) { | 5787 } else if (getter.isFunction) { |
| 5631 generateStaticFunctionGet(node, getter); | 5788 generateStaticFunctionGet(node, getter); |
| 5632 } else if (getter.isLocal) { | 5789 } else if (getter.isLocal) { |
| 5633 handleLocalGet(getter); | 5790 handleLocalGet(getter); |
| 5634 } else { | 5791 } else { |
| 5635 internalError(node, "Unexpected getter: $getter"); | 5792 internalError(node, "Unexpected getter: $getter"); |
| 5636 } | 5793 } |
| 5637 HInstruction getterInstruction = pop(); | 5794 HInstruction getterInstruction = pop(); |
| 5638 handleComplexOperatorSend(node, getterInstruction, node.arguments); | 5795 if (node.isIfNullAssignment) { |
| 5639 HInstruction value = pop(); | 5796 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5640 assert(value != null); | 5797 brancher.handleIfNull(() => stack.add(getterInstruction), |
| 5641 if (Elements.isInstanceSend(node, elements)) { | 5798 () { |
| 5642 assert(receiver != null); | 5799 visit(node.arguments.head); |
| 5643 generateInstanceSetterWithCompiledReceiver(node, receiver, value); | 5800 generateNonInstanceSetter(node, element, pop()); |
| 5801 }); |
| 5644 } else { | 5802 } else { |
| 5645 assert(receiver == null); | 5803 handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| 5804 HInstruction value = pop(); |
| 5646 generateNonInstanceSetter(node, element, value); | 5805 generateNonInstanceSetter(node, element, value); |
| 5647 } | 5806 } |
| 5648 if (node.isPostfix) { | 5807 if (node.isPostfix) { |
| 5649 pop(); | 5808 pop(); |
| 5650 stack.add(getterInstruction); | 5809 stack.add(getterInstruction); |
| 5651 } | 5810 } |
| 5652 } | 5811 } |
| 5653 } | 5812 } |
| 5654 | 5813 |
| 5655 void visitLiteralInt(ast.LiteralInt node) { | 5814 void visitLiteralInt(ast.LiteralInt node) { |
| (...skipping 1788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7444 } | 7603 } |
| 7445 | 7604 |
| 7446 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); | 7605 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); |
| 7447 } | 7606 } |
| 7448 | 7607 |
| 7449 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { | 7608 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { |
| 7450 assert(visitElse != null); | 7609 assert(visitElse != null); |
| 7451 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); | 7610 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); |
| 7452 } | 7611 } |
| 7453 | 7612 |
| 7613 handleIfNull(void left(), void right()) { |
| 7614 // x ?? y is transformed into: x == null ? y : x |
| 7615 HInstruction leftExpression; |
| 7616 handleConditional( |
| 7617 () { |
| 7618 left(); |
| 7619 leftExpression = builder.pop(); |
| 7620 builder.pushCheckNull(leftExpression); |
| 7621 }, |
| 7622 right, |
| 7623 () => builder.stack.add(leftExpression)); |
| 7624 } |
| 7625 |
| 7454 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) { | 7626 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) { |
| 7455 // x && y is transformed into: | 7627 // x && y is transformed into: |
| 7456 // t0 = boolify(x); | 7628 // t0 = boolify(x); |
| 7457 // if (t0) { | 7629 // if (t0) { |
| 7458 // t1 = boolify(y); | 7630 // t1 = boolify(y); |
| 7459 // } | 7631 // } |
| 7460 // result = phi(t1, false); | 7632 // result = phi(t1, false); |
| 7461 // | 7633 // |
| 7462 // x || y is transformed into: | 7634 // x || y is transformed into: |
| 7463 // t0 = boolify(x); | 7635 // t0 = boolify(x); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7662 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7834 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 7663 unaliased.accept(this, builder); | 7835 unaliased.accept(this, builder); |
| 7664 } | 7836 } |
| 7665 | 7837 |
| 7666 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7838 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 7667 JavaScriptBackend backend = builder.compiler.backend; | 7839 JavaScriptBackend backend = builder.compiler.backend; |
| 7668 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 7840 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 7669 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 7841 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 7670 } | 7842 } |
| 7671 } | 7843 } |
| OLD | NEW |