| Index: sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart | 
| diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart | 
| index b17cbd272de773800038ceece4948489c460400a..74142fa3da9bd549cfd2abdf526c72bcd0c43cec 100644 | 
| --- a/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart | 
| +++ b/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart | 
| @@ -26,6 +26,9 @@ import '../ir/const_expression.dart'; | 
| // | 
| // In contrast to the CPS-based IR, non-primitive expressions can be named and | 
| // arguments (to calls, primitives, and blocks) can be arbitrary expressions. | 
| +// | 
| +// Additionally, variables are considered in scope within inner functions; | 
| +// closure variables are thus handled directly instead of using ref cells. | 
|  | 
| /** | 
| * The base class of all Tree nodes. | 
| @@ -82,13 +85,24 @@ class Label { | 
| * Variables are [Expression]s. | 
| */ | 
| class Variable extends Expression { | 
| +  /// Function that declares this variable. | 
| +  FunctionDefinition host; | 
| + | 
| /// Element used for synthesizing a name for the variable. | 
| /// Different variables may have the same element. May be null. | 
| Element element; | 
|  | 
| int readCount = 0; | 
|  | 
| -  Variable(this.element); | 
| +  /// Number of places where this variable occurs as: | 
| +  /// - left-hand of an [Assign] | 
| +  /// - left-hand of a [FunctionDeclaration] | 
| +  /// - parameter in a [FunctionDefinition] | 
| +  int writeCount = 0; | 
| + | 
| +  Variable(this.host, this.element) { | 
| +    assert(host != null); | 
| +  } | 
|  | 
| accept(ExpressionVisitor visitor) => visitor.visitVariable(this); | 
| } | 
| @@ -140,7 +154,7 @@ class InvokeSuperMethod extends Expression implements Invoke { | 
|  | 
| InvokeSuperMethod(this.selector, this.arguments) ; | 
|  | 
| -  accept(Visitor visitor) => visitor.visitInvokeSuperMethod(this); | 
| +  accept(ExpressionVisitor visitor) => visitor.visitInvokeSuperMethod(this); | 
| } | 
|  | 
| /** | 
| @@ -192,9 +206,9 @@ class This extends Expression { | 
| } | 
|  | 
| class ReifyTypeVar extends Expression { | 
| -  TypeVariableElement element; | 
| +  TypeVariableElement typeVariable; | 
|  | 
| -  ReifyTypeVar(this.element); | 
| +  ReifyTypeVar(this.typeVariable); | 
|  | 
| accept(ExpressionVisitor visitor) => visitor.visitReifyTypeVar(this); | 
| } | 
| @@ -264,6 +278,33 @@ class Not extends Expression { | 
| accept(ExpressionVisitor visitor) => visitor.visitNot(this); | 
| } | 
|  | 
| +class FunctionExpression extends Expression { | 
| +  final FunctionDefinition definition; | 
| + | 
| +  FunctionExpression(this.definition) { | 
| +    assert(definition.element.functionSignature.type.returnType.treatAsDynamic); | 
| +  } | 
| + | 
| +  accept(ExpressionVisitor visitor) => visitor.visitFunctionExpression(this); | 
| +} | 
| + | 
| +/// Declares a local function. | 
| +/// Used for functions that may not occur in expression context due to | 
| +/// being recursive or having a return type. | 
| +/// The [variable] must not occur as the left-hand side of an [Assign] or | 
| +/// any other [FunctionDeclaration]. | 
| +class FunctionDeclaration extends Statement { | 
| +  Variable variable; | 
| +  final FunctionDefinition definition; | 
| +  Statement next; | 
| + | 
| +  FunctionDeclaration(this.variable, this.definition, this.next) { | 
| +    ++variable.writeCount; | 
| +  } | 
| + | 
| +  accept(StatementVisitor visitor) => visitor.visitFunctionDeclaration(this); | 
| +} | 
| + | 
| /// A [LabeledStatement] or [WhileTrue] or [WhileCondition]. | 
| abstract class JumpTarget extends Statement { | 
| Label get label; | 
| @@ -289,9 +330,6 @@ class LabeledStatement extends JumpTarget { | 
|  | 
| /// A [WhileTrue] or [WhileCondition] loop. | 
| abstract class Loop extends JumpTarget { | 
| -  /// When a [Continue] to a loop is executed, all update expressions are | 
| -  /// evaluated right-to-left before control resumes at the head of the loop. | 
| -  List<Expression> get updates; | 
| } | 
|  | 
| /** | 
| @@ -300,7 +338,6 @@ abstract class Loop extends JumpTarget { | 
| class WhileTrue extends Loop { | 
| final Label label; | 
| Statement body; | 
| -  final List<Expression> updates = <Expression>[]; | 
|  | 
| WhileTrue(this.label, this.body) { | 
| assert(label.binding == null); | 
| @@ -328,10 +365,9 @@ class WhileCondition extends Loop { | 
| Expression condition; | 
| Statement body; | 
| Statement next; | 
| -  final List<Expression> updates; | 
|  | 
| WhileCondition(this.label, this.condition, this.body, | 
| -                 this.next, this.updates) { | 
| +                 this.next) { | 
| assert(label.binding == null); | 
| label.binding = this; | 
| } | 
| @@ -389,7 +425,15 @@ class Assign extends Statement { | 
| final Variable variable; | 
| Expression definition; | 
|  | 
| -  Assign(this.variable, this.definition, this.next); | 
| +  /// If true, this declares a new copy of the closure variable. | 
| +  /// The consequences are similar to [ir.SetClosureVariable]. | 
| +  /// All uses of the variable must be nested inside the [next] statement. | 
| +  bool isDeclaration; | 
| + | 
| +  Assign(this.variable, this.definition, this.next, | 
| +         { this.isDeclaration: false }) { | 
| +    variable.writeCount++; | 
| +  } | 
|  | 
| bool get hasExactlyOneUse => variable.readCount == 1; | 
|  | 
| @@ -440,11 +484,13 @@ class ExpressionStatement extends Statement { | 
| } | 
|  | 
| class FunctionDefinition extends Node { | 
| +  final FunctionElement element; | 
| final List<Variable> parameters; | 
| Statement body; | 
| final List<ConstDeclaration> localConstants; | 
|  | 
| -  FunctionDefinition(this.parameters, this.body, this.localConstants); | 
| +  FunctionDefinition(this.element, this.parameters, this.body, | 
| +      this.localConstants); | 
| } | 
|  | 
| abstract class ExpressionVisitor<E> { | 
| @@ -464,6 +510,7 @@ abstract class ExpressionVisitor<E> { | 
| E visitLiteralList(LiteralList node); | 
| E visitLiteralMap(LiteralMap node); | 
| E visitTypeOperator(TypeOperator node); | 
| +  E visitFunctionExpression(FunctionExpression node); | 
| } | 
|  | 
| abstract class StatementVisitor<S> { | 
| @@ -476,6 +523,7 @@ abstract class StatementVisitor<S> { | 
| S visitIf(If node); | 
| S visitWhileTrue(WhileTrue node); | 
| S visitWhileCondition(WhileCondition node); | 
| +  S visitFunctionDeclaration(FunctionDeclaration node); | 
| S visitExpressionStatement(ExpressionStatement node); | 
| } | 
|  | 
| @@ -485,6 +533,120 @@ abstract class Visitor<S,E> implements ExpressionVisitor<E>, | 
| S visitStatement(Statement s) => s.accept(this); | 
| } | 
|  | 
| +class RecursiveVisitor extends Visitor { | 
| +  visitFunctionDefinition(FunctionDefinition node) { | 
| +    visitStatement(node.body); | 
| +  } | 
| + | 
| +  visitVariable(Variable node) {} | 
| + | 
| +  visitInvokeStatic(InvokeStatic node) { | 
| +    node.arguments.forEach(visitExpression); | 
| +  } | 
| + | 
| +  visitInvokeMethod(InvokeMethod node) { | 
| +    visitExpression(node.receiver); | 
| +    node.arguments.forEach(visitExpression); | 
| +  } | 
| + | 
| +  visitInvokeSuperMethod(InvokeSuperMethod node) { | 
| +    node.arguments.forEach(visitExpression); | 
| +  } | 
| + | 
| +  visitInvokeConstructor(InvokeConstructor node) { | 
| +    node.arguments.forEach(visitExpression); | 
| +  } | 
| + | 
| +  visitConcatenateStrings(ConcatenateStrings node) { | 
| +    node.arguments.forEach(visitExpression); | 
| +  } | 
| + | 
| +  visitConstant(Constant node) {} | 
| + | 
| +  visitThis(This node) {} | 
| + | 
| +  visitReifyTypeVar(ReifyTypeVar node) {} | 
| + | 
| +  visitConditional(Conditional node) { | 
| +    visitExpression(node.condition); | 
| +    visitExpression(node.thenExpression); | 
| +    visitExpression(node.elseExpression); | 
| +  } | 
| + | 
| +  visitLogicalOperator(LogicalOperator node) { | 
| +    visitExpression(node.left); | 
| +    visitExpression(node.right); | 
| +  } | 
| + | 
| +  visitNot(Not node) { | 
| +    visitExpression(node.operand); | 
| +  } | 
| + | 
| +  visitLiteralList(LiteralList node) { | 
| +    node.values.forEach(visitExpression); | 
| +  } | 
| + | 
| +  visitLiteralMap(LiteralMap node) { | 
| +    for (int i=0; i<node.keys.length; i++) { | 
| +      visitExpression(node.keys[i]); | 
| +      visitExpression(node.values[i]); | 
| +    } | 
| +  } | 
| + | 
| +  visitTypeOperator(TypeOperator node) { | 
| +    visitExpression(node.receiver); | 
| +  } | 
| + | 
| +  visitFunctionExpression(FunctionExpression node) { | 
| +    visitFunctionDefinition(node.definition); | 
| +  } | 
| + | 
| +  visitLabeledStatement(LabeledStatement node) { | 
| +    visitStatement(node.body); | 
| +    visitStatement(node.next); | 
| +  } | 
| + | 
| +  visitAssign(Assign node) { | 
| +    visitExpression(node.definition); | 
| +    visitVariable(node.variable); | 
| +    visitStatement(node.next); | 
| +  } | 
| + | 
| +  visitReturn(Return node) { | 
| +    visitExpression(node.value); | 
| +  } | 
| + | 
| +  visitBreak(Break node) {} | 
| + | 
| +  visitContinue(Continue node) {} | 
| + | 
| +  visitIf(If node) { | 
| +    visitExpression(node.condition); | 
| +    visitStatement(node.thenStatement); | 
| +    visitStatement(node.elseStatement); | 
| +  } | 
| + | 
| +  visitWhileTrue(WhileTrue node) { | 
| +    visitStatement(node.body); | 
| +  } | 
| + | 
| +  visitWhileCondition(WhileCondition node) { | 
| +    visitExpression(node.condition); | 
| +    visitStatement(node.body); | 
| +    visitStatement(node.next); | 
| +  } | 
| + | 
| +  visitFunctionDeclaration(FunctionDeclaration node) { | 
| +    visitFunctionDefinition(node.definition); | 
| +    visitStatement(node.next); | 
| +  } | 
| + | 
| +  visitExpressionStatement(ExpressionStatement node) { | 
| +    visitExpression(node.expression); | 
| +    visitStatement(node.next); | 
| +  } | 
| +} | 
| + | 
| /** | 
| * Builder translates from CPS-based IR to direct-style Tree. | 
| * | 
| @@ -524,6 +686,10 @@ class Builder extends ir.Visitor<Node> { | 
| final Map<Element, List<Variable>> element2variables = | 
| <Element,List<Variable>>{}; | 
|  | 
| +  /// Like [element2variables], except for closure variables. Closure variables | 
| +  /// are not subject to SSA, so at most one variable is used per element. | 
| +  final Map<Element, Variable> element2closure = <Element, Variable>{}; | 
| + | 
| // Continuations with more than one use are replaced with Tree labels.  This | 
| // is the mapping from continuations to labels. | 
| final Map<ir.Continuation, Label> labels = <ir.Continuation, Label>{}; | 
| @@ -531,11 +697,29 @@ class Builder extends ir.Visitor<Node> { | 
| FunctionDefinition function; | 
| ir.Continuation returnContinuation; | 
|  | 
| +  Builder parent; | 
| + | 
| +  Builder(this.compiler); | 
| + | 
| +  Builder.inner(Builder parent) | 
| +      : this.parent = parent, | 
| +        compiler = parent.compiler; | 
| + | 
| /// Variable used in [buildPhiAssignments] as a temporary when swapping | 
| /// variables. | 
| -  final Variable tempVar = new Variable(null); | 
| +  Variable phiTempVar; | 
|  | 
| -  Builder(this.compiler); | 
| +  Variable getClosureVariable(Element element) { | 
| +    if (element.enclosingElement != function.element) { | 
| +      return parent.getClosureVariable(element); | 
| +    } | 
| +    Variable variable = element2closure[element]; | 
| +    if (variable == null) { | 
| +      variable = new Variable(function, element); | 
| +      element2closure[element] = variable; | 
| +    } | 
| +    return variable; | 
| +  } | 
|  | 
| /// Obtains the variable representing the given primitive. Returns null for | 
| /// primitives that have no reference and do not need a variable. | 
| @@ -543,13 +727,13 @@ class Builder extends ir.Visitor<Node> { | 
| if (primitive.registerIndex == null) { | 
| return null; // variable is unused | 
| } | 
| -    List<Variable> variables = element2variables[primitive.element]; | 
| +    List<Variable> variables = element2variables[primitive.hint]; | 
| if (variables == null) { | 
| variables = <Variable>[]; | 
| -      element2variables[primitive.element] = variables; | 
| +      element2variables[primitive.hint] = variables; | 
| } | 
| while (variables.length <= primitive.registerIndex) { | 
| -      variables.add(new Variable(primitive.element)); | 
| +      variables.add(new Variable(function, primitive.hint)); | 
| } | 
| return variables[primitive.registerIndex]; | 
| } | 
| @@ -652,9 +836,9 @@ class Builder extends ir.Visitor<Node> { | 
| // Cycle found; store argument in a temporary variable. | 
| // The temporary will then be used as right-hand side when the | 
| // assignment gets added. | 
| -        if (assignmentSrc[i] != tempVar) { // Only move to temporary once. | 
| -          assignmentSrc[i] = tempVar; | 
| -          addAssignment(tempVar, arg); | 
| +        if (assignmentSrc[i] != phiTempVar) { // Only move to temporary once. | 
| +          assignmentSrc[i] = phiTempVar; | 
| +          addAssignment(phiTempVar, arg); | 
| } | 
| return; | 
| } | 
| @@ -683,24 +867,40 @@ class Builder extends ir.Visitor<Node> { | 
| return first; | 
| } | 
|  | 
| +  visitNode(ir.Node node) => throw "Unhandled node: $node"; | 
| + | 
| Expression visitFunctionDefinition(ir.FunctionDefinition node) { | 
| -    returnContinuation = node.returnContinuation; | 
| List<Variable> parameters = <Variable>[]; | 
| +    function = new FunctionDefinition(node.element, parameters, | 
| +        null, node.localConstants); | 
| +    returnContinuation = node.returnContinuation; | 
| for (ir.Parameter p in node.parameters) { | 
| Variable parameter = getVariable(p); | 
| assert(parameter != null); | 
| +      ++parameter.writeCount; // Being a parameter counts as a write. | 
| parameters.add(parameter); | 
| } | 
| -    function = new FunctionDefinition(parameters, visit(node.body), | 
| -        node.localConstants); | 
| +    phiTempVar = new Variable(function, null); | 
| +    function.body = visit(node.body); | 
| return null; | 
| } | 
|  | 
| Statement visitLetPrim(ir.LetPrim node) { | 
| Variable variable = getVariable(node.primitive); | 
| -    return variable == null | 
| -        ? visit(node.body) | 
| -        : new Assign(variable, visit(node.primitive), visit(node.body)); | 
| + | 
| +    // Don't translate unused primitives. | 
| +    if (variable == null) return visit(node.body); | 
| + | 
| +    Node definition = visit(node.primitive); | 
| + | 
| +    // visitPrimitive returns a Statement without successor if it cannot occur | 
| +    // in expression context (currently only the case for FunctionDeclarations). | 
| +    if (definition is Statement) { | 
| +      definition.next = visit(node.body); | 
| +      return definition; | 
| +    } else { | 
| +      return new Assign(variable, definition, visit(node.body)); | 
| +    } | 
| } | 
|  | 
| Statement visitLetCont(ir.LetCont node) { | 
| @@ -726,87 +926,69 @@ class Builder extends ir.Visitor<Node> { | 
| // Calls are translated to direct style. | 
| List<Expression> arguments = translateArguments(node.arguments); | 
| Expression invoke = new InvokeStatic(node.target, node.selector, arguments); | 
| -    ir.Continuation cont = node.continuation.definition; | 
| -    if (cont == returnContinuation) { | 
| -      return new Return(invoke); | 
| -    } else { | 
| -      assert(cont.hasExactlyOneUse); | 
| -      assert(cont.parameters.length == 1); | 
| -      return buildContinuationAssignment(cont.parameters.single, invoke, | 
| -          () => visit(cont.body)); | 
| -    } | 
| +    return continueWithExpression(node.continuation, invoke); | 
| } | 
|  | 
| Statement visitInvokeMethod(ir.InvokeMethod node) { | 
| Expression receiver = getVariableReference(node.receiver); | 
| List<Expression> arguments = translateArguments(node.arguments); | 
| Expression invoke = new InvokeMethod(receiver, node.selector, arguments); | 
| -    ir.Continuation cont = node.continuation.definition; | 
| -    if (cont == returnContinuation) { | 
| -      return new Return(invoke); | 
| -    } else { | 
| -      assert(cont.hasExactlyOneUse); | 
| -      assert(cont.parameters.length == 1); | 
| -      return buildContinuationAssignment(cont.parameters.single, invoke, | 
| -          () => visit(cont.body)); | 
| -    } | 
| +    return continueWithExpression(node.continuation, invoke); | 
| } | 
|  | 
| Statement visitInvokeSuperMethod(ir.InvokeSuperMethod node) { | 
| List<Expression> arguments = translateArguments(node.arguments); | 
| Expression invoke = new InvokeSuperMethod(node.selector, arguments); | 
| -    ir.Continuation cont = node.continuation.definition; | 
| -    if (cont == returnContinuation) { | 
| -      return new Return(invoke); | 
| -    } else { | 
| -      assert(cont.hasExactlyOneUse); | 
| -      assert(cont.parameters.length == 1); | 
| -      return buildContinuationAssignment(cont.parameters.single, invoke, | 
| -          () => visit(cont.body)); | 
| -    } | 
| +    return continueWithExpression(node.continuation, invoke); | 
| } | 
|  | 
| Statement visitConcatenateStrings(ir.ConcatenateStrings node) { | 
| List<Expression> arguments = translateArguments(node.arguments); | 
| Expression concat = new ConcatenateStrings(arguments); | 
| -    ir.Continuation cont = node.continuation.definition; | 
| +    return continueWithExpression(node.continuation, concat); | 
| +  } | 
| + | 
| +  Statement continueWithExpression(ir.Reference continuation, | 
| +                                   Expression expression) { | 
| +    ir.Continuation cont = continuation.definition; | 
| if (cont == returnContinuation) { | 
| -      return new Return(concat); | 
| +      return new Return(expression); | 
| } else { | 
| assert(cont.hasExactlyOneUse); | 
| assert(cont.parameters.length == 1); | 
| -      return buildContinuationAssignment(cont.parameters.single, concat, | 
| +      return buildContinuationAssignment(cont.parameters.single, expression, | 
| () => visit(cont.body)); | 
| } | 
| } | 
|  | 
| +  Expression visitGetClosureVariable(ir.GetClosureVariable node) { | 
| +    return getClosureVariable(node.variable); | 
| +  } | 
| + | 
| +  Statement visitSetClosureVariable(ir.SetClosureVariable node) { | 
| +    Variable variable = getClosureVariable(node.variable); | 
| +    Expression value = getVariableReference(node.value); | 
| +    return new Assign(variable, value, visit(node.body), | 
| +                      isDeclaration: node.isDeclaration); | 
| +  } | 
| + | 
| +  Statement visitDeclareFunction(ir.DeclareFunction node) { | 
| +    Variable variable = getClosureVariable(node.variable); | 
| +    FunctionDefinition function = makeSubFunction(node.definition); | 
| +    return new FunctionDeclaration(variable, function, visit(node.body)); | 
| +  } | 
| + | 
| Statement visitAsCast(ir.AsCast node) { | 
| Expression receiver = getVariableReference(node.receiver); | 
| Expression concat = new TypeOperator(receiver, node.type, "as"); | 
| -    ir.Continuation cont = node.continuation.definition; | 
| -    if (cont == returnContinuation) { | 
| -      return new Return(concat); | 
| -    } else { | 
| -      assert(cont.hasExactlyOneUse); | 
| -      assert(cont.parameters.length == 1); | 
| -      return buildContinuationAssignment(cont.parameters.single, concat, | 
| -          () => visit(cont.body)); | 
| -    } | 
| +    return continueWithExpression(node.continuation, concat); | 
| } | 
|  | 
| Statement visitInvokeConstructor(ir.InvokeConstructor node) { | 
| List<Expression> arguments = translateArguments(node.arguments); | 
| Expression invoke = | 
| new InvokeConstructor(node.type, node.target, node.selector, arguments); | 
| -    ir.Continuation cont = node.continuation.definition; | 
| -    if (cont == returnContinuation) { | 
| -      return new Return(invoke); | 
| -    } else { | 
| -      assert(cont.hasExactlyOneUse); | 
| -      assert(cont.parameters.length == 1); | 
| -      return buildContinuationAssignment(cont.parameters.single, invoke, | 
| -          () => visit(cont.body)); | 
| -    } | 
| +    return continueWithExpression(node.continuation, invoke); | 
| } | 
|  | 
| Statement visitInvokeContinuation(ir.InvokeContinuation node) { | 
| @@ -870,7 +1052,7 @@ class Builder extends ir.Visitor<Node> { | 
| } | 
|  | 
| Expression visitReifyTypeVar(ir.ReifyTypeVar node) { | 
| -    return new ReifyTypeVar(node.element); | 
| +    return new ReifyTypeVar(node.typeVariable); | 
| } | 
|  | 
| Expression visitLiteralList(ir.LiteralList node) { | 
| @@ -886,6 +1068,23 @@ class Builder extends ir.Visitor<Node> { | 
| translateArguments(node.values)); | 
| } | 
|  | 
| +  FunctionDefinition makeSubFunction(ir.FunctionDefinition function) { | 
| +    return new Builder.inner(this).build(function); | 
| +  } | 
| + | 
| +  Node visitCreateFunction(ir.CreateFunction node) { | 
| +    FunctionDefinition def = makeSubFunction(node.definition); | 
| +    FunctionSignature signature = node.definition.element.functionSignature; | 
| +    bool hasReturnType = !signature.type.returnType.treatAsDynamic; | 
| +    if (hasReturnType) { | 
| +      // This function cannot occur in expression context. | 
| +      // The successor will be filled in by visitLetPrim. | 
| +      return new FunctionDeclaration(getVariable(node), def, null); | 
| +    } else { | 
| +      return new FunctionExpression(def); | 
| +    } | 
| +  } | 
| + | 
| Expression visitIsCheck(ir.IsCheck node) { | 
| return new TypeOperator(getVariableReference(node.receiver), | 
| node.type, | 
| @@ -911,6 +1110,85 @@ class Builder extends ir.Visitor<Node> { | 
| } | 
| } | 
|  | 
| +/// Eliminates redundant variables and assignments that occur immediately after | 
| +/// parameters are declared or after a function declaration. | 
| +/// | 
| +/// These patterns arise when translating out of CPS where closure variables | 
| +/// live in a separate space. Since function parameters are IR primitives they | 
| +/// must be moved into a separate closure variable for inner functions to access | 
| +/// them. For example: | 
| +/// | 
| +///   foo(x) { | 
| +///     let v1 = ref x in BODY | 
| +///   } | 
| +///    ==> (dart_tree Builder) | 
| +///   foo(x) { | 
| +///     var v1 = x; | 
| +///     BODY.. | 
| +///   } | 
| +/// | 
| +/// This phase attempts to merge v1 and x in the example above. | 
| +/// A similar pattern can occur for local function declarations that are used | 
| +/// from closures. | 
| +class CopyPropagateClosureVariables extends RecursiveVisitor { | 
| + | 
| +  void rewrite(FunctionDefinition definition) { | 
| +    visitFunctionDefinition(definition); | 
| +  } | 
| + | 
| +  /// Performs the rewrite: | 
| +  /// | 
| +  ///   foo(x) { var v0 = x; S } | 
| +  ///     ==> (move v0 into parameter) | 
| +  ///   foo(v0) { S } | 
| +  ///     ==> (change the name of v0 to be x, so we preserve the parameter name) | 
| +  ///   foo(x) { S[v0\x] } | 
| +  /// | 
| +  ///   Condition: x cannot be used anywhere else. | 
| +  visitFunctionDefinition(FunctionDefinition definition) { | 
| +    while (definition.body is Assign) { | 
| +      Assign assign = definition.body; | 
| +      if (assign.definition is! Variable) break; | 
| + | 
| +      Variable rightHand = assign.definition; | 
| +      if (rightHand.readCount != 1) break; | 
| + | 
| +      int paramIndex = definition.parameters.indexOf(rightHand); | 
| +      if (paramIndex == -1) break; | 
| + | 
| +      // A variable may not occur as a parameter more than once. | 
| +      if (definition.parameters.contains(assign.variable)) break; | 
| + | 
| +      definition.parameters[paramIndex] = assign.variable; | 
| +      assign.variable.element = rightHand.element; | 
| +      definition.body = assign.next; | 
| +    } | 
| + | 
| +    visitStatement(definition.body); // Visit nested function definitions. | 
| +  } | 
| + | 
| +  /// Performs the rewrite: | 
| +  /// | 
| +  ///   int v0() { S } | 
| +  ///   foo = v0; | 
| +  ///     ==> | 
| +  ///   int foo() { S } | 
| +  /// | 
| +  ///   Condition: v0 cannot be used anywhere else. | 
| +  visitFunctionDeclaration(FunctionDeclaration node) { | 
| +    Statement next = node.next; | 
| +    if (next is Assign && | 
| +        next.definition == node.variable && | 
| +        node.variable.readCount == 1 && | 
| +        next.variable.writeCount == 1) { | 
| +      node.variable = next.variable; | 
| +      node.next = next.next; | 
| +    } | 
| +    super.visitFunctionDeclaration(node); | 
| +  } | 
| + | 
| +} | 
| + | 
| /** | 
| * Performs the following transformations on the tree: | 
| * - Assignment propagation | 
| @@ -1123,6 +1401,17 @@ class StatementRewriter extends Visitor<Statement, Expression> { | 
| return node; | 
| } | 
|  | 
| +  Expression visitFunctionExpression(FunctionExpression node) { | 
| +    new StatementRewriter().rewrite(node.definition); | 
| +    return node; | 
| +  } | 
| + | 
| +  Statement visitFunctionDeclaration(FunctionDeclaration node) { | 
| +    new StatementRewriter().rewrite(node.definition); | 
| +    node.next = visitStatement(node.next); | 
| +    return node; | 
| +  } | 
| + | 
| Statement visitReturn(Return node) { | 
| node.value = visitExpression(node.value); | 
| return node; | 
| @@ -1303,6 +1592,7 @@ class StatementRewriter extends Visitor<Statement, Expression> { | 
| if (s is Assign && t is Assign && s.variable == t.variable) { | 
| Statement next = combineStatements(s.next, t.next); | 
| if (next != null) { | 
| +        --t.variable.writeCount; // Two assignments become one. | 
| return new Assign(s.variable, | 
| combine(s.definition, t.definition), | 
| next); | 
| @@ -1466,7 +1756,7 @@ class StatementRewriter extends Visitor<Statement, Expression> { | 
| /// | 
| /// Note that the above pattern needs no iteration since nested ifs | 
| /// have been collapsed previously in the [StatementRewriter] phase. | 
| -class LoopRewriter extends StatementVisitor<Statement> { | 
| +class LoopRewriter extends RecursiveVisitor { | 
|  | 
| Set<Label> usedContinueLabels = new Set<Label>(); | 
|  | 
| @@ -1481,11 +1771,13 @@ class LoopRewriter extends StatementVisitor<Statement> { | 
| } | 
|  | 
| Statement visitAssign(Assign node) { | 
| +    visitExpression(node.definition); | 
| node.next = visitStatement(node.next); | 
| return node; | 
| } | 
|  | 
| Statement visitReturn(Return node) { | 
| +    visitExpression(node.value); | 
| return node; | 
| } | 
|  | 
| @@ -1499,6 +1791,7 @@ class LoopRewriter extends StatementVisitor<Statement> { | 
| } | 
|  | 
| Statement visitIf(If node) { | 
| +    visitExpression(node.condition); | 
| node.thenStatement = visitStatement(node.thenStatement); | 
| node.elseStatement = visitStatement(node.elseStatement); | 
| return node; | 
| @@ -1518,16 +1811,14 @@ class LoopRewriter extends StatementVisitor<Statement> { | 
| node.label, | 
| body.condition, | 
| body.thenStatement, | 
| -            body.elseStatement, | 
| -            node.updates); | 
| +            body.elseStatement); | 
| } else if (!thenHasContinue && elseHasContinue) { | 
| node.label.binding = null; | 
| return new WhileCondition( | 
| node.label, | 
| new Not(body.condition), | 
| body.elseStatement, | 
| -            body.thenStatement, | 
| -            node.updates); | 
| +            body.thenStatement); | 
| } | 
| } else { | 
| node.body = visitStatement(node.body); | 
| @@ -1538,28 +1829,28 @@ class LoopRewriter extends StatementVisitor<Statement> { | 
|  | 
| Statement visitWhileCondition(WhileCondition node) { | 
| // Note: not reachable but the implementation is trivial | 
| +    visitExpression(node.condition); | 
| node.body = visitStatement(node.body); | 
| node.next = visitStatement(node.next); | 
| return node; | 
| } | 
|  | 
| Statement visitExpressionStatement(ExpressionStatement node) { | 
| +    visitExpression(node.expression); | 
| node.next = visitStatement(node.next); | 
| -    // for (;;) { ... E; continue* L ... } | 
| -    //   ==> | 
| -    // for(;;E) { ... continue* L ... } | 
| -    if (node.next is Continue) { | 
| -      Continue jump = node.next; | 
| -      if (jump.target.useCount == 1) { | 
| -        Loop target = jump.target.binding; | 
| -        target.updates.add(node.expression); | 
| -        return jump; // Return the continue statement. | 
| -        // NOTE: The pattern may reclick in an enclosing expression statement. | 
| -      } | 
| -    } | 
| return node; | 
| } | 
|  | 
| +  Statement visitFunctionDeclaration(FunctionDeclaration node) { | 
| +    new LoopRewriter().rewrite(node.definition); | 
| +    node.next = visitStatement(node.next); | 
| +    return node; | 
| +  } | 
| + | 
| +  void visitFunctionExpression(FunctionExpression node) { | 
| +    new LoopRewriter().rewrite(node.definition); | 
| +  } | 
| + | 
| } | 
|  | 
|  | 
| @@ -1774,6 +2065,17 @@ class LogicalRewriter extends Visitor<Statement, Expression> { | 
| return node; | 
| } | 
|  | 
| +  Expression visitFunctionExpression(FunctionExpression node) { | 
| +    new LogicalRewriter().rewrite(node.definition); | 
| +    return node; | 
| +  } | 
| + | 
| +  Statement visitFunctionDeclaration(FunctionDeclaration node) { | 
| +    new LogicalRewriter().rewrite(node.definition); | 
| +    node.next = visitStatement(node.next); | 
| +    return node; | 
| +  } | 
| + | 
| Expression visitNot(Not node) { | 
| return toBoolean(makeCondition(node.operand, false, liftNots: false)); | 
| } | 
| @@ -1992,3 +2294,4 @@ class LogicalRewriter extends Visitor<Statement, Expression> { | 
| } | 
| } | 
| } | 
| + | 
|  |