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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 23063003: Fix issue 12023 by avoiding a critical edge in the SSA graph with a switch statement. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /** 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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698