Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 14553) |
+++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy) |
@@ -665,6 +665,9 @@ |
} |
void endLoop(HBasicBlock loopEntry) { |
+ // If the loop has an aborting body, we don't update the loop |
+ // phis. |
+ if (loopEntry.predecessors.length == 1) return; |
loopEntry.forEachPhi((HPhi phi) { |
Element element = phi.sourceElement; |
HInstruction postLoopDefinition = directLocals[element]; |
@@ -767,6 +770,7 @@ |
void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); |
void forEachContinue(void action(HContinue instruction, |
LocalsHandler locals)); |
+ bool hasAnyContinue(); |
void close(); |
final TargetElement target; |
List<LabelElement> labels(); |
@@ -791,6 +795,7 @@ |
void forEachBreak(Function ignored) { } |
void forEachContinue(Function ignored) { } |
void close() { } |
+ bool hasAnyContinue() => false; |
List<LabelElement> labels() => const <LabelElement>[]; |
TargetElement get target => null; |
@@ -848,6 +853,13 @@ |
} |
} |
+ bool hasAnyContinue() { |
+ for (JumpHandlerEntry entry in jumps) { |
+ if (entry.isContinue()) return true; |
+ } |
+ return false; |
+ } |
+ |
void close() { |
// The mapping from TargetElement to JumpHandler is no longer needed. |
builder.jumpTargets.remove(target); |
@@ -1793,57 +1805,69 @@ |
open(beginBodyBlock); |
localsHandler.enterLoopBody(loop); |
- hackAroundPossiblyAbortingBody(loop, body); |
+ body(); |
- SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); |
- HBasicBlock bodyBlock = close(new HGoto()); |
+ SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock); |
+ HBasicBlock bodyBlock = current; |
+ if (current != null) close(new HGoto()); |
- // Update. |
- // We create an update block, even when we are in a while loop. There the |
- // update block is the jump-target for continue statements. We could avoid |
- // the creation if there is no continue, but for now we always create it. |
- HBasicBlock updateBlock = addNewBlock(); |
+ SubExpression updateGraph; |
- List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
- jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { |
- instruction.block.addSuccessor(updateBlock); |
- continueLocals.add(locals); |
- }); |
- bodyBlock.addSuccessor(updateBlock); |
- continueLocals.add(localsHandler); |
+ // Check that the loop has at least one back-edge. |
+ if (jumpHandler.hasAnyContinue() || bodyBlock != null) { |
+ // Update. |
+ // We create an update block, even when we are in a while loop. There the |
+ // update block is the jump-target for continue statements. We could avoid |
+ // the creation if there is no continue, but for now we always create it. |
+ HBasicBlock updateBlock = addNewBlock(); |
- open(updateBlock); |
+ List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
+ jumpHandler.forEachContinue((HContinue instruction, |
+ LocalsHandler locals) { |
+ instruction.block.addSuccessor(updateBlock); |
+ continueLocals.add(locals); |
+ }); |
- localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); |
- HLabeledBlockInformation labelInfo; |
- List<LabelElement> labels = jumpHandler.labels(); |
- TargetElement target = elements[loop]; |
- if (!labels.isEmpty) { |
- beginBodyBlock.setBlockFlow( |
- new HLabeledBlockInformation( |
- new HSubGraphBlockInformation(bodyGraph), |
- jumpHandler.labels(), |
- isContinue: true), |
- updateBlock); |
- } else if (target != null && target.isContinueTarget) { |
- beginBodyBlock.setBlockFlow( |
- new HLabeledBlockInformation.implicit( |
- new HSubGraphBlockInformation(bodyGraph), |
- target, |
- isContinue: true), |
- updateBlock); |
- } |
+ if (bodyBlock != null) { |
+ continueLocals.add(localsHandler); |
+ bodyBlock.addSuccessor(updateBlock); |
+ } |
- localsHandler.enterLoopUpdates(loop); |
+ open(updateBlock); |
+ localsHandler = |
+ continueLocals[0].mergeMultiple(continueLocals, updateBlock); |
- update(); |
+ HLabeledBlockInformation labelInfo; |
+ List<LabelElement> labels = jumpHandler.labels(); |
+ TargetElement target = elements[loop]; |
+ if (!labels.isEmpty) { |
+ beginBodyBlock.setBlockFlow( |
+ new HLabeledBlockInformation( |
+ new HSubGraphBlockInformation(bodyGraph), |
+ jumpHandler.labels(), |
+ isContinue: true), |
+ updateBlock); |
+ } else if (target != null && target.isContinueTarget) { |
+ beginBodyBlock.setBlockFlow( |
+ new HLabeledBlockInformation.implicit( |
+ new HSubGraphBlockInformation(bodyGraph), |
+ target, |
+ isContinue: true), |
+ updateBlock); |
+ } |
- HBasicBlock updateEndBlock = close(new HGoto()); |
- // The back-edge completing the cycle. |
- updateEndBlock.addSuccessor(conditionBlock); |
+ localsHandler.enterLoopUpdates(loop); |
+ |
+ update(); |
+ |
+ HBasicBlock updateEndBlock = close(new HGoto()); |
+ // The back-edge completing the cycle. |
+ updateEndBlock.addSuccessor(conditionBlock); |
+ updateGraph = new SubExpression(updateBlock, updateEndBlock); |
+ } |
+ |
conditionBlock.postProcessLoopHeader(); |
- SubExpression updateGraph = new SubExpression(updateBlock, updateEndBlock); |
endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
HLoopBlockInformation info = |