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

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

Issue 1151163004: Implementation of null-aware operators. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 7 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
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 3124 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart ('k') | pkg/compiler/lib/src/tree/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698