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() && caseIterator.hasNext) { |
4714 pushInvokeStatic(switchCase, getFallThroughErrorElement, []); | 4712 pushInvokeStatic(switchCase, getFallThroughErrorElement, []); |
4715 HInstruction error = pop(); | 4713 HInstruction error = pop(); |
4716 closeAndGotoExit(new HThrow(error)); | 4714 closeAndGotoExit(new HThrow(error)); |
4717 } | 4715 } |
(...skipping 17 matching lines...) Expand all Loading... | |
4735 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 4733 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { |
4736 assert(invariant(errorNode, false, | 4734 assert(invariant(errorNode, false, |
4737 message: 'Continue cannot target a switch.')); | 4735 message: 'Continue cannot target a switch.')); |
4738 }); | 4736 }); |
4739 if (!isAborted()) { | 4737 if (!isAborted()) { |
4740 current.close(new HGoto()); | 4738 current.close(new HGoto()); |
4741 lastOpenedBlock.addSuccessor(joinBlock); | 4739 lastOpenedBlock.addSuccessor(joinBlock); |
4742 caseHandlers.add(localsHandler); | 4740 caseHandlers.add(localsHandler); |
4743 } | 4741 } |
4744 if (!hasDefault) { | 4742 if (!hasDefault) { |
4745 // The current flow is only aborted if the switch has a default that | 4743 // 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, | 4744 // graph. |
4747 // it's possible to miss all the cases). | 4745 HBasicBlock avoidCriticalEdge = addNewBlock(); |
karlklose
2013/08/14 14:36:43
Rename variable to 'defaultCase'?
ngeoffray
2013/08/14 14:57:57
Done.
| |
4748 expressionEnd.addSuccessor(joinBlock); | 4746 expressionEnd.addSuccessor(avoidCriticalEdge); |
4747 open(avoidCriticalEdge); | |
4748 close(new HGoto()); | |
4749 avoidCriticalEdge.addSuccessor(joinBlock); | |
4749 caseHandlers.add(savedLocals); | 4750 caseHandlers.add(savedLocals); |
4751 matchExpressions.add(<Constant>[]); | |
4752 statements.add(new HSubGraphBlockInformation(new SubGraph( | |
4753 avoidCriticalEdge, avoidCriticalEdge))); | |
4750 } | 4754 } |
4751 assert(caseHandlers.length == joinBlock.predecessors.length); | 4755 assert(caseHandlers.length == joinBlock.predecessors.length); |
4752 if (caseHandlers.length != 0) { | 4756 if (caseHandlers.length != 0) { |
4753 graph.addBlock(joinBlock); | 4757 graph.addBlock(joinBlock); |
4754 open(joinBlock); | 4758 open(joinBlock); |
4755 if (caseHandlers.length == 1) { | 4759 if (caseHandlers.length == 1) { |
4756 localsHandler = caseHandlers[0]; | 4760 localsHandler = caseHandlers[0]; |
4757 } else { | 4761 } else { |
4758 localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock); | 4762 localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock); |
4759 } | 4763 } |
4760 } else { | 4764 } else { |
4761 // The joinblock is not used. | 4765 // The joinblock is not used. |
4762 joinBlock = null; | 4766 joinBlock = null; |
4763 } | 4767 } |
4764 | 4768 |
4765 HSubExpressionBlockInformation expressionInfo = | 4769 HSubExpressionBlockInformation expressionInfo = |
4766 new HSubExpressionBlockInformation(new SubExpression(expressionStart, | 4770 new HSubExpressionBlockInformation(new SubExpression(expressionStart, |
4767 expressionEnd)); | 4771 expressionEnd)); |
4768 expressionStart.setBlockFlow( | 4772 expressionStart.setBlockFlow( |
4769 new HSwitchBlockInformation(expressionInfo, | 4773 new HSwitchBlockInformation(expressionInfo, |
4770 matchExpressions, | 4774 matchExpressions, |
4771 statements, | 4775 statements, |
4772 hasDefault, | |
4773 jumpHandler.target, | 4776 jumpHandler.target, |
4774 jumpHandler.labels()), | 4777 jumpHandler.labels()), |
4775 joinBlock); | 4778 joinBlock); |
4776 | 4779 |
4777 jumpHandler.close(); | 4780 jumpHandler.close(); |
4778 } | 4781 } |
4779 | 4782 |
4780 bool nonPrimitiveTypeOverridesEquals(Constant constant) { | 4783 bool nonPrimitiveTypeOverridesEquals(Constant constant) { |
4781 // Function values override equals. Even static ones, since | 4784 // Function values override equals. Even static ones, since |
4782 // they inherit from [Function]. | 4785 // they inherit from [Function]. |
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5443 new HSubGraphBlockInformation(elseBranch.graph)); | 5446 new HSubGraphBlockInformation(elseBranch.graph)); |
5444 | 5447 |
5445 HBasicBlock conditionStartBlock = conditionBranch.block; | 5448 HBasicBlock conditionStartBlock = conditionBranch.block; |
5446 conditionStartBlock.setBlockFlow(info, joinBlock); | 5449 conditionStartBlock.setBlockFlow(info, joinBlock); |
5447 SubGraph conditionGraph = conditionBranch.graph; | 5450 SubGraph conditionGraph = conditionBranch.graph; |
5448 HIf branch = conditionGraph.end.last; | 5451 HIf branch = conditionGraph.end.last; |
5449 assert(branch is HIf); | 5452 assert(branch is HIf); |
5450 branch.blockInformation = conditionStartBlock.blockFlow; | 5453 branch.blockInformation = conditionStartBlock.blockFlow; |
5451 } | 5454 } |
5452 } | 5455 } |
OLD | NEW |