| Index: pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
|
| diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
|
| index 11416657d4591a4e6e181f91b469c6a9f24bd0a8..6c864be8ee7c1205e3a6a0ae9920635871c07509 100644
|
| --- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
|
| +++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
|
| @@ -368,7 +368,29 @@ class StatementRewriter extends Transformer implements Pass {
|
| isEffectivelyConstant(node.value);
|
| }
|
|
|
| - Statement visitExpressionStatement(ExpressionStatement stmt) {
|
| + Statement visitExpressionStatement(ExpressionStatement inputNode) {
|
| + // Analyze chains of expression statements.
|
| + // To avoid deep recursion, [processExpressionStatement] returns a callback
|
| + // to invoke after its successor node has been processed.
|
| + // These callbacks are stored in a list and invoked in reverse at the end.
|
| + List<Function> stack = [];
|
| + Statement node = inputNode;
|
| + while (node is ExpressionStatement) {
|
| + stack.add(processExpressionStatement(node));
|
| + node = node.next;
|
| + }
|
| + Statement result = visitStatement(node);
|
| + for (Function fun in stack.reversed) {
|
| + result = fun(result);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + /// Attempts to propagate an assignment in an expression statement.
|
| + ///
|
| + /// Returns a callback to be invoked after the sucessor statement has
|
| + /// been processed.
|
| + Function processExpressionStatement(ExpressionStatement stmt) {
|
| Variable leftHand = getLeftHand(stmt.expression);
|
| pushDominatingAssignment(leftHand);
|
| if (isEffectivelyConstantAssignment(stmt.expression) &&
|
| @@ -380,44 +402,50 @@ class StatementRewriter extends Transformer implements Pass {
|
| if (assign.variable.readCount == 1) {
|
| // A single-use constant should always be propagated to its use site.
|
| constantEnvironment[assign.variable] = assign.value;
|
| - Statement next = visitStatement(stmt.next);
|
| - popDominatingAssignment(leftHand);
|
| - if (assign.variable.readCount > 0) {
|
| - // The assignment could not be propagated into the successor, either
|
| - // because it has an unsafe variable use (see [hasUnsafeVariableUse])
|
| - // or because the use is outside the current try block, and we do
|
| - // not currently support constant propagation out of a try block.
|
| - constantEnvironment.remove(assign.variable);
|
| - assign.value = visitExpression(assign.value);
|
| - stmt.next = next;
|
| - return stmt;
|
| - } else {
|
| - --assign.variable.writeCount;
|
| - return next;
|
| - }
|
| + return (Statement next) {
|
| + popDominatingAssignment(leftHand);
|
| + if (assign.variable.readCount > 0) {
|
| + // The assignment could not be propagated into the successor,
|
| + // either because it [hasUnsafeVariableUse] or because the
|
| + // use is outside the current try block, and we do not currently
|
| + // support constant propagation out of a try block.
|
| + constantEnvironment.remove(assign.variable);
|
| + assign.value = visitExpression(assign.value);
|
| + stmt.next = next;
|
| + return stmt;
|
| + } else {
|
| + --assign.variable.writeCount;
|
| + return next;
|
| + }
|
| + };
|
| } else {
|
| // With more than one use, we cannot propagate the constant.
|
| // Visit the following statement without polluting [environment] so
|
| // that any preceding non-constant assignments might still propagate.
|
| - stmt.next = visitStatement(stmt.next);
|
| - popDominatingAssignment(leftHand);
|
| - assign.value = visitExpression(assign.value);
|
| - return stmt;
|
| + return (Statement next) {
|
| + stmt.next = next;
|
| + popDominatingAssignment(leftHand);
|
| + assign.value = visitExpression(assign.value);
|
| + return stmt;
|
| + };
|
| }
|
| - }
|
| - // Try to propagate the expression, and block previous impure expressions
|
| - // until this has propagated.
|
| - environment.add(stmt.expression);
|
| - stmt.next = visitStatement(stmt.next);
|
| - popDominatingAssignment(leftHand);
|
| - if (!environment.isEmpty && environment.last == stmt.expression) {
|
| - // Retain the expression statement.
|
| - environment.removeLast();
|
| - stmt.expression = visitExpression(stmt.expression);
|
| - return stmt;
|
| } else {
|
| - // Expression was propagated into the successor.
|
| - return stmt.next;
|
| + // Try to propagate the expression, and block previous impure expressions
|
| + // until this has propagated.
|
| + environment.add(stmt.expression);
|
| + return (Statement next) {
|
| + stmt.next = next;
|
| + popDominatingAssignment(leftHand);
|
| + if (!environment.isEmpty && environment.last == stmt.expression) {
|
| + // Retain the expression statement.
|
| + environment.removeLast();
|
| + stmt.expression = visitExpression(stmt.expression);
|
| + return stmt;
|
| + } else {
|
| + // Expression was propagated into the successor.
|
| + return stmt.next;
|
| + }
|
| + };
|
| }
|
| }
|
|
|
|
|