Index: src/compiler/ast-graph-builder.cc |
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc |
index 629ea18679b1979a42ce09bd6bbc37439b310bfc..2e6dad8ada32fca463bc1b86da099e4989076c2c 100644 |
--- a/src/compiler/ast-graph-builder.cc |
+++ b/src/compiler/ast-graph-builder.cc |
@@ -632,6 +632,14 @@ static LhsKind DetermineLhsKind(Expression* expr) { |
} |
+// Gets the bailout id just before reading a variable proxy, but only for |
+// unallocated variables. |
+static BailoutId BeforeId(VariableProxy* proxy) { |
+ return proxy->var()->location() == Variable::UNALLOCATED ? proxy->BeforeId() |
+ : BailoutId::None(); |
+} |
+ |
+ |
static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) { |
#if DEBUG |
const AstRawString* name = scope->parameter(index)->raw_name(); |
@@ -1643,7 +1651,9 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { |
if (expr->scope() != NULL) { |
DCHECK_NOT_NULL(expr->class_variable_proxy()); |
Variable* var = expr->class_variable_proxy()->var(); |
- BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None()); |
+ FrameStateBeforeAndAfter states(this, BailoutId::None()); |
+ BuildVariableAssignment(states, var, literal, Token::INIT_CONST, |
+ BailoutId::None()); |
} |
ast_context()->ProduceValue(literal); |
@@ -1671,7 +1681,9 @@ void AstGraphBuilder::VisitConditional(Conditional* expr) { |
void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot()); |
- Node* value = BuildVariableLoad(expr->var(), expr->id(), pair); |
+ FrameStateBeforeAndAfter states(this, BeforeId(expr)); |
+ Node* value = BuildVariableLoad(states, expr->var(), expr->id(), pair, |
+ ast_context()->GetStateCombine()); |
ast_context()->ProduceValue(value); |
} |
@@ -1744,11 +1756,13 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
if (key->value()->IsInternalizedString()) { |
if (property->emit_store()) { |
VisitForValue(property->value()); |
+ FrameStateBeforeAndAfter states(this, property->value()->id()); |
Node* value = environment()->Pop(); |
Handle<Name> name = key->AsPropertyName(); |
Node* store = |
BuildNamedStore(literal, name, value, TypeFeedbackId::None()); |
- PrepareFrameState(store, key->id()); |
+ states.AddToNode(store, key->id(), |
+ OutputFrameStateCombine::Ignore()); |
BuildSetHomeObject(value, literal, property->value()); |
} else { |
VisitForEffect(property->value()); |
@@ -1945,34 +1959,32 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value, |
switch (assign_type) { |
case VARIABLE: { |
Variable* var = expr->AsVariableProxy()->var(); |
- BuildVariableAssignment(var, value, Token::ASSIGN, bailout_id); |
+ FrameStateBeforeAndAfter states(this, BailoutId::None()); |
+ BuildVariableAssignment(states, var, value, Token::ASSIGN, bailout_id); |
break; |
} |
case NAMED_PROPERTY: { |
environment()->Push(value); |
VisitForValue(property->obj()); |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
Node* object = environment()->Pop(); |
value = environment()->Pop(); |
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
Node* store = |
BuildNamedStore(object, name, value, TypeFeedbackId::None()); |
- PrepareFrameState(store, bailout_id); |
+ states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore()); |
break; |
} |
case KEYED_PROPERTY: { |
environment()->Push(value); |
VisitForValue(property->obj()); |
VisitForValue(property->key()); |
- { |
- // TODO(jarin) Provide a real frame state before. |
- FrameStateBeforeAndAfter states(this, BailoutId::None()); |
- Node* key = environment()->Pop(); |
- Node* object = environment()->Pop(); |
- value = environment()->Pop(); |
- Node* store = |
- BuildKeyedStore(object, key, value, TypeFeedbackId::None()); |
- states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore()); |
- } |
+ FrameStateBeforeAndAfter states(this, property->key()->id()); |
+ Node* key = environment()->Pop(); |
+ Node* object = environment()->Pop(); |
+ value = environment()->Pop(); |
+ Node* store = BuildKeyedStore(object, key, value, TypeFeedbackId::None()); |
+ states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore()); |
break; |
} |
} |
@@ -2018,7 +2030,10 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
VariableProxy* proxy = expr->target()->AsVariableProxy(); |
VectorSlotPair pair = |
CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
- old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair); |
+ FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
+ old_value = |
+ BuildVariableLoad(states, proxy->var(), expr->target()->id(), pair, |
+ OutputFrameStateCombine::Push()); |
break; |
} |
case NAMED_PROPERTY: { |
@@ -2026,10 +2041,11 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
VectorSlotPair pair = |
CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
old_value = |
BuildNamedLoad(object, name, pair, property->PropertyFeedbackId()); |
- PrepareFrameState(old_value, property->LoadId(), |
- OutputFrameStateCombine::Push()); |
+ states.AddToNode(old_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
break; |
} |
case KEYED_PROPERTY: { |
@@ -2037,10 +2053,11 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
Node* object = environment()->Peek(1); |
VectorSlotPair pair = |
CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
+ FrameStateBeforeAndAfter states(this, property->key()->id()); |
old_value = |
BuildKeyedLoad(object, key, pair, property->PropertyFeedbackId()); |
- PrepareFrameState(old_value, property->LoadId(), |
- OutputFrameStateCombine::Push()); |
+ states.AddToNode(old_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
break; |
} |
} |
@@ -2072,8 +2089,8 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
switch (assign_type) { |
case VARIABLE: { |
Variable* variable = expr->target()->AsVariableProxy()->var(); |
- BuildVariableAssignment(variable, value, expr->op(), expr->id(), |
- ast_context()->GetStateCombine()); |
+ BuildVariableAssignment(store_states, variable, value, expr->op(), |
+ expr->id(), ast_context()->GetStateCombine()); |
break; |
} |
case NAMED_PROPERTY: { |
@@ -2120,17 +2137,20 @@ void AstGraphBuilder::VisitProperty(Property* expr) { |
VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); |
if (expr->key()->IsPropertyName()) { |
VisitForValue(expr->obj()); |
+ FrameStateBeforeAndAfter states(this, expr->obj()->id()); |
Node* object = environment()->Pop(); |
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName(); |
value = BuildNamedLoad(object, name, pair, expr->PropertyFeedbackId()); |
+ states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
} else { |
VisitForValue(expr->obj()); |
VisitForValue(expr->key()); |
+ FrameStateBeforeAndAfter states(this, expr->key()->id()); |
Node* key = environment()->Pop(); |
Node* object = environment()->Pop(); |
value = BuildKeyedLoad(object, key, pair, expr->PropertyFeedbackId()); |
+ states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
} |
- PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
ast_context()->ProduceValue(value); |
} |
@@ -2149,8 +2169,10 @@ void AstGraphBuilder::VisitCall(Call* expr) { |
case Call::GLOBAL_CALL: { |
VariableProxy* proxy = callee->AsVariableProxy(); |
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
+ FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
callee_value = |
- BuildVariableLoad(proxy->var(), expr->expression()->id(), pair); |
+ BuildVariableLoad(states, proxy->var(), expr->expression()->id(), |
+ pair, OutputFrameStateCombine::Push()); |
receiver_value = jsgraph()->UndefinedConstant(); |
break; |
} |
@@ -2175,17 +2197,21 @@ void AstGraphBuilder::VisitCall(Call* expr) { |
VectorSlotPair pair = |
CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
if (property->key()->IsPropertyName()) { |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
callee_value = |
BuildNamedLoad(object, name, pair, property->PropertyFeedbackId()); |
+ states.AddToNode(callee_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
} else { |
VisitForValue(property->key()); |
+ FrameStateBeforeAndAfter states(this, property->key()->id()); |
Node* key = environment()->Pop(); |
callee_value = |
BuildKeyedLoad(object, key, pair, property->PropertyFeedbackId()); |
+ states.AddToNode(callee_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
} |
- PrepareFrameState(callee_value, property->LoadId(), |
- OutputFrameStateCombine::Push()); |
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, |
@@ -2295,12 +2321,12 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { |
CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; |
Node* receiver_value = BuildLoadBuiltinsObject(); |
VectorSlotPair pair = CreateVectorSlotPair(expr->CallRuntimeFeedbackSlot()); |
+ // TODO(jarin): bailout ids for runtime calls. |
+ FrameStateBeforeAndAfter states(this, BailoutId::None()); |
Node* callee_value = |
BuildNamedLoad(receiver_value, name, pair, expr->CallRuntimeFeedbackId()); |
- // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft |
- // refuses to optimize functions with jsruntime calls). |
- PrepareFrameState(callee_value, BailoutId::None(), |
- OutputFrameStateCombine::Push()); |
+ states.AddToNode(callee_value, BailoutId::None(), |
+ OutputFrameStateCombine::Push()); |
environment()->Push(callee_value); |
environment()->Push(receiver_value); |
@@ -2374,35 +2400,39 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { |
case VARIABLE: { |
VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
+ FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
old_value = |
- BuildVariableLoad(proxy->var(), expr->expression()->id(), pair); |
+ BuildVariableLoad(states, proxy->var(), expr->expression()->id(), |
+ pair, OutputFrameStateCombine::Push()); |
stack_depth = 0; |
break; |
} |
case NAMED_PROPERTY: { |
VisitForValue(property->obj()); |
+ FrameStateBeforeAndAfter states(this, property->obj()->id()); |
Node* object = environment()->Top(); |
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
VectorSlotPair pair = |
CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
old_value = |
BuildNamedLoad(object, name, pair, property->PropertyFeedbackId()); |
- PrepareFrameState(old_value, property->LoadId(), |
- OutputFrameStateCombine::Push()); |
+ states.AddToNode(old_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
stack_depth = 1; |
break; |
} |
case KEYED_PROPERTY: { |
VisitForValue(property->obj()); |
VisitForValue(property->key()); |
+ FrameStateBeforeAndAfter states(this, property->key()->id()); |
Node* key = environment()->Top(); |
Node* object = environment()->Peek(1); |
VectorSlotPair pair = |
CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
old_value = |
BuildKeyedLoad(object, key, pair, property->PropertyFeedbackId()); |
- PrepareFrameState(old_value, property->LoadId(), |
- OutputFrameStateCombine::Push()); |
+ states.AddToNode(old_value, property->LoadId(), |
+ OutputFrameStateCombine::Push()); |
stack_depth = 2; |
break; |
} |
@@ -2438,7 +2468,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { |
case VARIABLE: { |
Variable* variable = expr->expression()->AsVariableProxy()->var(); |
environment()->Push(value); |
- BuildVariableAssignment(variable, value, expr->op(), |
+ BuildVariableAssignment(store_states, variable, value, expr->op(), |
expr->AssignmentId()); |
environment()->Pop(); |
break; |
@@ -2449,7 +2479,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { |
Node* store = |
BuildNamedStore(object, name, value, expr->CountStoreFeedbackId()); |
environment()->Push(value); |
- PrepareFrameState(store, expr->AssignmentId()); |
+ store_states.AddToNode(store, expr->AssignmentId(), |
+ OutputFrameStateCombine::Ignore()); |
environment()->Pop(); |
break; |
} |
@@ -2639,8 +2670,10 @@ void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
// perform a non-contextual load in case the operand is a variable proxy. |
VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
- operand = BuildVariableLoad(proxy->var(), expr->expression()->id(), pair, |
- NOT_CONTEXTUAL); |
+ FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
+ operand = |
+ BuildVariableLoad(states, proxy->var(), expr->expression()->id(), pair, |
+ OutputFrameStateCombine::Push(), NOT_CONTEXTUAL); |
} else { |
VisitForValue(expr->expression()); |
operand = environment()->Pop(); |
@@ -2810,7 +2843,9 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { |
// Assign the object to the arguments variable. |
DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); |
// This should never lazy deopt, so it is fine to send invalid bailout id. |
- BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None()); |
+ FrameStateBeforeAndAfter states(this, BailoutId::None()); |
+ BuildVariableAssignment(states, arguments, object, Token::ASSIGN, |
+ BailoutId::None()); |
return object; |
} |
@@ -2826,7 +2861,9 @@ Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) { |
// Assign the object to the rest array |
DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); |
// This should never lazy deopt, so it is fine to send invalid bailout id. |
- BuildVariableAssignment(rest, object, Token::ASSIGN, BailoutId::None()); |
+ FrameStateBeforeAndAfter states(this, BailoutId::None()); |
+ BuildVariableAssignment(states, rest, object, Token::ASSIGN, |
+ BailoutId::None()); |
return object; |
} |
@@ -2875,9 +2912,11 @@ Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name, |
} |
-Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
+Node* AstGraphBuilder::BuildVariableLoad(FrameStateBeforeAndAfter& states, |
+ Variable* variable, |
BailoutId bailout_id, |
const VectorSlotPair& feedback, |
+ OutputFrameStateCombine combine, |
ContextualMode contextual_mode) { |
Node* the_hole = jsgraph()->TheHoleConstant(); |
VariableMode mode = variable->mode(); |
@@ -2888,7 +2927,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
Handle<Name> name = variable->name(); |
Node* node = BuildNamedLoad(global, name, feedback, |
TypeFeedbackId::None(), contextual_mode); |
- PrepareFrameState(node, bailout_id, OutputFrameStateCombine::Push()); |
+ states.AddToNode(node, bailout_id, combine); |
return node; |
} |
case Variable::PARAMETER: |
@@ -2951,9 +2990,9 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
} |
-Node* AstGraphBuilder::BuildVariableDelete( |
- Variable* variable, BailoutId bailout_id, |
- OutputFrameStateCombine state_combine) { |
+Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, |
+ BailoutId bailout_id, |
+ OutputFrameStateCombine combine) { |
switch (variable->location()) { |
case Variable::UNALLOCATED: { |
// Global var, const, or let variable. |
@@ -2961,7 +3000,7 @@ Node* AstGraphBuilder::BuildVariableDelete( |
Node* name = jsgraph()->Constant(variable->name()); |
const Operator* op = javascript()->DeleteProperty(language_mode()); |
Node* result = NewNode(op, global, name); |
- PrepareFrameState(result, bailout_id, state_combine); |
+ PrepareFrameState(result, bailout_id, combine); |
return result; |
} |
case Variable::PARAMETER: |
@@ -2975,7 +3014,7 @@ Node* AstGraphBuilder::BuildVariableDelete( |
const Operator* op = |
javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2); |
Node* result = NewNode(op, current_context(), name); |
- PrepareFrameState(result, bailout_id, state_combine); |
+ PrepareFrameState(result, bailout_id, combine); |
return result; |
} |
} |
@@ -2985,8 +3024,8 @@ Node* AstGraphBuilder::BuildVariableDelete( |
Node* AstGraphBuilder::BuildVariableAssignment( |
- Variable* variable, Node* value, Token::Value op, BailoutId bailout_id, |
- OutputFrameStateCombine combine) { |
+ FrameStateBeforeAndAfter& states, Variable* variable, Node* value, |
+ Token::Value op, BailoutId bailout_id, OutputFrameStateCombine combine) { |
Node* the_hole = jsgraph()->TheHoleConstant(); |
VariableMode mode = variable->mode(); |
switch (variable->location()) { |
@@ -2996,7 +3035,7 @@ Node* AstGraphBuilder::BuildVariableAssignment( |
Handle<Name> name = variable->name(); |
Node* store = |
BuildNamedStore(global, name, value, TypeFeedbackId::None()); |
- PrepareFrameState(store, bailout_id, combine); |
+ states.AddToNode(store, bailout_id, combine); |
return store; |
} |
case Variable::PARAMETER: |
@@ -3215,9 +3254,10 @@ Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object, |
Expression* expr) { |
if (!FunctionLiteral::NeedsHomeObject(expr)) return value; |
Handle<Name> name = isolate()->factory()->home_object_symbol(); |
+ FrameStateBeforeAndAfter states(this, BailoutId::None()); |
Node* store = |
BuildNamedStore(value, name, home_object, TypeFeedbackId::None()); |
- PrepareFrameState(store, BailoutId::None()); |
+ states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore()); |
return store; |
} |