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 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 ? null : t1.x; | |
| 3415 visit(receiver); | |
|
sra1
2015/05/22 21:17:28
I think we should visit(receiver) in the visitCond
Siggi Cherem (dart-lang)
2015/05/22 22:36:08
Done.
| |
| 3416 HInstruction expression = pop(); | |
| 3417 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 3418 brancher.handleConditional(() => pushCheckNull(expression), | |
|
sra1
2015/05/22 21:17:28
It would look cleaner if this was on a new line.
Siggi Cherem (dart-lang)
2015/05/22 22:36:08
Done.
| |
| 3419 () => stack.add(graph.addConstantNull(compiler)), | |
|
Siggi Cherem (dart-lang)
2015/05/22 03:50:49
technically we know that t1 is null too, does it m
| |
| 3420 () => generateInstanceGetterWithCompiledReceiver( | |
| 3421 node, elements.getSelector(node), expression)); | |
| 3422 } | |
| 3423 | |
| 3424 /// Pushes a boolean checking [expression] against null. | |
| 3425 pushCheckNull(HInstruction expression) { | |
| 3426 push(new HIdentity(expression, graph.addConstantNull(compiler), | |
| 3427 null, backend.boolType)); | |
| 3428 } | |
| 3429 | |
| 3430 @override | |
| 3401 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { | 3431 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { |
| 3402 handleLocalGet(variable); | 3432 handleLocalGet(variable); |
| 3403 } | 3433 } |
| 3404 | 3434 |
| 3405 @override | 3435 @override |
| 3406 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { | 3436 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { |
| 3407 handleLocalGet(parameter); | 3437 handleLocalGet(parameter); |
| 3408 } | 3438 } |
| 3409 | 3439 |
| 3410 @override | 3440 @override |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3461 } | 3491 } |
| 3462 | 3492 |
| 3463 @override | 3493 @override |
| 3464 void visitTopLevelGetterGet( | 3494 void visitTopLevelGetterGet( |
| 3465 ast.Send node, | 3495 ast.Send node, |
| 3466 FunctionElement getter, | 3496 FunctionElement getter, |
| 3467 _) { | 3497 _) { |
| 3468 generateStaticGetterGet(node, getter); | 3498 generateStaticGetterGet(node, getter); |
| 3469 } | 3499 } |
| 3470 | 3500 |
| 3501 void generatePossiblyConditionalInstanceSetter(ast.Send send, | |
| 3502 HInstruction receiver, | |
| 3503 HInstruction pushValue(), | |
| 3504 {Selector selector, | |
| 3505 ast.Node location}) { | |
| 3506 if (send.isConditional) { | |
| 3507 SsaBranchBuilder brancher = new SsaBranchBuilder(this, send); | |
| 3508 // compile e?.x = e2 to: | |
| 3509 // | |
| 3510 // t1 = e | |
| 3511 // if (t1 == null) | |
| 3512 // t1 = null; | |
| 3513 // else | |
| 3514 // t1 = e.x = e2 | |
| 3515 brancher.handleConditional( | |
| 3516 () => pushCheckNull(receiver), | |
| 3517 () => stack.add(graph.addConstantNull(compiler)), | |
| 3518 () => generateInstanceSetterWithCompiledReceiver( | |
| 3519 send, receiver, pushValue(), | |
| 3520 selector: selector, location: location)); | |
| 3521 } else { | |
| 3522 generateInstanceSetterWithCompiledReceiver(send, receiver, pushValue(), | |
| 3523 selector: selector, location: location); | |
| 3524 } | |
| 3525 } | |
| 3526 | |
| 3471 void generateInstanceSetterWithCompiledReceiver(ast.Send send, | 3527 void generateInstanceSetterWithCompiledReceiver(ast.Send send, |
| 3472 HInstruction receiver, | 3528 HInstruction receiver, |
| 3473 HInstruction value, | 3529 HInstruction value, |
| 3474 {Selector selector, | 3530 {Selector selector, |
| 3475 ast.Node location}) { | 3531 ast.Node location}) { |
| 3476 assert(send == null || Elements.isInstanceSend(send, elements)); | 3532 assert(send == null || Elements.isInstanceSend(send, elements)); |
| 3477 if (selector == null) { | 3533 if (selector == null) { |
| 3478 assert(send != null); | 3534 assert(send != null); |
| 3479 selector = elements.getSelector(send); | 3535 selector = elements.getSelector(send); |
| 3480 } | 3536 } |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3723 | 3779 |
| 3724 void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> lis t) { | 3780 void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> lis t) { |
| 3725 for (; !link.isEmpty; link = link.tail) { | 3781 for (; !link.isEmpty; link = link.tail) { |
| 3726 visit(link.head); | 3782 visit(link.head); |
| 3727 list.add(pop()); | 3783 list.add(pop()); |
| 3728 } | 3784 } |
| 3729 } | 3785 } |
| 3730 | 3786 |
| 3731 /// Generate a dynamic method, getter or setter invocation. | 3787 /// Generate a dynamic method, getter or setter invocation. |
| 3732 void generateDynamicSend(ast.Send node) { | 3788 void generateDynamicSend(ast.Send node) { |
| 3789 HInstruction receiver = generateInstanceSendReceiver(node); | |
| 3790 _generateDynamicSend(node, receiver); | |
| 3791 } | |
| 3792 | |
| 3793 void _generateDynamicSend(ast.Send node, HInstruction receiver) { | |
| 3733 Selector selector = elements.getSelector(node); | 3794 Selector selector = elements.getSelector(node); |
| 3734 | 3795 |
| 3735 List<HInstruction> inputs = <HInstruction>[]; | 3796 List<HInstruction> inputs = <HInstruction>[]; |
| 3736 HInstruction receiver = generateInstanceSendReceiver(node); | |
| 3737 inputs.add(receiver); | 3797 inputs.add(receiver); |
| 3738 addDynamicSendArgumentsToList(node, inputs); | 3798 addDynamicSendArgumentsToList(node, inputs); |
| 3739 | 3799 |
| 3740 pushInvokeDynamic(node, selector, inputs); | 3800 pushInvokeDynamic(node, selector, inputs); |
| 3741 if (selector.isSetter || selector.isIndexSet) { | 3801 if (selector.isSetter || selector.isIndexSet) { |
| 3742 pop(); | 3802 pop(); |
| 3743 stack.add(inputs.last); | 3803 stack.add(inputs.last); |
| 3744 } | 3804 } |
| 3745 } | 3805 } |
| 3746 | 3806 |
| 3747 @override | 3807 @override |
| 3748 visitDynamicPropertyInvoke( | 3808 visitDynamicPropertyInvoke( |
| 3749 ast.Send node, | 3809 ast.Send node, |
| 3750 ast.Node receiver, | 3810 ast.Node receiver, |
| 3751 ast.NodeList arguments, | 3811 ast.NodeList arguments, |
| 3752 Selector selector, | 3812 Selector selector, |
| 3753 _) { | 3813 _) { |
| 3754 generateDynamicSend(node); | 3814 generateDynamicSend(node); |
| 3755 } | 3815 } |
| 3756 | 3816 |
| 3757 @override | 3817 @override |
| 3818 visitIfNotNullDynamicPropertyInvoke( | |
| 3819 ast.Send node, | |
| 3820 ast.Node receiver, | |
| 3821 ast.NodeList arguments, | |
| 3822 Selector selector, | |
| 3823 _) { | |
| 3824 HInstruction receiver = generateInstanceSendReceiver(node); | |
| 3825 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 3826 brancher.handleConditional(() => pushCheckNull(receiver), | |
| 3827 () => stack.add(graph.addConstantNull(compiler)), | |
|
sra1
2015/05/22 21:17:28
We probably want to preserve the variant of null (
Siggi Cherem (dart-lang)
2015/05/22 22:36:08
Done.
| |
| 3828 () => _generateDynamicSend(node, receiver)); | |
| 3829 } | |
| 3830 | |
| 3831 @override | |
| 3758 visitThisPropertyInvoke( | 3832 visitThisPropertyInvoke( |
| 3759 ast.Send node, | 3833 ast.Send node, |
| 3760 ast.NodeList arguments, | 3834 ast.NodeList arguments, |
| 3761 Selector selector, | 3835 Selector selector, |
| 3762 _) { | 3836 _) { |
| 3763 generateDynamicSend(node); | 3837 generateDynamicSend(node); |
| 3764 } | 3838 } |
| 3765 | 3839 |
| 3766 @override | 3840 @override |
| 3767 visitExpressionInvoke( | 3841 visitExpressionInvoke( |
| (...skipping 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5498 generateIsDeferredLoadedCheckOfSend(node); | 5572 generateIsDeferredLoadedCheckOfSend(node); |
| 5499 Element element = elements[node]; | 5573 Element element = elements[node]; |
| 5500 if (!Elements.isUnresolved(element) && element.impliesType) { | 5574 if (!Elements.isUnresolved(element) && element.impliesType) { |
| 5501 ast.Identifier selector = node.selector; | 5575 ast.Identifier selector = node.selector; |
| 5502 generateThrowNoSuchMethod(node, selector.source, | 5576 generateThrowNoSuchMethod(node, selector.source, |
| 5503 argumentNodes: node.arguments); | 5577 argumentNodes: node.arguments); |
| 5504 return; | 5578 return; |
| 5505 } | 5579 } |
| 5506 ast.Operator op = node.assignmentOperator; | 5580 ast.Operator op = node.assignmentOperator; |
| 5507 if (node.isSuperCall) { | 5581 if (node.isSuperCall) { |
| 5508 HInstruction result; | |
| 5509 List<HInstruction> setterInputs = <HInstruction>[]; | 5582 List<HInstruction> setterInputs = <HInstruction>[]; |
| 5583 void generateSuperSendSet() { | |
| 5584 Selector setterSelector = elements.getSelector(node); | |
| 5585 if (Elements.isUnresolved(element) | |
| 5586 || !setterSelector.applies(element, compiler.world)) { | |
| 5587 generateSuperNoSuchMethodSend( | |
| 5588 node, setterSelector, setterInputs); | |
| 5589 pop(); | |
| 5590 } else { | |
| 5591 add(buildInvokeSuper(setterSelector, element, setterInputs)); | |
| 5592 } | |
| 5593 } | |
| 5510 if (identical(node.assignmentOperator.source, '=')) { | 5594 if (identical(node.assignmentOperator.source, '=')) { |
| 5511 addDynamicSendArgumentsToList(node, setterInputs); | 5595 addDynamicSendArgumentsToList(node, setterInputs); |
| 5512 result = setterInputs.last; | 5596 generateSuperSendSet(); |
| 5597 stack.add(setterInputs.last); | |
| 5513 } else { | 5598 } else { |
| 5514 Element getter = elements[node.selector]; | 5599 Element getter = elements[node.selector]; |
| 5515 List<HInstruction> getterInputs = <HInstruction>[]; | 5600 List<HInstruction> getterInputs = <HInstruction>[]; |
| 5516 Link<ast.Node> arguments = node.arguments; | 5601 Link<ast.Node> arguments = node.arguments; |
| 5517 if (node.isIndex) { | 5602 if (node.isIndex) { |
| 5518 // If node is of the from [:super.foo[0] += 2:], the send has | 5603 // 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 | 5604 // two arguments: the index and the left hand side. We get |
| 5520 // the index and add it as input of the getter and the | 5605 // the index and add it as input of the getter and the |
| 5521 // setter. | 5606 // setter. |
| 5522 visit(arguments.head); | 5607 visit(arguments.head); |
| 5523 arguments = arguments.tail; | 5608 arguments = arguments.tail; |
| 5524 HInstruction index = pop(); | 5609 HInstruction index = pop(); |
| 5525 getterInputs.add(index); | 5610 getterInputs.add(index); |
| 5526 setterInputs.add(index); | 5611 setterInputs.add(index); |
| 5527 } | 5612 } |
| 5528 HInstruction getterInstruction; | 5613 HInstruction getterInstruction; |
| 5529 Selector getterSelector = | 5614 Selector getterSelector = |
| 5530 elements.getGetterSelectorInComplexSendSet(node); | 5615 elements.getGetterSelectorInComplexSendSet(node); |
| 5531 if (Elements.isUnresolved(getter)) { | 5616 if (Elements.isUnresolved(getter)) { |
| 5532 generateSuperNoSuchMethodSend( | 5617 generateSuperNoSuchMethodSend( |
| 5533 node, | 5618 node, |
| 5534 getterSelector, | 5619 getterSelector, |
| 5535 getterInputs); | 5620 getterInputs); |
| 5536 getterInstruction = pop(); | 5621 getterInstruction = pop(); |
| 5537 } else { | 5622 } else { |
| 5538 getterInstruction = buildInvokeSuper( | 5623 getterInstruction = buildInvokeSuper( |
| 5539 getterSelector, getter, getterInputs); | 5624 getterSelector, getter, getterInputs); |
| 5540 add(getterInstruction); | 5625 add(getterInstruction); |
| 5541 } | 5626 } |
| 5542 handleComplexOperatorSend(node, getterInstruction, arguments); | |
| 5543 setterInputs.add(pop()); | |
| 5544 | 5627 |
| 5545 if (node.isPostfix) { | 5628 if (node.isIfNullAssignment) { |
| 5546 result = getterInstruction; | 5629 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5630 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5631 () { | |
| 5632 addDynamicSendArgumentsToList(node, setterInputs); | |
| 5633 generateSuperSendSet(); | |
| 5634 stack.add(setterInputs.last); | |
| 5635 }); | |
| 5547 } else { | 5636 } else { |
| 5548 result = setterInputs.last; | 5637 handleComplexOperatorSend(node, getterInstruction, arguments); |
| 5638 setterInputs.add(pop()); | |
| 5639 generateSuperSendSet(); | |
| 5640 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); | |
| 5549 } | 5641 } |
| 5550 } | 5642 } |
| 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) { | 5643 } else if (node.isIndex) { |
| 5562 if ("=" == op.source) { | 5644 if ("=" == op.source) { |
| 5563 generateDynamicSend(node); | 5645 generateDynamicSend(node); |
| 5564 } else { | 5646 } else { |
| 5565 visit(node.receiver); | 5647 visit(node.receiver); |
| 5566 HInstruction receiver = pop(); | 5648 HInstruction receiver = pop(); |
| 5567 Link<ast.Node> arguments = node.arguments; | 5649 Link<ast.Node> arguments = node.arguments; |
| 5568 HInstruction index; | 5650 HInstruction index; |
| 5569 if (node.isIndex) { | 5651 if (node.isIndex) { |
| 5570 visit(arguments.head); | 5652 visit(arguments.head); |
| 5571 arguments = arguments.tail; | 5653 arguments = arguments.tail; |
| 5572 index = pop(); | 5654 index = pop(); |
| 5573 } | 5655 } |
| 5574 | 5656 |
| 5575 pushInvokeDynamic( | 5657 pushInvokeDynamic( |
| 5576 node, | 5658 node, |
| 5577 elements.getGetterSelectorInComplexSendSet(node), | 5659 elements.getGetterSelectorInComplexSendSet(node), |
| 5578 [receiver, index]); | 5660 [receiver, index]); |
| 5579 HInstruction getterInstruction = pop(); | 5661 HInstruction getterInstruction = pop(); |
| 5580 | 5662 if (node.isIfNullAssignment) { |
| 5581 handleComplexOperatorSend(node, getterInstruction, arguments); | 5663 // Compile x[i] ??= e as: |
| 5582 HInstruction value = pop(); | 5664 // t1 = x[i] |
| 5583 | 5665 // if (t1 == null) |
| 5584 pushInvokeDynamic( | 5666 // t1 = x[i] = e; |
| 5585 node, elements.getSelector(node), [receiver, index, value]); | 5667 // result = t1 |
| 5586 pop(); | 5668 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5587 | 5669 brancher.handleIfNull(() => stack.add(getterInstruction), |
| 5588 if (node.isPostfix) { | 5670 () { |
| 5589 stack.add(getterInstruction); | 5671 visit(arguments.head); |
| 5672 HInstruction value = pop(); | |
| 5673 pushInvokeDynamic( | |
| 5674 node, elements.getSelector(node), [receiver, index, value]); | |
| 5675 pop(); | |
| 5676 stack.add(value); | |
| 5677 }); | |
| 5590 } else { | 5678 } else { |
| 5591 stack.add(value); | 5679 handleComplexOperatorSend(node, getterInstruction, arguments); |
| 5680 HInstruction value = pop(); | |
| 5681 pushInvokeDynamic( | |
| 5682 node, elements.getSelector(node), [receiver, index, value]); | |
| 5683 pop(); | |
| 5684 if (node.isPostfix) { | |
| 5685 stack.add(getterInstruction); | |
| 5686 } else { | |
| 5687 stack.add(value); | |
| 5688 } | |
| 5592 } | 5689 } |
| 5593 } | 5690 } |
| 5594 } else if ("=" == op.source) { | 5691 } else if ("=" == op.source) { |
| 5595 Link<ast.Node> link = node.arguments; | 5692 Link<ast.Node> link = node.arguments; |
| 5596 assert(!link.isEmpty && link.tail.isEmpty); | 5693 assert(!link.isEmpty && link.tail.isEmpty); |
| 5597 if (Elements.isInstanceSend(node, elements)) { | 5694 if (Elements.isInstanceSend(node, elements)) { |
| 5598 HInstruction receiver = generateInstanceSendReceiver(node); | 5695 HInstruction receiver = generateInstanceSendReceiver(node); |
| 5599 visit(link.head); | 5696 generatePossiblyConditionalInstanceSetter(node, receiver, |
| 5600 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); | 5697 () => visitAndPop(link.head)); |
| 5601 } else { | 5698 } else { |
| 5602 visit(link.head); | 5699 visit(link.head); |
| 5603 generateNonInstanceSetter(node, element, pop()); | 5700 generateNonInstanceSetter(node, element, pop()); |
| 5604 } | 5701 } |
| 5605 } else if (identical(op.source, "is")) { | 5702 } else if (identical(op.source, "is")) { |
| 5606 compiler.internalError(op, "is-operator as SendSet."); | 5703 compiler.internalError(op, "is-operator as SendSet."); |
| 5607 } else { | 5704 } else { |
| 5608 assert("++" == op.source || "--" == op.source || | 5705 assert("++" == op.source || "--" == op.source || |
| 5609 node.assignmentOperator.source.endsWith("=")); | 5706 node.assignmentOperator.source.endsWith("=")); |
| 5610 | 5707 |
| 5611 // [receiver] is only used if the node is an instance send. | |
| 5612 HInstruction receiver = null; | |
| 5613 Element getter = elements[node.selector]; | 5708 Element getter = elements[node.selector]; |
| 5614 | 5709 |
| 5615 if (!Elements.isUnresolved(getter) && getter.impliesType) { | 5710 if (!Elements.isUnresolved(getter) && getter.impliesType) { |
| 5616 ast.Identifier selector = node.selector; | 5711 if (node.isIfNullAssignment) { |
| 5617 generateThrowNoSuchMethod(node, selector.source, | 5712 // C ??= x is compiled just as C. |
| 5618 argumentNodes: node.arguments); | 5713 stack.add(addConstant(node.selector)); |
| 5714 } else { | |
| 5715 ast.Identifier selector = node.selector; | |
| 5716 generateThrowNoSuchMethod(node, selector.source, | |
| 5717 argumentNodes: node.arguments); | |
| 5718 } | |
| 5619 return; | 5719 return; |
| 5620 } else if (Elements.isInstanceSend(node, elements)) { | 5720 } |
| 5621 receiver = generateInstanceSendReceiver(node); | 5721 |
| 5622 generateInstanceGetterWithCompiledReceiver( | 5722 if (Elements.isInstanceSend(node, elements)) { |
| 5623 node, elements.getGetterSelectorInComplexSendSet(node), receiver); | 5723 final HInstruction receiver = generateInstanceSendReceiver(node); |
| 5624 } else if (getter.isErroneous) { | 5724 void generateAssignment() { |
| 5725 // desugarizes `e.x op= e2` as: `e.x = e.x op e2` | |
|
sra1
2015/05/22 21:17:28
Desugars ... to: ...
| |
| 5726 generateInstanceGetterWithCompiledReceiver( | |
| 5727 node, elements.getGetterSelectorInComplexSendSet(node), receiver); | |
| 5728 HInstruction getterInstruction = pop(); | |
| 5729 if (node.isIfNullAssignment) { | |
| 5730 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5731 brancher.handleIfNull(() => stack.add(getterInstruction), | |
| 5732 () { | |
| 5733 visit(node.arguments.head); | |
| 5734 generateInstanceSetterWithCompiledReceiver( | |
| 5735 node, receiver, pop()); | |
| 5736 }); | |
| 5737 } else { | |
| 5738 handleComplexOperatorSend(node, getterInstruction, node.arguments); | |
| 5739 HInstruction value = pop(); | |
| 5740 generateInstanceSetterWithCompiledReceiver(node, receiver, value); | |
| 5741 } | |
| 5742 if (node.isPostfix) { | |
| 5743 pop(); | |
| 5744 stack.add(getterInstruction); | |
| 5745 } | |
| 5746 } | |
| 5747 if (node.isConditional) { | |
| 5748 // generate `e?.x op= e2` as: | |
| 5749 // t1 = e | |
| 5750 // t1 == null ? null : (t1.x = t1.x op e2); | |
| 5751 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | |
| 5752 brancher.handleConditional( | |
| 5753 () => pushCheckNull(receiver), | |
| 5754 () => stack.add(graph.addConstantNull(compiler)), | |
| 5755 generateAssignment); | |
| 5756 } else { | |
| 5757 generateAssignment(); | |
| 5758 } | |
| 5759 return; | |
| 5760 } | |
| 5761 | |
| 5762 if (getter.isErroneous) { | |
| 5625 generateStaticUnresolvedGet(node, getter); | 5763 generateStaticUnresolvedGet(node, getter); |
| 5626 } else if (getter.isField) { | 5764 } else if (getter.isField) { |
| 5627 generateStaticFieldGet(node, getter); | 5765 generateStaticFieldGet(node, getter); |
| 5628 } else if (getter.isGetter) { | 5766 } else if (getter.isGetter) { |
| 5629 generateStaticGetterGet(node, getter); | 5767 generateStaticGetterGet(node, getter); |
| 5630 } else if (getter.isFunction) { | 5768 } else if (getter.isFunction) { |
| 5631 generateStaticFunctionGet(node, getter); | 5769 generateStaticFunctionGet(node, getter); |
| 5632 } else if (getter.isLocal) { | 5770 } else if (getter.isLocal) { |
| 5633 handleLocalGet(getter); | 5771 handleLocalGet(getter); |
| 5634 } else { | 5772 } else { |
| 5635 internalError(node, "Unexpected getter: $getter"); | 5773 internalError(node, "Unexpected getter: $getter"); |
| 5636 } | 5774 } |
| 5637 HInstruction getterInstruction = pop(); | 5775 HInstruction getterInstruction = pop(); |
| 5638 handleComplexOperatorSend(node, getterInstruction, node.arguments); | 5776 if (node.isIfNullAssignment) { |
| 5639 HInstruction value = pop(); | 5777 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5640 assert(value != null); | 5778 brancher.handleIfNull(() => stack.add(getterInstruction), |
| 5641 if (Elements.isInstanceSend(node, elements)) { | 5779 () { |
| 5642 assert(receiver != null); | 5780 visit(node.arguments.head); |
| 5643 generateInstanceSetterWithCompiledReceiver(node, receiver, value); | 5781 generateNonInstanceSetter(node, element, pop()); |
| 5782 }); | |
| 5644 } else { | 5783 } else { |
| 5645 assert(receiver == null); | 5784 handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| 5785 HInstruction value = pop(); | |
| 5646 generateNonInstanceSetter(node, element, value); | 5786 generateNonInstanceSetter(node, element, value); |
| 5647 } | 5787 } |
| 5648 if (node.isPostfix) { | 5788 if (node.isPostfix) { |
| 5649 pop(); | 5789 pop(); |
| 5650 stack.add(getterInstruction); | 5790 stack.add(getterInstruction); |
| 5651 } | 5791 } |
| 5652 } | 5792 } |
| 5653 } | 5793 } |
| 5654 | 5794 |
| 5655 void visitLiteralInt(ast.LiteralInt node) { | 5795 void visitLiteralInt(ast.LiteralInt node) { |
| (...skipping 1788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7444 } | 7584 } |
| 7445 | 7585 |
| 7446 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); | 7586 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); |
| 7447 } | 7587 } |
| 7448 | 7588 |
| 7449 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { | 7589 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { |
| 7450 assert(visitElse != null); | 7590 assert(visitElse != null); |
| 7451 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); | 7591 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); |
| 7452 } | 7592 } |
| 7453 | 7593 |
| 7594 handleIfNull(void left(), void right()) { | |
| 7595 // x ?? y is transformed into: x == null ? y : x | |
| 7596 left(); | |
| 7597 HInstruction leftExpression = builder.pop(); | |
| 7598 handleConditional( | |
| 7599 () => builder.pushCheckNull(leftExpression), | |
|
sra1
2015/05/22 21:17:28
left() should be called in here.
Siggi Cherem (dart-lang)
2015/05/22 22:36:08
Done
| |
| 7600 right, | |
| 7601 () => builder.stack.add(leftExpression)); | |
| 7602 } | |
| 7603 | |
| 7454 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) { | 7604 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) { |
| 7455 // x && y is transformed into: | 7605 // x && y is transformed into: |
| 7456 // t0 = boolify(x); | 7606 // t0 = boolify(x); |
| 7457 // if (t0) { | 7607 // if (t0) { |
| 7458 // t1 = boolify(y); | 7608 // t1 = boolify(y); |
| 7459 // } | 7609 // } |
| 7460 // result = phi(t1, false); | 7610 // result = phi(t1, false); |
| 7461 // | 7611 // |
| 7462 // x || y is transformed into: | 7612 // x || y is transformed into: |
| 7463 // t0 = boolify(x); | 7613 // t0 = boolify(x); |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7664 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7814 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 7665 unaliased.accept(this, builder); | 7815 unaliased.accept(this, builder); |
| 7666 } | 7816 } |
| 7667 | 7817 |
| 7668 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7818 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 7669 JavaScriptBackend backend = builder.compiler.backend; | 7819 JavaScriptBackend backend = builder.compiler.backend; |
| 7670 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 7820 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 7671 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 7821 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 7672 } | 7822 } |
| 7673 } | 7823 } |
| OLD | NEW |