Index: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/ssa/codegen.dart (revision 15011) |
+++ sdk/lib/_internal/compiler/implementation/ssa/codegen.dart (working copy) |
@@ -943,18 +943,29 @@ |
} |
break; |
case HLoopBlockInformation.DO_WHILE_LOOP: |
- // If there are phi copies after the condition, we cannot emit |
- // a pretty do/while loop, se we fallback to the generic |
- // emission of a loop. |
- CopyHandler handler = variableNames.getCopyHandler(info.end); |
- if (handler != null && !handler.isEmpty) return false; |
if (info.initializer != null) { |
generateStatements(info.initializer); |
} |
js.Block oldContainer = currentContainer; |
js.Statement body = new js.Block.empty(); |
+ // If there are phi copies in the block that jumps to the |
+ // loop entry, we must emit the condition like this: |
+ // do { |
+ // body; |
+ // if (condition) { |
+ // phi updates; |
+ // continue; |
+ // } else { |
+ // break; |
+ // } |
+ // } while (true); |
+ HBasicBlock avoidEdge = info.end.successors[0]; |
+ js.Statement updateBody = new js.Block.empty(); |
+ currentContainer = updateBody; |
+ assignPhisOfSuccessors(avoidEdge); |
+ bool hasPhiUpdates = !updateBody.statements.isEmpty; |
currentContainer = body; |
- if (!isConditionExpression || info.updates != null) { |
+ if (hasPhiUpdates || !isConditionExpression || info.updates != null) { |
wrapLoopBodyForContinue(info); |
} else { |
visitBodyIgnoreLabels(info); |
@@ -971,9 +982,13 @@ |
use(condition.conditionExpression); |
} |
js.Expression jsCondition = pop(); |
+ if (hasPhiUpdates) { |
+ updateBody.statements.add(new js.Continue(null)); |
+ body.statements.add( |
+ new js.If(jsCondition, updateBody, new js.Break(null))); |
+ } |
+ loop = new js.Do(unwrapStatement(body), jsCondition); |
currentContainer = oldContainer; |
- body = unwrapStatement(body); |
- loop = new js.Do(body, jsCondition); |
break; |
default: |
compiler.internalError( |
@@ -1244,16 +1259,7 @@ |
} |
instruction = instruction.next; |
} |
- if (instruction is HLoopBranch) { |
- HLoopBranch branch = instruction; |
- // If the loop is a do/while loop, the phi updates must happen |
- // after the evaluation of the condition. |
- if (!branch.isDoWhile()) { |
- assignPhisOfSuccessors(node); |
- } |
- } else { |
- assignPhisOfSuccessors(node); |
- } |
+ assignPhisOfSuccessors(node); |
visit(instruction); |
} |
@@ -1870,11 +1876,7 @@ |
HBasicBlock branchBlock = currentBlock; |
handleLoopCondition(node); |
List<HBasicBlock> dominated = currentBlock.dominatedBlocks; |
- if (node.isDoWhile()) { |
- // Now that the condition has been evaluated, we can update the |
- // phis of a do/while loop. |
- assignPhisOfSuccessors(node.block); |
- } else { |
+ if (!node.isDoWhile()) { |
// For a do while loop, the body has already been visited. |
visitBasicBlock(dominated[0]); |
} |