Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1299)

Unified Diff: pkg/compiler/lib/src/ssa/builder_kernel.dart

Issue 2607783002: Implement do-while in Kernel SSA. (Closed)
Patch Set: . Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/compiler/dart2js/kernel/loops_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/builder_kernel.dart
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 1fc734fbda894d51b84ccc2690c7aa5bc998cf17..4dabdefd8bebe4ce7f2035f5e583f95dcf80f901 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -234,8 +234,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
addParameter(typeParamElement, commonMasks.nonNullType);
// This is a little bit wacky (and n^2) until we make the localsHandler
// take Kernel DartTypes instead of just the AST DartTypes.
- var typeVariableType = clsElement
- .typeVariables
+ var typeVariableType = clsElement.typeVariables
.firstWhere((TypeVariableType i) => i.name == typeParameter.name);
localsHandler.directLocals[
localsHandler.getTypeVariableAsLocal(typeVariableType)] = param;
@@ -783,6 +782,146 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
}
@override
+ visitDoStatement(ir.DoStatement doStatement) {
+ // TODO(efortuna): I think this can be rewritten using
+ // LoopHandler.handleLoop with some tricks about when the "update" happens.
+ LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
+ localsHandler.startLoop(astAdapter.getNode(doStatement));
+ JumpHandler jumpHandler = loopHandler.beginLoopHeader(doStatement);
+ HLoopInformation loopInfo = current.loopInformation;
+ HBasicBlock loopEntryBlock = current;
+ HBasicBlock bodyEntryBlock = current;
+ JumpTarget target =
+ elements.getTargetDefinition(astAdapter.getNode(doStatement));
+ bool hasContinues = target != null && target.isContinueTarget;
+ if (hasContinues) {
+ // Add extra block to hang labels on.
+ // It doesn't currently work if they are on the same block as the
+ // HLoopInfo. The handling of HLabeledBlockInformation will visit a
+ // SubGraph that starts at the same block again, so the HLoopInfo is
+ // either handled twice, or it's handled after the labeled block info,
+ // both of which generate the wrong code.
+ // Using a separate block is just a simple workaround.
+ bodyEntryBlock = openNewBlock();
+ }
+ localsHandler.enterLoopBody(astAdapter.getNode(doStatement));
+ doStatement.body.accept(this);
+
+ // 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;
+ bool isAbortingBody = false;
+ if (current != null) {
+ bodyExitBlock = close(new HGoto());
+ } else {
+ isAbortingBody = true;
+ bodyExitBlock = lastOpenedBlock;
+ }
+
+ SubExpression conditionExpression;
+ bool loopIsDegenerate = isAbortingBody && !hasContinues;
+ if (!loopIsDegenerate) {
+ HBasicBlock conditionBlock = addNewBlock();
+
+ List<LocalsHandler> continueHandlers = <LocalsHandler>[];
+ jumpHandler
+ .forEachContinue((HContinue instruction, LocalsHandler locals) {
+ instruction.block.addSuccessor(conditionBlock);
+ continueHandlers.add(locals);
+ });
+
+ if (!isAbortingBody) {
+ bodyExitBlock.addSuccessor(conditionBlock);
+ }
+
+ if (!continueHandlers.isEmpty) {
+ if (!isAbortingBody) continueHandlers.add(localsHandler);
+ localsHandler =
+ savedLocals.mergeMultiple(continueHandlers, conditionBlock);
+ SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
+ List<LabelDefinition> 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);
+
+ doStatement.condition.accept(this);
+ assert(!isAborted());
+ HInstruction conditionInstruction = popBoolified();
+ HBasicBlock conditionEndBlock = close(
+ new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
+
+ HBasicBlock avoidCriticalEdge = addNewBlock();
+ conditionEndBlock.addSuccessor(avoidCriticalEdge);
+ open(avoidCriticalEdge);
+ close(new HGoto());
+ avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge.
+
+ conditionExpression =
+ new SubExpression(conditionBlock, conditionEndBlock);
+
+ // Avoid a critical edge from the condition to the loop-exit body.
+ HBasicBlock conditionExitBlock = addNewBlock();
+ open(conditionExitBlock);
+ close(new HGoto());
+ conditionEndBlock.addSuccessor(conditionExitBlock);
+
+ loopHandler.endLoop(
+ loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler);
+
+ loopEntryBlock.postProcessLoopHeader();
+ SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock);
+ HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation(
+ HLoopBlockInformation.DO_WHILE_LOOP,
+ null,
+ wrapExpressionGraph(conditionExpression),
+ wrapStatementGraph(bodyGraph),
+ null,
+ loopEntryBlock.loopInformation.target,
+ loopEntryBlock.loopInformation.labels,
+ sourceInformationBuilder.buildLoop(astAdapter.getNode(doStatement)));
+ loopEntryBlock.setBlockFlow(loopBlockInfo, current);
+ loopInfo.loopBlockInformation = loopBlockInfo;
+ } else {
+ // Since the loop has no back edge, we remove the loop information on the
+ // header.
+ loopEntryBlock.loopInformation = null;
+
+ if (jumpHandler.hasAnyBreak()) {
+ // Null branchBlock because the body of the do-while loop always aborts,
+ // so we never get to the condition.
+ loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler);
+
+ // Since the body of the loop has a break, we attach a synthesized label
+ // to the body.
+ SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
+ JumpTarget target =
+ elements.getTargetDefinition(astAdapter.getNode(doStatement));
+ LabelDefinition label = target.addLabel(null, 'loop');
+ label.setBreakTarget();
+ HLabeledBlockInformation info = new HLabeledBlockInformation(
+ new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]);
+ loopEntryBlock.setBlockFlow(info, current);
+ jumpHandler.forEachBreak((HBreak breakInstruction, _) {
+ HBasicBlock block = breakInstruction.block;
+ block.addAtExit(new HBreak.toLabel(label));
+ block.remove(breakInstruction);
+ });
+ }
+ }
+ jumpHandler.close();
+ }
+
+ @override
void visitIfStatement(ir.IfStatement ifStatement) {
handleIf(
visitCondition: () => ifStatement.condition.accept(this),
« no previous file with comments | « no previous file | tests/compiler/dart2js/kernel/loops_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698