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 |