| Index: src/compiler/ast-graph-builder.cc
 | 
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
 | 
| index 9359719d52cb36ee944d56eb7f3d9da35e7d10dd..49a67157c7a96866fbd12045e1070ee59c76aace 100644
 | 
| --- a/src/compiler/ast-graph-builder.cc
 | 
| +++ b/src/compiler/ast-graph-builder.cc
 | 
| @@ -238,8 +238,12 @@ Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id) {
 | 
|  
 | 
|  
 | 
|  AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
 | 
| -                                        Expression::Context kind)
 | 
| -    : kind_(kind), owner_(own), outer_(own->ast_context()) {
 | 
| +                                        Expression::Context kind,
 | 
| +                                        BailoutId bailout_id)
 | 
| +    : bailout_id_(bailout_id),
 | 
| +      kind_(kind),
 | 
| +      owner_(own),
 | 
| +      outer_(own->ast_context()) {
 | 
|    owner()->set_ast_context(this);  // Push.
 | 
|  #ifdef DEBUG
 | 
|    original_height_ = environment()->stack_height();
 | 
| @@ -267,6 +271,28 @@ AstGraphBuilder::AstTestContext::~AstTestContext() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void AstGraphBuilder::AstEffectContext::ProduceValueWithLazyBailout(
 | 
| +    Node* value) {
 | 
| +  ProduceValue(value);
 | 
| +  owner()->BuildLazyBailout(value, bailout_id_);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void AstGraphBuilder::AstValueContext::ProduceValueWithLazyBailout(
 | 
| +    Node* value) {
 | 
| +  ProduceValue(value);
 | 
| +  owner()->BuildLazyBailout(value, bailout_id_);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void AstGraphBuilder::AstTestContext::ProduceValueWithLazyBailout(Node* value) {
 | 
| +  environment()->Push(value);
 | 
| +  owner()->BuildLazyBailout(value, bailout_id_);
 | 
| +  environment()->Pop();
 | 
| +  ProduceValue(value);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
 | 
|    // The value is ignored.
 | 
|  }
 | 
| @@ -333,7 +359,7 @@ void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
 | 
|  
 | 
|  
 | 
|  void AstGraphBuilder::VisitForValue(Expression* expr) {
 | 
| -  AstValueContext for_value(this);
 | 
| +  AstValueContext for_value(this, expr->id());
 | 
|    if (!HasStackOverflow()) {
 | 
|      expr->Accept(this);
 | 
|    }
 | 
| @@ -341,7 +367,7 @@ void AstGraphBuilder::VisitForValue(Expression* expr) {
 | 
|  
 | 
|  
 | 
|  void AstGraphBuilder::VisitForEffect(Expression* expr) {
 | 
| -  AstEffectContext for_effect(this);
 | 
| +  AstEffectContext for_effect(this, expr->id());
 | 
|    if (!HasStackOverflow()) {
 | 
|      expr->Accept(this);
 | 
|    }
 | 
| @@ -349,7 +375,7 @@ void AstGraphBuilder::VisitForEffect(Expression* expr) {
 | 
|  
 | 
|  
 | 
|  void AstGraphBuilder::VisitForTest(Expression* expr) {
 | 
| -  AstTestContext for_condition(this);
 | 
| +  AstTestContext for_condition(this, expr->id());
 | 
|    if (!HasStackOverflow()) {
 | 
|      expr->Accept(this);
 | 
|    }
 | 
| @@ -687,7 +713,7 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
 | 
|          Node* exit_cond =
 | 
|              NewNode(javascript()->LessThan(), index, cache_length);
 | 
|          // TODO(jarin): provide real bailout id.
 | 
| -        PrepareFrameState(exit_cond, BailoutId::None());
 | 
| +        BuildLazyBailout(exit_cond, BailoutId::None());
 | 
|          for_loop.BreakUnless(exit_cond);
 | 
|          // TODO(dcarney): this runtime call should be a handful of
 | 
|          //                simplified instructions that
 | 
| @@ -727,7 +753,7 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
 | 
|            Node* res = ProcessArguments(
 | 
|                javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3);
 | 
|            // TODO(jarin): provide real bailout id.
 | 
| -          PrepareFrameState(res, BailoutId::None());
 | 
| +          BuildLazyBailout(res, BailoutId::None());
 | 
|            Node* property_missing = NewNode(javascript()->StrictEqual(), res,
 | 
|                                             jsgraph()->ZeroConstant());
 | 
|            {
 | 
| @@ -739,7 +765,7 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
 | 
|                  NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
 | 
|              environment()->Poke(0, index_inc);
 | 
|              // TODO(jarin): provide real bailout id.
 | 
| -            PrepareFrameState(index_inc, BailoutId::None());
 | 
| +            BuildLazyBailout(index_inc, BailoutId::None());
 | 
|              for_loop.Continue();
 | 
|              is_property_missing.Else();
 | 
|              is_property_missing.End();
 | 
| @@ -758,7 +784,7 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
 | 
|              NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
 | 
|          environment()->Poke(0, index_inc);
 | 
|          // TODO(jarin): provide real bailout id.
 | 
| -        PrepareFrameState(index_inc, BailoutId::None());
 | 
| +        BuildLazyBailout(index_inc, BailoutId::None());
 | 
|          for_loop.EndBody();
 | 
|          for_loop.EndLoop();
 | 
|          environment()->Drop(5);
 | 
| @@ -906,7 +932,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
 | 
|              PrintableUnique<Name> name = MakeUnique(key->AsPropertyName());
 | 
|              Node* store =
 | 
|                  NewNode(javascript()->StoreNamed(name), literal, value);
 | 
| -            PrepareFrameState(store, key->id());
 | 
| +            BuildLazyBailout(store, key->id());
 | 
|            } else {
 | 
|              VisitForEffect(property->value());
 | 
|            }
 | 
| @@ -998,7 +1024,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
 | 
|      Node* value = environment()->Pop();
 | 
|      Node* index = jsgraph()->Constant(i);
 | 
|      Node* store = NewNode(javascript()->StoreProperty(), literal, index, value);
 | 
| -    PrepareFrameState(store, expr->GetIdForElement(i));
 | 
| +    BuildLazyBailout(store, expr->GetIdForElement(i));
 | 
|    }
 | 
|  
 | 
|    environment()->Pop();  // Array literal index.
 | 
| @@ -1030,7 +1056,7 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
 | 
|            MakeUnique(property->key()->AsLiteral()->AsPropertyName());
 | 
|        Node* store = NewNode(javascript()->StoreNamed(name), object, value);
 | 
|        // TODO(jarin) Fill in the correct bailout id.
 | 
| -      PrepareFrameState(store, BailoutId::None());
 | 
| +      BuildLazyBailout(store, BailoutId::None());
 | 
|        break;
 | 
|      }
 | 
|      case KEYED_PROPERTY: {
 | 
| @@ -1042,7 +1068,7 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
 | 
|        value = environment()->Pop();
 | 
|        Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
 | 
|        // TODO(jarin) Fill in the correct bailout id.
 | 
| -      PrepareFrameState(store, BailoutId::None());
 | 
| +      BuildLazyBailout(store, BailoutId::None());
 | 
|        break;
 | 
|      }
 | 
|    }
 | 
| @@ -1086,14 +1112,14 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
 | 
|          PrintableUnique<Name> name =
 | 
|              MakeUnique(property->key()->AsLiteral()->AsPropertyName());
 | 
|          old_value = NewNode(javascript()->LoadNamed(name), object);
 | 
| -        PrepareFrameState(old_value, property->LoadId(), PUSH_OUTPUT);
 | 
| +        BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
 | 
|          break;
 | 
|        }
 | 
|        case KEYED_PROPERTY: {
 | 
|          Node* key = environment()->Top();
 | 
|          Node* object = environment()->Peek(1);
 | 
|          old_value = NewNode(javascript()->LoadProperty(), object, key);
 | 
| -        PrepareFrameState(old_value, property->LoadId(), PUSH_OUTPUT);
 | 
| +        BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
 | 
|          break;
 | 
|        }
 | 
|      }
 | 
| @@ -1103,7 +1129,7 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
 | 
|      Node* left = environment()->Pop();
 | 
|      Node* value = BuildBinaryOp(left, right, expr->binary_op());
 | 
|      environment()->Push(value);
 | 
| -    PrepareFrameState(value, expr->binary_operation()->id());
 | 
| +    BuildLazyBailout(value, expr->binary_operation()->id());
 | 
|    } else {
 | 
|      VisitForValue(expr->value());
 | 
|    }
 | 
| @@ -1122,14 +1148,14 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
 | 
|        PrintableUnique<Name> name =
 | 
|            MakeUnique(property->key()->AsLiteral()->AsPropertyName());
 | 
|        Node* store = NewNode(javascript()->StoreNamed(name), object, value);
 | 
| -      PrepareFrameState(store, expr->AssignmentId());
 | 
| +      BuildLazyBailout(store, expr->AssignmentId());
 | 
|        break;
 | 
|      }
 | 
|      case KEYED_PROPERTY: {
 | 
|        Node* key = environment()->Pop();
 | 
|        Node* object = environment()->Pop();
 | 
|        Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
 | 
| -      PrepareFrameState(store, expr->AssignmentId());
 | 
| +      BuildLazyBailout(store, expr->AssignmentId());
 | 
|        break;
 | 
|      }
 | 
|    }
 | 
| @@ -1172,8 +1198,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
 | 
|      Node* object = environment()->Pop();
 | 
|      value = NewNode(javascript()->LoadProperty(), object, key);
 | 
|    }
 | 
| -  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
 | 
| -  ast_context()->ProduceValue(value);
 | 
| +  ast_context()->ProduceValueWithLazyBailout(value);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1217,7 +1242,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
 | 
|          Node* key = environment()->Pop();
 | 
|          callee_value = NewNode(javascript()->LoadProperty(), object, key);
 | 
|        }
 | 
| -      PrepareFrameState(callee_value, property->LoadId(), PUSH_OUTPUT);
 | 
| +      BuildLazyBailoutWithPushedNode(callee_value, property->LoadId());
 | 
|        receiver_value = environment()->Pop();
 | 
|        // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
 | 
|        // object for sloppy callees. This could also be modeled explicitly here,
 | 
| @@ -1272,8 +1297,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
 | 
|    // Create node to perform the function call.
 | 
|    Operator* call = javascript()->Call(args->length() + 2, flags);
 | 
|    Node* value = ProcessArguments(call, args->length() + 2);
 | 
| -  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
 | 
| -  ast_context()->ProduceValue(value);
 | 
| +  ast_context()->ProduceValueWithLazyBailout(value);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1287,8 +1311,7 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
 | 
|    // Create node to perform the construct call.
 | 
|    Operator* call = javascript()->CallNew(args->length() + 1);
 | 
|    Node* value = ProcessArguments(call, args->length() + 1);
 | 
| -  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
 | 
| -  ast_context()->ProduceValue(value);
 | 
| +  ast_context()->ProduceValueWithLazyBailout(value);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1304,7 +1327,7 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
 | 
|    environment()->Push(callee_value);
 | 
|    // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
 | 
|    // refuses to optimize functions with jsruntime calls).
 | 
| -  PrepareFrameState(callee_value, BailoutId::None());
 | 
| +  BuildLazyBailout(callee_value, BailoutId::None());
 | 
|    environment()->Push(receiver_value);
 | 
|  
 | 
|    // Evaluate all arguments to the JS runtime call.
 | 
| @@ -1314,8 +1337,7 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
 | 
|    // Create node to perform the JS runtime call.
 | 
|    Operator* call = javascript()->Call(args->length() + 2, flags);
 | 
|    Node* value = ProcessArguments(call, args->length() + 2);
 | 
| -  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
 | 
| -  ast_context()->ProduceValue(value);
 | 
| +  ast_context()->ProduceValueWithLazyBailout(value);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1337,8 +1359,7 @@ void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
 | 
|    Runtime::FunctionId functionId = function->function_id;
 | 
|    Operator* call = javascript()->Runtime(functionId, args->length());
 | 
|    Node* value = ProcessArguments(call, args->length());
 | 
| -  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
 | 
| -  ast_context()->ProduceValue(value);
 | 
| +  ast_context()->ProduceValueWithLazyBailout(value);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1385,7 +1406,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|        PrintableUnique<Name> name =
 | 
|            MakeUnique(property->key()->AsLiteral()->AsPropertyName());
 | 
|        old_value = NewNode(javascript()->LoadNamed(name), object);
 | 
| -      PrepareFrameState(old_value, property->LoadId(), PUSH_OUTPUT);
 | 
| +      BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
 | 
|        stack_depth = 1;
 | 
|        break;
 | 
|      }
 | 
| @@ -1395,7 +1416,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|        Node* key = environment()->Top();
 | 
|        Node* object = environment()->Peek(1);
 | 
|        old_value = NewNode(javascript()->LoadProperty(), object, key);
 | 
| -      PrepareFrameState(old_value, property->LoadId(), PUSH_OUTPUT);
 | 
| +      BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
 | 
|        stack_depth = 2;
 | 
|        break;
 | 
|      }
 | 
| @@ -1412,7 +1433,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|        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());
 | 
| +  BuildLazyBailout(value, BailoutId::None());
 | 
|  
 | 
|    // Store the value.
 | 
|    switch (assign_type) {
 | 
| @@ -1427,14 +1448,14 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|        PrintableUnique<Name> name =
 | 
|            MakeUnique(property->key()->AsLiteral()->AsPropertyName());
 | 
|        Node* store = NewNode(javascript()->StoreNamed(name), object, value);
 | 
| -      PrepareFrameState(store, expr->AssignmentId());
 | 
| +      BuildLazyBailout(store, expr->AssignmentId());
 | 
|        break;
 | 
|      }
 | 
|      case KEYED_PROPERTY: {
 | 
|        Node* key = environment()->Pop();
 | 
|        Node* object = environment()->Pop();
 | 
|        Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
 | 
| -      PrepareFrameState(store, expr->AssignmentId());
 | 
| +      BuildLazyBailout(store, expr->AssignmentId());
 | 
|        break;
 | 
|      }
 | 
|    }
 | 
| @@ -1459,8 +1480,7 @@ void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
 | 
|        Node* right = environment()->Pop();
 | 
|        Node* left = environment()->Pop();
 | 
|        Node* value = BuildBinaryOp(left, right, expr->op());
 | 
| -      PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
 | 
| -      ast_context()->ProduceValue(value);
 | 
| +      ast_context()->ProduceValueWithLazyBailout(value);
 | 
|      }
 | 
|    }
 | 
|  }
 | 
| @@ -1510,7 +1530,7 @@ void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
 | 
|    Node* value = NewNode(op, left, right);
 | 
|    ast_context()->ProduceValue(value);
 | 
|  
 | 
| -  PrepareFrameState(value, expr->id());
 | 
| +  BuildLazyBailout(value, expr->id());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1740,7 +1760,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
 | 
|        PrintableUnique<Name> name = MakeUnique(variable->name());
 | 
|        Operator* op = javascript()->LoadNamed(name, contextual_mode);
 | 
|        Node* node = NewNode(op, global);
 | 
| -      PrepareFrameState(node, bailout_id, PUSH_OUTPUT);
 | 
| +      BuildLazyBailoutWithPushedNode(node, bailout_id);
 | 
|        return node;
 | 
|      }
 | 
|      case Variable::PARAMETER:
 | 
| @@ -1841,7 +1861,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
 | 
|        PrintableUnique<Name> name = MakeUnique(variable->name());
 | 
|        Operator* op = javascript()->StoreNamed(name);
 | 
|        Node* store = NewNode(op, global, value);
 | 
| -      PrepareFrameState(store, bailout_id);
 | 
| +      BuildLazyBailout(store, bailout_id);
 | 
|        return store;
 | 
|      }
 | 
|      case Variable::PARAMETER:
 | 
| @@ -1993,16 +2013,11 @@ Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
 | 
| -                                        OutputFrameStateCombine combine) {
 | 
| +void AstGraphBuilder::BuildLazyBailout(Node* node, BailoutId ast_id) {
 | 
|    if (OperatorProperties::CanLazilyDeoptimize(node->op())) {
 | 
|      // The deopting node should have an outgoing control dependency.
 | 
|      DCHECK(environment()->GetControlDependency() == node);
 | 
|  
 | 
| -    if (combine == PUSH_OUTPUT) {
 | 
| -      environment()->Push(node);
 | 
| -    }
 | 
| -
 | 
|      StructuredGraphBuilder::Environment* continuation_env = environment();
 | 
|      // Create environment for the deoptimization block, and build the block.
 | 
|      StructuredGraphBuilder::Environment* deopt_env =
 | 
| @@ -2024,14 +2039,17 @@ void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
 | 
|      // Continue with the original environment.
 | 
|      set_environment(continuation_env);
 | 
|  
 | 
| -    if (combine == PUSH_OUTPUT) {
 | 
| -      environment()->Pop();
 | 
| -    }
 | 
| -
 | 
|      NewNode(common()->Continuation());
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +
 | 
| +void AstGraphBuilder::BuildLazyBailoutWithPushedNode(Node* node,
 | 
| +                                                     BailoutId ast_id) {
 | 
| +  environment()->Push(node);
 | 
| +  BuildLazyBailout(node, ast_id);
 | 
| +  environment()->Pop();
 | 
| +}
 | 
|  }
 | 
|  }
 | 
|  }  // namespace v8::internal::compiler
 | 
| 
 |