Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 15009) |
+++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy) |
@@ -1800,11 +1800,11 @@ |
// For while loops, initializer and update are null. |
// The condition function must return a boolean result. |
// None of the functions must leave anything on the stack. |
- handleLoop(Node loop, |
- void initialize(), |
- HInstruction condition(), |
- void update(), |
- void body()) { |
+ void handleLoop(Node loop, |
+ void initialize(), |
+ HInstruction condition(), |
+ void update(), |
+ void body()) { |
// Generate: |
// <initializer> |
// loop-entry: |
@@ -1909,23 +1909,82 @@ |
updateGraph = new SubExpression(updateBlock, updateEndBlock); |
} |
- conditionBlock.postProcessLoopHeader(); |
+ if (jumpHandler.hasAnyContinue() || bodyBlock != null) { |
+ endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
+ conditionBlock.postProcessLoopHeader(); |
+ HLoopBlockInformation info = |
+ new HLoopBlockInformation( |
+ HLoopBlockInformation.loopType(loop), |
+ wrapExpressionGraph(initializerGraph), |
+ wrapExpressionGraph(conditionExpression), |
+ wrapStatementGraph(bodyGraph), |
+ wrapExpressionGraph(updateGraph), |
+ conditionBlock.loopInformation.target, |
+ conditionBlock.loopInformation.labels, |
+ sourceFileLocationForBeginToken(loop), |
+ sourceFileLocationForEndToken(loop)); |
- endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
- HLoopBlockInformation info = |
- new HLoopBlockInformation( |
- HLoopBlockInformation.loopType(loop), |
- wrapExpressionGraph(initializerGraph), |
+ startBlock.setBlockFlow(info, current); |
+ loopInfo.loopBlockInformation = info; |
+ } else { |
+ // There is no back edge for the loop, so we turn the code into: |
+ // if (condition) { |
+ // body; |
+ // } else { |
+ // // We always create an empty else block to avoid critical edges. |
+ // } |
+ // |
+ // If there is any break in the body, we attach a synthetic |
+ // label to the if. |
+ HBasicBlock elseBlock = addNewBlock(); |
+ open(elseBlock); |
+ close(new HGoto()); |
+ endLoop(conditionBlock, null, jumpHandler, savedLocals); |
+ |
+ // [endLoop] will not create an exit block if there are no |
+ // breaks. |
+ if (current == null) open(addNewBlock()); |
+ elseBlock.addSuccessor(current); |
+ SubGraph elseGraph = new SubGraph(elseBlock, elseBlock); |
+ // Remove the loop information attached to the header. |
+ conditionBlock.loopInformation = null; |
+ |
+ // Remove the [HLoopBranch] instruction and replace it with |
+ // [HIf]. |
+ HInstruction condition = conditionExitBlock.last.inputs[0]; |
+ conditionExitBlock.addAtExit(new HIf(condition)); |
+ conditionExitBlock.addSuccessor(elseBlock); |
+ conditionExitBlock.remove(conditionExitBlock.last); |
+ HIfBlockInformation info = |
+ new HIfBlockInformation( |
wrapExpressionGraph(conditionExpression), |
wrapStatementGraph(bodyGraph), |
- wrapExpressionGraph(updateGraph), |
- conditionBlock.loopInformation.target, |
- conditionBlock.loopInformation.labels, |
- sourceFileLocationForBeginToken(loop), |
- sourceFileLocationForEndToken(loop)); |
+ wrapStatementGraph(elseGraph)); |
- startBlock.setBlockFlow(info, current); |
- loopInfo.loopBlockInformation = info; |
+ conditionBlock.setBlockFlow(info, current); |
+ conditionBlock.last.blockInformation = conditionBlock.blockFlow; |
+ |
+ // If the body has any break, attach a synthesized label to the |
+ // if block. |
+ if (jumpHandler.hasAnyBreak()) { |
+ TargetElement target = elements[loop]; |
+ LabelElement label = target.addLabel(null, 'loop'); |
+ label.isBreakTarget = true; |
+ SubGraph labelGraph = new SubGraph(conditionBlock, current); |
+ HLabeledBlockInformation labelInfo = new HLabeledBlockInformation( |
+ new HSubGraphBlockInformation(labelGraph), |
+ <LabelElement>[label]); |
+ |
+ conditionBlock.setBlockFlow(labelInfo, current); |
+ |
+ jumpHandler.forEachBreak((HBreak breakInstruction, _) { |
+ HBasicBlock block = breakInstruction.block; |
+ block.addAtExit(new HBreak.toLabel(label)); |
+ block.remove(breakInstruction); |
+ }); |
+ } |
+ } |
+ jumpHandler.close(); |
} |
visitFor(For node) { |
@@ -2054,26 +2113,46 @@ |
new SubExpression(conditionBlock, conditionEndBlock); |
} |
- loopEntryBlock.postProcessLoopHeader(); |
+ endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); |
+ if (!isAbortingBody || hasContinues) { |
+ loopEntryBlock.postProcessLoopHeader(); |
+ SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
+ HLoopBlockInformation loopBlockInfo = |
+ new HLoopBlockInformation( |
+ HLoopBlockInformation.DO_WHILE_LOOP, |
+ null, |
+ wrapExpressionGraph(conditionExpression), |
+ wrapStatementGraph(bodyGraph), |
+ null, |
+ loopEntryBlock.loopInformation.target, |
+ loopEntryBlock.loopInformation.labels, |
+ sourceFileLocationForBeginToken(node), |
+ sourceFileLocationForEndToken(node)); |
+ loopEntryBlock.setBlockFlow(loopBlockInfo, current); |
+ loopInfo.loopBlockInformation = loopBlockInfo; |
+ } else { |
+ // If the loop has no back edge, we remove the loop information |
+ // on the header. |
+ loopEntryBlock.loopInformation = null; |
- endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); |
+ // If the body of the loop has any break, we attach a |
+ // synthesized label to the body. |
+ if (jumpHandler.hasAnyBreak()) { |
+ SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
+ TargetElement target = elements[node]; |
+ LabelElement label = target.addLabel(null, 'loop'); |
+ label.isBreakTarget = true; |
+ HLabeledBlockInformation info = new HLabeledBlockInformation( |
+ new HSubGraphBlockInformation(bodyGraph), <LabelElement>[label]); |
+ loopEntryBlock.setBlockFlow(info, current); |
+ jumpHandler.forEachBreak((HBreak breakInstruction, _) { |
+ HBasicBlock block = breakInstruction.block; |
+ block.addAtExit(new HBreak.toLabel(label)); |
+ block.remove(breakInstruction); |
+ }); |
+ } |
+ } |
jumpHandler.close(); |
- |
- SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
- |
- HLoopBlockInformation loopBlockInfo = |
- new HLoopBlockInformation( |
- HLoopBlockInformation.DO_WHILE_LOOP, |
- null, |
- wrapExpressionGraph(conditionExpression), |
- wrapStatementGraph(bodyGraph), |
- null, |
- loopEntryBlock.loopInformation.target, |
- loopEntryBlock.loopInformation.labels, |
- sourceFileLocationForBeginToken(node), |
- sourceFileLocationForEndToken(node)); |
- loopEntryBlock.setBlockFlow(loopBlockInfo, current); |
- loopInfo.loopBlockInformation = loopBlockInfo; |
} |
visitFunctionExpression(FunctionExpression node) { |