| Index: src/compiler/ast-graph-builder.cc | 
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc | 
| index f4b8676730d0b7d80b1101bdf201551bf64ba5cd..3f61d5a29bc232e070cb8bdb26a8356515fa0fcf 100644 | 
| --- a/src/compiler/ast-graph-builder.cc | 
| +++ b/src/compiler/ast-graph-builder.cc | 
| @@ -1175,7 +1175,9 @@ void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) { | 
| Node* index_inc = | 
| NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | 
| // TODO(jarin): provide real bailout id. | 
| -      PrepareFrameState(index_inc, BailoutId::None()); | 
| +      PrepareFrameStateAfterAndBefore(index_inc, BailoutId::None(), | 
| +                                      OutputFrameStateCombine::Ignore(), | 
| +                                      jsgraph()->EmptyFrameState()); | 
| environment()->Poke(0, index_inc); | 
| for_loop.Continue(); | 
| is_property_missing.Else(); | 
| @@ -1195,7 +1197,9 @@ void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) { | 
| Node* index_inc = | 
| NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | 
| // TODO(jarin): provide real bailout id. | 
| -  PrepareFrameState(index_inc, BailoutId::None()); | 
| +  PrepareFrameStateAfterAndBefore(index_inc, BailoutId::None(), | 
| +                                  OutputFrameStateCombine::Ignore(), | 
| +                                  jsgraph()->EmptyFrameState()); | 
| environment()->Poke(0, index_inc); | 
| for_loop.EndLoop(); | 
| environment()->Drop(5); | 
| @@ -1816,11 +1820,13 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { | 
| } | 
| environment()->Push(old_value); | 
| VisitForValue(expr->value()); | 
| +    Node* frame_state_before = environment()->Checkpoint(expr->value()->id()); | 
| Node* right = environment()->Pop(); | 
| Node* left = environment()->Pop(); | 
| Node* value = BuildBinaryOp(left, right, expr->binary_op()); | 
| -    PrepareFrameState(value, expr->binary_operation()->id(), | 
| -                      OutputFrameStateCombine::Push()); | 
| +    PrepareFrameStateAfterAndBefore(value, expr->binary_operation()->id(), | 
| +                                    OutputFrameStateCombine::Push(), | 
| +                                    frame_state_before); | 
| environment()->Push(value); | 
| } else { | 
| VisitForValue(expr->value()); | 
| @@ -2168,9 +2174,11 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { | 
| // Create node to perform +1/-1 operation. | 
| Node* value = | 
| BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op()); | 
| -  // TODO(jarin) Insert proper bailout id here (will need to change | 
| -  // full code generator). | 
| -  PrepareFrameState(value, BailoutId::None()); | 
| +  // This should never deoptimize because we have converted to number | 
| +  // before. | 
| +  PrepareFrameStateAfterAndBefore(value, BailoutId::None(), | 
| +                                  OutputFrameStateCombine::Ignore(), | 
| +                                  jsgraph()->EmptyFrameState()); | 
|  | 
| // Store the value. | 
| switch (assign_type) { | 
| @@ -2222,10 +2230,13 @@ void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 
| default: { | 
| VisitForValue(expr->left()); | 
| VisitForValue(expr->right()); | 
| +      Node* frame_state_before = environment()->Checkpoint(expr->right()->id()); | 
| Node* right = environment()->Pop(); | 
| Node* left = environment()->Pop(); | 
| Node* value = BuildBinaryOp(left, right, expr->op()); | 
| -      PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 
| +      PrepareFrameStateAfterAndBefore(value, expr->id(), | 
| +                                      ast_context()->GetStateCombine(), | 
| +                                      frame_state_before); | 
| ast_context()->ProduceValue(value); | 
| } | 
| } | 
| @@ -2960,11 +2971,31 @@ bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) { | 
|  | 
| void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, | 
| OutputFrameStateCombine combine) { | 
| -  if (OperatorProperties::HasFrameStateInput(node->op())) { | 
| -    DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() == | 
| -           IrOpcode::kDead); | 
| +  if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { | 
| +    DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 
| + | 
| +    DCHECK_EQ(IrOpcode::kDead, | 
| +              NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 
| NodeProperties::ReplaceFrameStateInput( | 
| -        node, environment()->Checkpoint(ast_id, combine)); | 
| +        node, 0, environment()->Checkpoint(ast_id, combine)); | 
| +  } | 
| +} | 
| + | 
| + | 
| +void AstGraphBuilder::PrepareFrameStateAfterAndBefore( | 
| +    Node* node, BailoutId ast_id, OutputFrameStateCombine combine, | 
| +    Node* frame_state_before) { | 
| +  if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { | 
| +    DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op())); | 
| + | 
| +    DCHECK_EQ(IrOpcode::kDead, | 
| +              NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 
| +    NodeProperties::ReplaceFrameStateInput( | 
| +        node, 0, environment()->Checkpoint(ast_id, combine)); | 
| + | 
| +    DCHECK_EQ(IrOpcode::kDead, | 
| +              NodeProperties::GetFrameStateInput(node, 1)->opcode()); | 
| +    NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before); | 
| } | 
| } | 
|  | 
| @@ -2991,7 +3022,7 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, | 
| DCHECK(op->ValueInputCount() == value_input_count); | 
|  | 
| bool has_context = OperatorProperties::HasContextInput(op); | 
| -  bool has_framestate = OperatorProperties::HasFrameStateInput(op); | 
| +  int frame_state_count = OperatorProperties::GetFrameStateInputCount(op); | 
| bool has_control = op->ControlInputCount() == 1; | 
| bool has_effect = op->EffectInputCount() == 1; | 
|  | 
| @@ -2999,13 +3030,13 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, | 
| DCHECK(op->EffectInputCount() < 2); | 
|  | 
| Node* result = NULL; | 
| -  if (!has_context && !has_framestate && !has_control && !has_effect) { | 
| +  if (!has_context && frame_state_count == 0 && !has_control && !has_effect) { | 
| result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | 
| } else { | 
| bool inside_try_scope = try_nesting_level_ > 0; | 
| int input_count_with_deps = value_input_count; | 
| if (has_context) ++input_count_with_deps; | 
| -    if (has_framestate) ++input_count_with_deps; | 
| +    input_count_with_deps += frame_state_count; | 
| if (has_control) ++input_count_with_deps; | 
| if (has_effect) ++input_count_with_deps; | 
| Node** buffer = EnsureInputBufferSize(input_count_with_deps); | 
| @@ -3014,7 +3045,7 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, | 
| if (has_context) { | 
| *current_input++ = current_context(); | 
| } | 
| -    if (has_framestate) { | 
| +    for (int i = 0; i < frame_state_count; i++) { | 
| // The frame state will be inserted later. Here we misuse | 
| // the {DeadControl} node as a sentinel to be later overwritten | 
| // with the real frame state. | 
|  |