| Index: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
 | 
| diff --git a/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart b/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
 | 
| index 2b27aab37ebf2b513f730f22967bb4dece4666a8..d1605c8c713cb6b0e450f0908830a22560740bbc 100644
 | 
| --- a/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
 | 
| +++ b/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
 | 
| @@ -884,6 +884,133 @@ class IrBuilder {
 | 
|      }
 | 
|    }
 | 
|  
 | 
| +  /// Creates a for-in loop, `for (v in e) b`.
 | 
| +  ///
 | 
| +  /// [buildExpression] creates the expression, `e`. The variable, `v`, can
 | 
| +  /// take one of three forms:
 | 
| +  ///     1) `v` can be declared within the for-in statement, like in
 | 
| +  ///        `for (var v in e)`, in which case, [buildVariableDeclaration]
 | 
| +  ///        creates its declaration and [variableElement] is the element for
 | 
| +  ///        the declared variable,
 | 
| +  ///     2) `v` is predeclared statically known variable, that is top-level,
 | 
| +  ///        static, or local variable, in which case [variableElement] is the
 | 
| +  ///        variable element, and [variableSelector] defines its write access,
 | 
| +  ///     3) `v` is an instance variable in which case [variableSelector]
 | 
| +  ///        defines its write access.
 | 
| +  /// [buildBody] creates the body, `b`, of the loop. The jump [target] is used
 | 
| +  /// to identify which `break` and `continue` statements that have this for-in
 | 
| +  /// statement as their target.
 | 
| +  void buildForIn({SubbuildFunction buildExpression,
 | 
| +                   SubbuildFunction buildVariableDeclaration,
 | 
| +                   Element variableElement,
 | 
| +                   Selector variableSelector,
 | 
| +                   SubbuildFunction buildBody,
 | 
| +                   JumpTarget target}) {
 | 
| +    // The for-in loop
 | 
| +    //
 | 
| +    // for (a in e) s;
 | 
| +    //
 | 
| +    // Is compiled analogously to:
 | 
| +    //
 | 
| +    // a = e.iterator;
 | 
| +    // while (a.moveNext()) {
 | 
| +    //   var n0 = a.current;
 | 
| +    //   s;
 | 
| +    // }
 | 
| +
 | 
| +    // The condition and body are delimited.
 | 
| +    IrBuilder condBuilder = new IrBuilder.recursive(this);
 | 
| +
 | 
| +    ir.Primitive expressionReceiver = buildExpression(this);
 | 
| +    List<ir.Primitive> emptyArguments = new List<ir.Primitive>();
 | 
| +
 | 
| +    ir.Parameter iterator = new ir.Parameter(null);
 | 
| +    ir.Continuation iteratorInvoked = new ir.Continuation([iterator]);
 | 
| +    add(new ir.LetCont(iteratorInvoked,
 | 
| +        new ir.InvokeMethod(expressionReceiver,
 | 
| +            new Selector.getter("iterator", null), iteratorInvoked,
 | 
| +            emptyArguments)));
 | 
| +
 | 
| +    ir.Parameter condition = new ir.Parameter(null);
 | 
| +    ir.Continuation moveNextInvoked = new ir.Continuation([condition]);
 | 
| +    condBuilder.add(new ir.LetCont(moveNextInvoked,
 | 
| +        new ir.InvokeMethod(iterator,
 | 
| +            new Selector.call("moveNext", null, 0),
 | 
| +            moveNextInvoked, emptyArguments)));
 | 
| +
 | 
| +    JumpCollector breakCollector = new JumpCollector(target);
 | 
| +    JumpCollector continueCollector = new JumpCollector(target);
 | 
| +    state.breakCollectors.add(breakCollector);
 | 
| +    state.continueCollectors.add(continueCollector);
 | 
| +
 | 
| +    IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder);
 | 
| +    if (buildVariableDeclaration != null) {
 | 
| +      buildVariableDeclaration(bodyBuilder);
 | 
| +    }
 | 
| +
 | 
| +    ir.Parameter currentValue = new ir.Parameter(null);
 | 
| +    ir.Continuation currentInvoked = new ir.Continuation([currentValue]);
 | 
| +    bodyBuilder.add(new ir.LetCont(currentInvoked,
 | 
| +        new ir.InvokeMethod(iterator, new Selector.getter("current", null),
 | 
| +            currentInvoked, emptyArguments)));
 | 
| +    if (Elements.isLocal(variableElement)) {
 | 
| +      bodyBuilder.buildLocalSet(variableElement, currentValue);
 | 
| +    } else if (Elements.isStaticOrTopLevel(variableElement)) {
 | 
| +      bodyBuilder.buildStaticSet(
 | 
| +          variableElement, variableSelector, currentValue);
 | 
| +    } else {
 | 
| +      ir.Primitive receiver = bodyBuilder.buildThis();
 | 
| +      bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue);
 | 
| +    }
 | 
| +
 | 
| +    buildBody(bodyBuilder);
 | 
| +    assert(state.breakCollectors.last == breakCollector);
 | 
| +    assert(state.continueCollectors.last == continueCollector);
 | 
| +    state.breakCollectors.removeLast();
 | 
| +    state.continueCollectors.removeLast();
 | 
| +
 | 
| +    // Create body entry and loop exit continuations and a branch to them.
 | 
| +    ir.Continuation bodyContinuation = new ir.Continuation([]);
 | 
| +    ir.Continuation exitContinuation = new ir.Continuation([]);
 | 
| +    ir.LetCont branch =
 | 
| +        new ir.LetCont(exitContinuation,
 | 
| +            new ir.LetCont(bodyContinuation,
 | 
| +                new ir.Branch(new ir.IsTrue(condition),
 | 
| +                              bodyContinuation,
 | 
| +                              exitContinuation)));
 | 
| +    // If there are breaks in the body, then there must be a join-point
 | 
| +    // continuation for the normal exit and the breaks.
 | 
| +    bool hasBreaks = !breakCollector.isEmpty;
 | 
| +    ir.LetCont letJoin;
 | 
| +    if (hasBreaks) {
 | 
| +      letJoin = new ir.LetCont(null, branch);
 | 
| +      condBuilder.add(letJoin);
 | 
| +      condBuilder._current = branch;
 | 
| +    } else {
 | 
| +      condBuilder.add(branch);
 | 
| +    }
 | 
| +    ir.Continuation loopContinuation =
 | 
| +        new ir.Continuation(condBuilder._parameters);
 | 
| +    if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder);
 | 
| +    invokeFullJoin(
 | 
| +        loopContinuation, continueCollector, recursive: true);
 | 
| +    bodyContinuation.body = bodyBuilder._root;
 | 
| +
 | 
| +    loopContinuation.body = condBuilder._root;
 | 
| +    add(new ir.LetCont(loopContinuation,
 | 
| +            new ir.InvokeContinuation(loopContinuation,
 | 
| +                                      environment.index2value)));
 | 
| +    if (hasBreaks) {
 | 
| +      _current = branch;
 | 
| +      environment = condBuilder.environment;
 | 
| +      breakCollector.addJump(this);
 | 
| +      letJoin.continuation = createJoin(environment.length, breakCollector);
 | 
| +      _current = letJoin;
 | 
| +    } else {
 | 
| +      _current = condBuilder._current;
 | 
| +      environment = condBuilder.environment;
 | 
| +    }
 | 
| +  }
 | 
|  
 | 
|    /// Creates a while loop in which the condition and body are created by
 | 
|    /// [buildCondition] and [buildBody], respectively.
 | 
| @@ -1170,6 +1297,14 @@ class IrBuilder {
 | 
|      return joinContinuation.parameters.last;
 | 
|    }
 | 
|  
 | 
| +  /// Creates an access to `this`.
 | 
| +  ir.Primitive buildThis() {
 | 
| +    assert(isOpen);
 | 
| +    ir.Primitive result = new ir.This();
 | 
| +    add(new ir.LetPrim(result));
 | 
| +    return result;
 | 
| +  }
 | 
| +
 | 
|    /// Create a non-recursive join-point continuation.
 | 
|    ///
 | 
|    /// Given the environment length at the join point and a list of
 | 
| 
 |