| 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 =
|
|
|