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

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 ? 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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698