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 /** | 7 /** |
8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
(...skipping 4652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4663 JumpHandler jumpHandler, | 4663 JumpHandler jumpHandler, |
4664 HInstruction buildExpression(), | 4664 HInstruction buildExpression(), |
4665 var switchCases, | 4665 var switchCases, |
4666 Iterable<Constant> getConstants(SwitchCase switchCase), | 4666 Iterable<Constant> getConstants(SwitchCase switchCase), |
4667 bool isDefaultCase(SwitchCase switchCase), | 4667 bool isDefaultCase(SwitchCase switchCase), |
4668 void buildSwitchCase(SwitchCase switchCase)) { | 4668 void buildSwitchCase(SwitchCase switchCase)) { |
4669 Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>(); | 4669 Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>(); |
4670 | 4670 |
4671 // TODO(ngeoffray): Handle switch-instruction in bailout code. | 4671 // TODO(ngeoffray): Handle switch-instruction in bailout code. |
4672 work.allowSpeculativeOptimization = false; | 4672 work.allowSpeculativeOptimization = false; |
4673 // Then build a switch structure. | |
4674 HBasicBlock expressionStart = openNewBlock(); | 4673 HBasicBlock expressionStart = openNewBlock(); |
4675 HInstruction expression = buildExpression(); | 4674 HInstruction expression = buildExpression(); |
4676 if (switchCases.isEmpty) { | 4675 if (switchCases.isEmpty) { |
4677 return; | 4676 return; |
4678 } | 4677 } |
4679 HBasicBlock expressionEnd = current; | |
4680 | 4678 |
4681 HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]); | 4679 HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]); |
4682 HBasicBlock expressionBlock = close(switchInstruction); | 4680 HBasicBlock expressionEnd = close(switchInstruction); |
4683 LocalsHandler savedLocals = localsHandler; | 4681 LocalsHandler savedLocals = localsHandler; |
4684 | 4682 |
4685 List<List<Constant>> matchExpressions = <List<Constant>>[]; | 4683 List<List<Constant>> matchExpressions = <List<Constant>>[]; |
4686 List<HStatementInformation> statements = <HStatementInformation>[]; | 4684 List<HStatementInformation> statements = <HStatementInformation>[]; |
4687 bool hasDefault = false; | 4685 bool hasDefault = false; |
4688 Element getFallThroughErrorElement = backend.getFallThroughError(); | 4686 Element getFallThroughErrorElement = backend.getFallThroughError(); |
4689 HasNextIterator<Node> caseIterator = | 4687 HasNextIterator<Node> caseIterator = |
4690 new HasNextIterator<Node>(switchCases.iterator); | 4688 new HasNextIterator<Node>(switchCases.iterator); |
4691 while (caseIterator.hasNext) { | 4689 while (caseIterator.hasNext) { |
4692 SwitchCase switchCase = caseIterator.next(); | 4690 SwitchCase switchCase = caseIterator.next(); |
4693 List<Constant> caseConstants = <Constant>[]; | 4691 List<Constant> caseConstants = <Constant>[]; |
4694 HBasicBlock block = graph.addNewBlock(); | 4692 HBasicBlock block = graph.addNewBlock(); |
4695 for (Constant constant in getConstants(switchCase)) { | 4693 for (Constant constant in getConstants(switchCase)) { |
4696 caseConstants.add(constant); | 4694 caseConstants.add(constant); |
4697 HConstant hConstant = graph.addConstant(constant, compiler); | 4695 HConstant hConstant = graph.addConstant(constant, compiler); |
4698 switchInstruction.inputs.add(hConstant); | 4696 switchInstruction.inputs.add(hConstant); |
4699 hConstant.usedBy.add(switchInstruction); | 4697 hConstant.usedBy.add(switchInstruction); |
4700 expressionBlock.addSuccessor(block); | 4698 expressionEnd.addSuccessor(block); |
4701 } | 4699 } |
4702 matchExpressions.add(caseConstants); | 4700 matchExpressions.add(caseConstants); |
4703 | 4701 |
4704 if (isDefaultCase(switchCase)) { | 4702 if (isDefaultCase(switchCase)) { |
4705 // An HSwitch has n inputs and n+1 successors, the last being the | 4703 // An HSwitch has n inputs and n+1 successors, the last being the |
4706 // default case. | 4704 // default case. |
4707 expressionBlock.addSuccessor(block); | 4705 expressionEnd.addSuccessor(block); |
4708 hasDefault = true; | 4706 hasDefault = true; |
4709 } | 4707 } |
4710 open(block); | 4708 open(block); |
4711 localsHandler = new LocalsHandler.from(savedLocals); | 4709 localsHandler = new LocalsHandler.from(savedLocals); |
4712 buildSwitchCase(switchCase); | 4710 buildSwitchCase(switchCase); |
4713 if (!isAborted() && caseIterator.hasNext) { | 4711 if (!isAborted()) { |
4714 pushInvokeStatic(switchCase, getFallThroughErrorElement, []); | 4712 if (caseIterator.hasNext) { |
4715 HInstruction error = pop(); | 4713 pushInvokeStatic(switchCase, getFallThroughErrorElement, []); |
4716 closeAndGotoExit(new HThrow(error)); | 4714 HInstruction error = pop(); |
| 4715 closeAndGotoExit(new HThrow(error)); |
| 4716 } else if (!isDefaultCase(switchCase)) { |
| 4717 // If there is no default, we will add one later to avoid |
| 4718 // the critical edge. So we generate a break statement to make |
| 4719 // sure the last case does not fall through to the default case. |
| 4720 jumpHandler.generateBreak(); |
| 4721 } |
4717 } | 4722 } |
4718 statements.add( | 4723 statements.add( |
4719 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); | 4724 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); |
4720 } | 4725 } |
4721 | 4726 |
4722 // Add a join-block if necessary. | 4727 // Add a join-block if necessary. |
4723 // We create [joinBlock] early, and then go through the cases that might | 4728 // We create [joinBlock] early, and then go through the cases that might |
4724 // want to jump to it. In each case, if we add [joinBlock] as a successor | 4729 // want to jump to it. In each case, if we add [joinBlock] as a successor |
4725 // of another block, we also add an element to [caseHandlers] that is used | 4730 // of another block, we also add an element to [caseHandlers] that is used |
4726 // to create the phis in [joinBlock]. | 4731 // to create the phis in [joinBlock]. |
4727 // If we never jump to the join block, [caseHandlers] will stay empty, and | 4732 // If we never jump to the join block, [caseHandlers] will stay empty, and |
4728 // the join block is never added to the graph. | 4733 // the join block is never added to the graph. |
4729 HBasicBlock joinBlock = new HBasicBlock(); | 4734 HBasicBlock joinBlock = new HBasicBlock(); |
4730 List<LocalsHandler> caseHandlers = <LocalsHandler>[]; | 4735 List<LocalsHandler> caseHandlers = <LocalsHandler>[]; |
4731 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { | 4736 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { |
4732 instruction.block.addSuccessor(joinBlock); | 4737 instruction.block.addSuccessor(joinBlock); |
4733 caseHandlers.add(locals); | 4738 caseHandlers.add(locals); |
4734 }); | 4739 }); |
4735 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 4740 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { |
4736 assert(invariant(errorNode, false, | 4741 assert(invariant(errorNode, false, |
4737 message: 'Continue cannot target a switch.')); | 4742 message: 'Continue cannot target a switch.')); |
4738 }); | 4743 }); |
4739 if (!isAborted()) { | 4744 if (!isAborted()) { |
4740 current.close(new HGoto()); | 4745 current.close(new HGoto()); |
4741 lastOpenedBlock.addSuccessor(joinBlock); | 4746 lastOpenedBlock.addSuccessor(joinBlock); |
4742 caseHandlers.add(localsHandler); | 4747 caseHandlers.add(localsHandler); |
4743 } | 4748 } |
4744 if (!hasDefault) { | 4749 if (!hasDefault) { |
4745 // The current flow is only aborted if the switch has a default that | 4750 // Always create a default case, to avoid a critical edge in the |
4746 // aborts (all previous cases must abort, and if there is no default, | 4751 // graph. |
4747 // it's possible to miss all the cases). | 4752 HBasicBlock defaultCase = addNewBlock(); |
4748 expressionEnd.addSuccessor(joinBlock); | 4753 expressionEnd.addSuccessor(defaultCase); |
| 4754 open(defaultCase); |
| 4755 close(new HGoto()); |
| 4756 defaultCase.addSuccessor(joinBlock); |
4749 caseHandlers.add(savedLocals); | 4757 caseHandlers.add(savedLocals); |
| 4758 matchExpressions.add(<Constant>[]); |
| 4759 statements.add(new HSubGraphBlockInformation(new SubGraph( |
| 4760 defaultCase, defaultCase))); |
4750 } | 4761 } |
4751 assert(caseHandlers.length == joinBlock.predecessors.length); | 4762 assert(caseHandlers.length == joinBlock.predecessors.length); |
4752 if (caseHandlers.length != 0) { | 4763 if (caseHandlers.length != 0) { |
4753 graph.addBlock(joinBlock); | 4764 graph.addBlock(joinBlock); |
4754 open(joinBlock); | 4765 open(joinBlock); |
4755 if (caseHandlers.length == 1) { | 4766 if (caseHandlers.length == 1) { |
4756 localsHandler = caseHandlers[0]; | 4767 localsHandler = caseHandlers[0]; |
4757 } else { | 4768 } else { |
4758 localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock); | 4769 localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock); |
4759 } | 4770 } |
4760 } else { | 4771 } else { |
4761 // The joinblock is not used. | 4772 // The joinblock is not used. |
4762 joinBlock = null; | 4773 joinBlock = null; |
4763 } | 4774 } |
4764 | 4775 |
4765 HSubExpressionBlockInformation expressionInfo = | 4776 HSubExpressionBlockInformation expressionInfo = |
4766 new HSubExpressionBlockInformation(new SubExpression(expressionStart, | 4777 new HSubExpressionBlockInformation(new SubExpression(expressionStart, |
4767 expressionEnd)); | 4778 expressionEnd)); |
4768 expressionStart.setBlockFlow( | 4779 expressionStart.setBlockFlow( |
4769 new HSwitchBlockInformation(expressionInfo, | 4780 new HSwitchBlockInformation(expressionInfo, |
4770 matchExpressions, | 4781 matchExpressions, |
4771 statements, | 4782 statements, |
4772 hasDefault, | |
4773 jumpHandler.target, | 4783 jumpHandler.target, |
4774 jumpHandler.labels()), | 4784 jumpHandler.labels()), |
4775 joinBlock); | 4785 joinBlock); |
4776 | 4786 |
4777 jumpHandler.close(); | 4787 jumpHandler.close(); |
4778 } | 4788 } |
4779 | 4789 |
4780 bool nonPrimitiveTypeOverridesEquals(Constant constant) { | 4790 bool nonPrimitiveTypeOverridesEquals(Constant constant) { |
4781 // Function values override equals. Even static ones, since | 4791 // Function values override equals. Even static ones, since |
4782 // they inherit from [Function]. | 4792 // they inherit from [Function]. |
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5443 new HSubGraphBlockInformation(elseBranch.graph)); | 5453 new HSubGraphBlockInformation(elseBranch.graph)); |
5444 | 5454 |
5445 HBasicBlock conditionStartBlock = conditionBranch.block; | 5455 HBasicBlock conditionStartBlock = conditionBranch.block; |
5446 conditionStartBlock.setBlockFlow(info, joinBlock); | 5456 conditionStartBlock.setBlockFlow(info, joinBlock); |
5447 SubGraph conditionGraph = conditionBranch.graph; | 5457 SubGraph conditionGraph = conditionBranch.graph; |
5448 HIf branch = conditionGraph.end.last; | 5458 HIf branch = conditionGraph.end.last; |
5449 assert(branch is HIf); | 5459 assert(branch is HIf); |
5450 branch.blockInformation = conditionStartBlock.blockFlow; | 5460 branch.blockInformation = conditionStartBlock.blockFlow; |
5451 } | 5461 } |
5452 } | 5462 } |
OLD | NEW |