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

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()) {
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
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 }
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