| Index: src/compiler/ast-graph-builder.cc
|
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
|
| index 2c242cbe1434c28cf76f0ef8bfb583fa277fa69e..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);
|
| }
|
| @@ -686,6 +712,8 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
| Node* index = environment()->Peek(0);
|
| Node* exit_cond =
|
| NewNode(javascript()->LessThan(), index, cache_length);
|
| + // TODO(jarin): provide real bailout id.
|
| + BuildLazyBailout(exit_cond, BailoutId::None());
|
| for_loop.BreakUnless(exit_cond);
|
| // TODO(dcarney): this runtime call should be a handful of
|
| // simplified instructions that
|
| @@ -724,6 +752,8 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
| // is gone.
|
| Node* res = ProcessArguments(
|
| javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3);
|
| + // TODO(jarin): provide real bailout id.
|
| + BuildLazyBailout(res, BailoutId::None());
|
| Node* property_missing = NewNode(javascript()->StrictEqual(), res,
|
| jsgraph()->ZeroConstant());
|
| {
|
| @@ -734,6 +764,8 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
| Node* index_inc =
|
| NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
|
| environment()->Poke(0, index_inc);
|
| + // TODO(jarin): provide real bailout id.
|
| + BuildLazyBailout(index_inc, BailoutId::None());
|
| for_loop.Continue();
|
| is_property_missing.Else();
|
| is_property_missing.End();
|
| @@ -751,6 +783,8 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
| Node* index_inc =
|
| NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
|
| environment()->Poke(0, index_inc);
|
| + // TODO(jarin): provide real bailout id.
|
| + BuildLazyBailout(index_inc, BailoutId::None());
|
| for_loop.EndBody();
|
| for_loop.EndLoop();
|
| environment()->Drop(5);
|
| @@ -829,7 +863,7 @@ void AstGraphBuilder::VisitConditional(Conditional* expr) {
|
|
|
|
|
| void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
| - Node* value = BuildVariableLoad(expr->var());
|
| + Node* value = BuildVariableLoad(expr->var(), expr->id());
|
| ast_context()->ProduceValue(value);
|
| }
|
|
|
| @@ -896,7 +930,9 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
| VisitForValue(property->value());
|
| Node* value = environment()->Pop();
|
| PrintableUnique<Name> name = MakeUnique(key->AsPropertyName());
|
| - NewNode(javascript()->StoreNamed(name), literal, value);
|
| + Node* store =
|
| + NewNode(javascript()->StoreNamed(name), literal, value);
|
| + BuildLazyBailout(store, key->id());
|
| } else {
|
| VisitForEffect(property->value());
|
| }
|
| @@ -987,7 +1023,8 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
| VisitForValue(subexpr);
|
| Node* value = environment()->Pop();
|
| Node* index = jsgraph()->Constant(i);
|
| - NewNode(javascript()->StoreProperty(), literal, index, value);
|
| + Node* store = NewNode(javascript()->StoreProperty(), literal, index, value);
|
| + BuildLazyBailout(store, expr->GetIdForElement(i));
|
| }
|
|
|
| environment()->Pop(); // Array literal index.
|
| @@ -1006,7 +1043,8 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
|
| switch (assign_type) {
|
| case VARIABLE: {
|
| Variable* var = expr->AsVariableProxy()->var();
|
| - BuildVariableAssignment(var, value, Token::ASSIGN);
|
| + // TODO(jarin) Fill in the correct bailout id.
|
| + BuildVariableAssignment(var, value, Token::ASSIGN, BailoutId::None());
|
| break;
|
| }
|
| case NAMED_PROPERTY: {
|
| @@ -1016,7 +1054,9 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
|
| value = environment()->Pop();
|
| PrintableUnique<Name> name =
|
| MakeUnique(property->key()->AsLiteral()->AsPropertyName());
|
| - NewNode(javascript()->StoreNamed(name), object, value);
|
| + Node* store = NewNode(javascript()->StoreNamed(name), object, value);
|
| + // TODO(jarin) Fill in the correct bailout id.
|
| + BuildLazyBailout(store, BailoutId::None());
|
| break;
|
| }
|
| case KEYED_PROPERTY: {
|
| @@ -1026,7 +1066,9 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
|
| Node* key = environment()->Pop();
|
| Node* object = environment()->Pop();
|
| value = environment()->Pop();
|
| - NewNode(javascript()->StoreProperty(), object, key, value);
|
| + Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
|
| + // TODO(jarin) Fill in the correct bailout id.
|
| + BuildLazyBailout(store, BailoutId::None());
|
| break;
|
| }
|
| }
|
| @@ -1062,7 +1104,7 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
| switch (assign_type) {
|
| case VARIABLE: {
|
| Variable* variable = expr->target()->AsVariableProxy()->var();
|
| - old_value = BuildVariableLoad(variable);
|
| + old_value = BuildVariableLoad(variable, expr->target()->id());
|
| break;
|
| }
|
| case NAMED_PROPERTY: {
|
| @@ -1070,12 +1112,14 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
| PrintableUnique<Name> name =
|
| MakeUnique(property->key()->AsLiteral()->AsPropertyName());
|
| old_value = NewNode(javascript()->LoadNamed(name), object);
|
| + 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);
|
| + BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
|
| break;
|
| }
|
| }
|
| @@ -1085,6 +1129,7 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
| Node* left = environment()->Pop();
|
| Node* value = BuildBinaryOp(left, right, expr->binary_op());
|
| environment()->Push(value);
|
| + BuildLazyBailout(value, expr->binary_operation()->id());
|
| } else {
|
| VisitForValue(expr->value());
|
| }
|
| @@ -1094,20 +1139,23 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
| switch (assign_type) {
|
| case VARIABLE: {
|
| Variable* variable = expr->target()->AsVariableProxy()->var();
|
| - BuildVariableAssignment(variable, value, expr->op());
|
| + BuildVariableAssignment(variable, value, expr->op(),
|
| + expr->AssignmentId());
|
| break;
|
| }
|
| case NAMED_PROPERTY: {
|
| Node* object = environment()->Pop();
|
| PrintableUnique<Name> name =
|
| MakeUnique(property->key()->AsLiteral()->AsPropertyName());
|
| - NewNode(javascript()->StoreNamed(name), object, value);
|
| + Node* store = NewNode(javascript()->StoreNamed(name), object, value);
|
| + BuildLazyBailout(store, expr->AssignmentId());
|
| break;
|
| }
|
| case KEYED_PROPERTY: {
|
| Node* key = environment()->Pop();
|
| Node* object = environment()->Pop();
|
| - NewNode(javascript()->StoreProperty(), object, key, value);
|
| + Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
|
| + BuildLazyBailout(store, expr->AssignmentId());
|
| break;
|
| }
|
| }
|
| @@ -1150,7 +1198,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
| Node* object = environment()->Pop();
|
| value = NewNode(javascript()->LoadProperty(), object, key);
|
| }
|
| - ast_context()->ProduceValue(value);
|
| + ast_context()->ProduceValueWithLazyBailout(value);
|
| }
|
|
|
|
|
| @@ -1167,7 +1215,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
| switch (call_type) {
|
| case Call::GLOBAL_CALL: {
|
| Variable* variable = callee->AsVariableProxy()->var();
|
| - callee_value = BuildVariableLoad(variable);
|
| + callee_value = BuildVariableLoad(variable, expr->expression()->id());
|
| receiver_value = jsgraph()->UndefinedConstant();
|
| break;
|
| }
|
| @@ -1194,6 +1242,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
| Node* key = environment()->Pop();
|
| callee_value = NewNode(javascript()->LoadProperty(), object, key);
|
| }
|
| + 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,
|
| @@ -1248,7 +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);
|
| - ast_context()->ProduceValue(value);
|
| + ast_context()->ProduceValueWithLazyBailout(value);
|
| }
|
|
|
|
|
| @@ -1262,7 +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);
|
| - ast_context()->ProduceValue(value);
|
| + ast_context()->ProduceValueWithLazyBailout(value);
|
| }
|
|
|
|
|
| @@ -1276,6 +1325,9 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
|
| PrintableUnique<String> unique = MakeUnique(name);
|
| Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value);
|
| environment()->Push(callee_value);
|
| + // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
|
| + // refuses to optimize functions with jsruntime calls).
|
| + BuildLazyBailout(callee_value, BailoutId::None());
|
| environment()->Push(receiver_value);
|
|
|
| // Evaluate all arguments to the JS runtime call.
|
| @@ -1285,7 +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);
|
| - ast_context()->ProduceValue(value);
|
| + ast_context()->ProduceValueWithLazyBailout(value);
|
| }
|
|
|
|
|
| @@ -1307,9 +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());
|
| - ast_context()->ProduceValue(value);
|
| -
|
| - BuildLazyBailout(value, expr->id());
|
| + ast_context()->ProduceValueWithLazyBailout(value);
|
| }
|
|
|
|
|
| @@ -1346,7 +1396,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| switch (assign_type) {
|
| case VARIABLE: {
|
| Variable* variable = expr->expression()->AsVariableProxy()->var();
|
| - old_value = BuildVariableLoad(variable);
|
| + old_value = BuildVariableLoad(variable, expr->expression()->id());
|
| stack_depth = 0;
|
| break;
|
| }
|
| @@ -1356,6 +1406,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| PrintableUnique<Name> name =
|
| MakeUnique(property->key()->AsLiteral()->AsPropertyName());
|
| old_value = NewNode(javascript()->LoadNamed(name), object);
|
| + BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
|
| stack_depth = 1;
|
| break;
|
| }
|
| @@ -1365,6 +1416,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| Node* key = environment()->Top();
|
| Node* object = environment()->Peek(1);
|
| old_value = NewNode(javascript()->LoadProperty(), object, key);
|
| + BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
|
| stack_depth = 2;
|
| break;
|
| }
|
| @@ -1379,25 +1431,31 @@ 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).
|
| + BuildLazyBailout(value, BailoutId::None());
|
|
|
| // Store the value.
|
| switch (assign_type) {
|
| case VARIABLE: {
|
| Variable* variable = expr->expression()->AsVariableProxy()->var();
|
| - BuildVariableAssignment(variable, value, expr->op());
|
| + BuildVariableAssignment(variable, value, expr->op(),
|
| + expr->AssignmentId());
|
| break;
|
| }
|
| case NAMED_PROPERTY: {
|
| Node* object = environment()->Pop();
|
| PrintableUnique<Name> name =
|
| MakeUnique(property->key()->AsLiteral()->AsPropertyName());
|
| - NewNode(javascript()->StoreNamed(name), object, value);
|
| + Node* store = NewNode(javascript()->StoreNamed(name), object, value);
|
| + BuildLazyBailout(store, expr->AssignmentId());
|
| break;
|
| }
|
| case KEYED_PROPERTY: {
|
| Node* key = environment()->Pop();
|
| Node* object = environment()->Pop();
|
| - NewNode(javascript()->StoreProperty(), object, key, value);
|
| + Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
|
| + BuildLazyBailout(store, expr->AssignmentId());
|
| break;
|
| }
|
| }
|
| @@ -1422,7 +1480,7 @@ void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
|
| Node* right = environment()->Pop();
|
| Node* left = environment()->Pop();
|
| Node* value = BuildBinaryOp(left, right, expr->op());
|
| - ast_context()->ProduceValue(value);
|
| + ast_context()->ProduceValueWithLazyBailout(value);
|
| }
|
| }
|
| }
|
| @@ -1471,6 +1529,8 @@ void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| Node* left = environment()->Pop();
|
| Node* value = NewNode(op, left, right);
|
| ast_context()->ProduceValue(value);
|
| +
|
| + BuildLazyBailout(value, expr->id());
|
| }
|
|
|
|
|
| @@ -1550,7 +1610,8 @@ void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
|
| // Typeof does not throw a reference error on global variables, hence we
|
| // perform a non-contextual load in case the operand is a variable proxy.
|
| Variable* variable = expr->expression()->AsVariableProxy()->var();
|
| - operand = BuildVariableLoad(variable, NOT_CONTEXTUAL);
|
| + operand =
|
| + BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL);
|
| } else {
|
| VisitForValue(expr->expression());
|
| operand = environment()->Pop();
|
| @@ -1650,7 +1711,8 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
|
|
|
| // Assign the object to the arguments variable.
|
| DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
|
| - BuildVariableAssignment(arguments, object, Token::ASSIGN);
|
| + // This should never lazy deopt, so it is fine to send invalid bailout id.
|
| + BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None());
|
|
|
| return object;
|
| }
|
| @@ -1687,6 +1749,7 @@ Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
|
|
|
|
|
| Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
| + BailoutId bailout_id,
|
| ContextualMode contextual_mode) {
|
| Node* the_hole = jsgraph()->TheHoleConstant();
|
| VariableMode mode = variable->mode();
|
| @@ -1696,7 +1759,9 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
| Node* global = BuildLoadGlobalObject();
|
| PrintableUnique<Name> name = MakeUnique(variable->name());
|
| Operator* op = javascript()->LoadNamed(name, contextual_mode);
|
| - return NewNode(op, global);
|
| + Node* node = NewNode(op, global);
|
| + BuildLazyBailoutWithPushedNode(node, bailout_id);
|
| + return node;
|
| }
|
| case Variable::PARAMETER:
|
| case Variable::LOCAL: {
|
| @@ -1785,7 +1850,8 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
|
|
|
|
|
| Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
|
| - Token::Value op) {
|
| + Token::Value op,
|
| + BailoutId bailout_id) {
|
| Node* the_hole = jsgraph()->TheHoleConstant();
|
| VariableMode mode = variable->mode();
|
| switch (variable->location()) {
|
| @@ -1794,7 +1860,9 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
|
| Node* global = BuildLoadGlobalObject();
|
| PrintableUnique<Name> name = MakeUnique(variable->name());
|
| Operator* op = javascript()->StoreNamed(name);
|
| - return NewNode(op, global, value);
|
| + Node* store = NewNode(op, global, value);
|
| + BuildLazyBailout(store, bailout_id);
|
| + return store;
|
| }
|
| case Variable::PARAMETER:
|
| case Variable::LOCAL:
|
| @@ -1958,6 +2026,10 @@ void AstGraphBuilder::BuildLazyBailout(Node* node, BailoutId ast_id) {
|
|
|
| NewNode(common()->LazyDeoptimization());
|
|
|
| + // TODO(jarin) If ast_id.IsNone(), perhaps we should generate an empty
|
| + // deopt block and make sure there is no patch entry for this (so
|
| + // that the deoptimizer dies when trying to deoptimize here).
|
| +
|
| Node* state_node = environment()->Checkpoint(ast_id);
|
|
|
| Node* deoptimize_node = NewNode(common()->Deoptimize(), state_node);
|
| @@ -1970,6 +2042,14 @@ void AstGraphBuilder::BuildLazyBailout(Node* node, BailoutId ast_id) {
|
| NewNode(common()->Continuation());
|
| }
|
| }
|
| +
|
| +
|
| +void AstGraphBuilder::BuildLazyBailoutWithPushedNode(Node* node,
|
| + BailoutId ast_id) {
|
| + environment()->Push(node);
|
| + BuildLazyBailout(node, ast_id);
|
| + environment()->Pop();
|
| +}
|
| }
|
| }
|
| } // namespace v8::internal::compiler
|
|
|