| Index: pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
|
| diff --git a/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
|
| index 14069e87ac0e6a9b3bebc134b43a49bbf0ab14c2..8287bacdb751ff7c54394e5258fdfe5809522c4b 100644
|
| --- a/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
|
| +++ b/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
|
| @@ -7,7 +7,7 @@ library tree_ir.optimization.loop_rewriter;
|
| import 'optimization.dart' show Pass;
|
| import '../tree_ir_nodes.dart';
|
|
|
| -/// Rewrites [WhileTrue] statements into [For] statements.
|
| +/// Rewrites [WhileTrue] statements.
|
| ///
|
| /// Before this phase, loops usually contain a lot of "exit code", that is,
|
| /// code that happens at a point where a [Continue] can no longer be reached,
|
| @@ -50,40 +50,16 @@ import '../tree_ir_nodes.dart';
|
| ///
|
| /// A similar transformation is used when S2 occurs in the 'then' position.
|
| ///
|
| -/// Note that the pattern above needs no iteration since nested ifs have been
|
| -/// collapsed previously in the [StatementRewriter] phase.
|
| -///
|
| +/// Note that the last pattern above needs no iteration since nested ifs
|
| +/// have been collapsed previously in the [StatementRewriter] phase.
|
| ///
|
| -/// PULL INTO UPDATE EXPRESSION:
|
| -///
|
| -/// Assignment expressions before the unique continue to a [whileCondition] are
|
| -/// pulled into the updates for the loop.
|
| -///
|
| -/// L:
|
| -/// for (; condition; updates) {
|
| -/// S [ x = E; continue L ]
|
| -/// }
|
| -/// ==>
|
| -/// L:
|
| -/// for (; condition; updates, x = E) {
|
| -/// S [ continue L ]
|
| -/// }
|
| -///
|
| -/// The decision to only pull in assignments is a heuristic to balance
|
| -/// readability and stack trace usability versus the modest code size
|
| -/// reduction one might get by aggressively moving expressions into the
|
| -/// updates.
|
| +/// [WhileCondition] statements exist only after this phase.
|
| class LoopRewriter extends RecursiveTransformer
|
| implements Pass {
|
| String get passName => 'Loop rewriter';
|
|
|
| Set<Label> usedContinueLabels = new Set<Label>();
|
|
|
| - /// Maps loop labels to a list, if that loop can accept update expressions.
|
| - /// The list will then be populated while traversing the body of that loop.
|
| - /// If a loop is not in the map, update expressions cannot be hoisted there.
|
| - Map<Label, List<Expression>> updateExpressions = <Label, List<Expression>>{};
|
| -
|
| void rewrite(FunctionDefinition root) {
|
| root.body = visitStatement(root.body);
|
| }
|
| @@ -120,29 +96,26 @@ class LoopRewriter extends RecursiveTransformer
|
| }
|
| }
|
|
|
| - // Rewrite while(true) to for(; condition; updates).
|
| + // Rewrite while(true) to while(condition).
|
| Statement loop = node;
|
| if (node.body is If) {
|
| If body = node.body;
|
| - updateExpressions[node.label] = <Expression>[];
|
| body.thenStatement = visitStatement(body.thenStatement);
|
| bool thenHasContinue = usedContinueLabels.remove(node.label);
|
| body.elseStatement = visitStatement(body.elseStatement);
|
| bool elseHasContinue = usedContinueLabels.remove(node.label);
|
| if (thenHasContinue && !elseHasContinue) {
|
| node.label.binding = null; // Prepare to rebind the label.
|
| - loop = new For(
|
| + loop = new WhileCondition(
|
| node.label,
|
| body.condition,
|
| - updateExpressions[node.label],
|
| body.thenStatement,
|
| body.elseStatement);
|
| } else if (!thenHasContinue && elseHasContinue) {
|
| node.label.binding = null;
|
| - loop = new For(
|
| + loop = new WhileCondition(
|
| node.label,
|
| new Not(body.condition),
|
| - updateExpressions[node.label],
|
| body.elseStatement,
|
| body.thenStatement);
|
| }
|
| @@ -160,42 +133,4 @@ class LoopRewriter extends RecursiveTransformer
|
| tail.body = loop;
|
| return head;
|
| }
|
| -
|
| - Statement visitExpressionStatement(ExpressionStatement node) {
|
| - if (updateExpressions.isEmpty) {
|
| - // Avoid allocating a list if there is no loop.
|
| - return super.visitExpressionStatement(node);
|
| - }
|
| - List<ExpressionStatement> statements = <ExpressionStatement>[];
|
| - while (node.next is ExpressionStatement) {
|
| - statements.add(node);
|
| - node = node.next;
|
| - }
|
| - statements.add(node);
|
| - Statement next = visitStatement(node.next);
|
| - if (next is Continue && next.target.useCount == 1) {
|
| - List<Expression> updates = updateExpressions[next.target];
|
| - if (updates != null) {
|
| - // Pull expressions before the continue into the for loop update.
|
| - // As a heuristic, we only pull in assignment expressions.
|
| - // Determine the index of the first assignment to pull in.
|
| - int index = statements.length;
|
| - while (index > 0 && statements[index - 1].expression is Assign) {
|
| - --index;
|
| - }
|
| - for (ExpressionStatement stmt in statements.skip(index)) {
|
| - updates.add(stmt.expression);
|
| - }
|
| - if (index > 0) {
|
| - statements[index - 1].next = next;
|
| - return statements.first;
|
| - } else {
|
| - return next;
|
| - }
|
| - }
|
| - }
|
| - // The expression statements could not be pulled into a loop update.
|
| - node.next = next;
|
| - return statements.first;
|
| - }
|
| }
|
|
|