| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 14555)
|
| +++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy)
|
| @@ -771,6 +771,7 @@
|
| void forEachContinue(void action(HContinue instruction,
|
| LocalsHandler locals));
|
| bool hasAnyContinue();
|
| + bool hasAnyBreak();
|
| void close();
|
| final TargetElement target;
|
| List<LabelElement> labels();
|
| @@ -796,6 +797,7 @@
|
| void forEachContinue(Function ignored) { }
|
| void close() { }
|
| bool hasAnyContinue() => false;
|
| + bool hasAnyBreak() => false;
|
|
|
| List<LabelElement> labels() => const <LabelElement>[];
|
| TargetElement get target => null;
|
| @@ -860,6 +862,13 @@
|
| return false;
|
| }
|
|
|
| + bool hasAnyBreak() {
|
| + for (JumpHandlerEntry entry in jumps) {
|
| + if (entry.isBreak()) return true;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| void close() {
|
| // The mapping from TargetElement to JumpHandler is no longer needed.
|
| builder.jumpTargets.remove(target);
|
| @@ -1728,14 +1737,18 @@
|
| HBasicBlock branchBlock,
|
| JumpHandler jumpHandler,
|
| LocalsHandler savedLocals) {
|
| + if (branchBlock == null && !jumpHandler.hasAnyBreak()) return;
|
| +
|
| HBasicBlock loopExitBlock = addNewBlock();
|
| - assert(branchBlock.successors.length == 1);
|
| + assert(branchBlock == null || branchBlock.successors.length == 1);
|
| List<LocalsHandler> breakLocals = <LocalsHandler>[];
|
| jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
|
| breakInstruction.block.addSuccessor(loopExitBlock);
|
| breakLocals.add(locals);
|
| });
|
| - branchBlock.addSuccessor(loopExitBlock);
|
| + if (branchBlock != null) {
|
| + branchBlock.addSuccessor(loopExitBlock);
|
| + }
|
| open(loopExitBlock);
|
| localsHandler.endLoop(loopEntry);
|
| if (!breakLocals.isEmpty) {
|
| @@ -1953,51 +1966,71 @@
|
| bodyEntryBlock = openNewBlock();
|
| }
|
| localsHandler.enterLoopBody(node);
|
| - hackAroundPossiblyAbortingBody(node, () { visit(node.body); });
|
| + visit(node.body);
|
|
|
| // If there are no continues we could avoid the creation of the condition
|
| // block. This could also lead to a block having multiple entries and exits.
|
| - HBasicBlock bodyExitBlock = close(new HGoto());
|
| - HBasicBlock conditionBlock = addNewBlock();
|
| + HBasicBlock bodyExitBlock;
|
| + bool isAbortingBody = false;
|
| + if (current != null) {
|
| + bodyExitBlock = close(new HGoto());
|
| + } else {
|
| + isAbortingBody = true;
|
| + bodyExitBlock = lastOpenedBlock;
|
| + }
|
|
|
| - List<LocalsHandler> continueLocals = <LocalsHandler>[];
|
| - jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) {
|
| - instruction.block.addSuccessor(conditionBlock);
|
| - continueLocals.add(locals);
|
| - });
|
| - bodyExitBlock.addSuccessor(conditionBlock);
|
| - if (!continueLocals.isEmpty) {
|
| - continueLocals.add(localsHandler);
|
| - localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock);
|
| - SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
|
| - List<LabelElement> labels = jumpHandler.labels();
|
| - HSubGraphBlockInformation bodyInfo =
|
| - new HSubGraphBlockInformation(bodyGraph);
|
| - HLabeledBlockInformation info;
|
| - if (!labels.isEmpty) {
|
| - info = new HLabeledBlockInformation(bodyInfo, labels, isContinue: true);
|
| - } else {
|
| - info = new HLabeledBlockInformation.implicit(bodyInfo, target,
|
| - isContinue: true);
|
| + SubExpression conditionExpression;
|
| + HBasicBlock conditionEndBlock;
|
| + if (!isAbortingBody || hasContinues) {
|
| + HBasicBlock conditionBlock = addNewBlock();
|
| +
|
| + List<LocalsHandler> continueLocals = <LocalsHandler>[];
|
| + jumpHandler.forEachContinue((HContinue instruction,
|
| + LocalsHandler locals) {
|
| + instruction.block.addSuccessor(conditionBlock);
|
| + continueLocals.add(locals);
|
| + });
|
| +
|
| + if (!isAbortingBody) {
|
| + bodyExitBlock.addSuccessor(conditionBlock);
|
| }
|
| - bodyEntryBlock.setBlockFlow(info, conditionBlock);
|
| +
|
| + if (!continueLocals.isEmpty) {
|
| + if (!isAbortingBody) continueLocals.add(localsHandler);
|
| + localsHandler =
|
| + savedLocals.mergeMultiple(continueLocals, conditionBlock);
|
| + SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
|
| + List<LabelElement> labels = jumpHandler.labels();
|
| + HSubGraphBlockInformation bodyInfo =
|
| + new HSubGraphBlockInformation(bodyGraph);
|
| + HLabeledBlockInformation info;
|
| + if (!labels.isEmpty) {
|
| + info = new HLabeledBlockInformation(bodyInfo, labels,
|
| + isContinue: true);
|
| + } else {
|
| + info = new HLabeledBlockInformation.implicit(bodyInfo, target,
|
| + isContinue: true);
|
| + }
|
| + bodyEntryBlock.setBlockFlow(info, conditionBlock);
|
| + }
|
| + open(conditionBlock);
|
| +
|
| + visit(node.condition);
|
| + assert(!isAborted());
|
| + HInstruction conditionInstruction = popBoolified();
|
| + conditionEndBlock = close(
|
| + new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
|
| +
|
| + conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge.
|
| + conditionExpression =
|
| + new SubExpression(conditionBlock, conditionEndBlock);
|
| }
|
| - open(conditionBlock);
|
|
|
| - visit(node.condition);
|
| - assert(!isAborted());
|
| - HInstruction conditionInstruction = popBoolified();
|
| - HBasicBlock conditionEndBlock =
|
| - close(new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
|
| -
|
| - conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge.
|
| loopEntryBlock.postProcessLoopHeader();
|
|
|
| endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler);
|
| jumpHandler.close();
|
|
|
| - SubExpression conditionExpression =
|
| - new SubExpression(conditionBlock, conditionEndBlock);
|
| SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
|
|
|
| HLoopBlockInformation loopBlockInfo =
|
|
|