Commit 29e15dad authored by titzer's avatar titzer Committed by Commit bot

[turbofan] Add FrameStates before all property accesses.

R=jarin@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1133303006

Cr-Commit-Position: refs/heads/master@{#28392}
parent e73594c7
...@@ -632,6 +632,14 @@ static LhsKind DetermineLhsKind(Expression* expr) { ...@@ -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) { static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) {
#if DEBUG #if DEBUG
const AstRawString* name = scope->parameter(index)->raw_name(); const AstRawString* name = scope->parameter(index)->raw_name();
...@@ -1643,7 +1651,9 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { ...@@ -1643,7 +1651,9 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
if (expr->scope() != NULL) { if (expr->scope() != NULL) {
DCHECK_NOT_NULL(expr->class_variable_proxy()); DCHECK_NOT_NULL(expr->class_variable_proxy());
Variable* var = expr->class_variable_proxy()->var(); 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); ast_context()->ProduceValue(literal);
...@@ -1671,7 +1681,9 @@ void AstGraphBuilder::VisitConditional(Conditional* expr) { ...@@ -1671,7 +1681,9 @@ void AstGraphBuilder::VisitConditional(Conditional* expr) {
void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot()); 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); ast_context()->ProduceValue(value);
} }
...@@ -1744,11 +1756,13 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1744,11 +1756,13 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
if (key->value()->IsInternalizedString()) { if (key->value()->IsInternalizedString()) {
if (property->emit_store()) { if (property->emit_store()) {
VisitForValue(property->value()); VisitForValue(property->value());
FrameStateBeforeAndAfter states(this, property->value()->id());
Node* value = environment()->Pop(); Node* value = environment()->Pop();
Handle<Name> name = key->AsPropertyName(); Handle<Name> name = key->AsPropertyName();
Node* store = Node* store =
BuildNamedStore(literal, name, value, TypeFeedbackId::None()); BuildNamedStore(literal, name, value, TypeFeedbackId::None());
PrepareFrameState(store, key->id()); states.AddToNode(store, key->id(),
OutputFrameStateCombine::Ignore());
BuildSetHomeObject(value, literal, property->value()); BuildSetHomeObject(value, literal, property->value());
} else { } else {
VisitForEffect(property->value()); VisitForEffect(property->value());
...@@ -1945,34 +1959,32 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value, ...@@ -1945,34 +1959,32 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
switch (assign_type) { switch (assign_type) {
case VARIABLE: { case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var(); 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; break;
} }
case NAMED_PROPERTY: { case NAMED_PROPERTY: {
environment()->Push(value); environment()->Push(value);
VisitForValue(property->obj()); VisitForValue(property->obj());
FrameStateBeforeAndAfter states(this, property->obj()->id());
Node* object = environment()->Pop(); Node* object = environment()->Pop();
value = environment()->Pop(); value = environment()->Pop();
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Node* store = Node* store =
BuildNamedStore(object, name, value, TypeFeedbackId::None()); BuildNamedStore(object, name, value, TypeFeedbackId::None());
PrepareFrameState(store, bailout_id); states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
break; break;
} }
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
environment()->Push(value); environment()->Push(value);
VisitForValue(property->obj()); VisitForValue(property->obj());
VisitForValue(property->key()); VisitForValue(property->key());
{ FrameStateBeforeAndAfter states(this, property->key()->id());
// TODO(jarin) Provide a real frame state before. Node* key = environment()->Pop();
FrameStateBeforeAndAfter states(this, BailoutId::None()); Node* object = environment()->Pop();
Node* key = environment()->Pop(); value = environment()->Pop();
Node* object = environment()->Pop(); Node* store = BuildKeyedStore(object, key, value, TypeFeedbackId::None());
value = environment()->Pop(); states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
Node* store =
BuildKeyedStore(object, key, value, TypeFeedbackId::None());
states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
}
break; break;
} }
} }
...@@ -2018,7 +2030,10 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { ...@@ -2018,7 +2030,10 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
VariableProxy* proxy = expr->target()->AsVariableProxy(); VariableProxy* proxy = expr->target()->AsVariableProxy();
VectorSlotPair pair = VectorSlotPair pair =
CreateVectorSlotPair(proxy->VariableFeedbackSlot()); 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; break;
} }
case NAMED_PROPERTY: { case NAMED_PROPERTY: {
...@@ -2026,10 +2041,11 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { ...@@ -2026,10 +2041,11 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
VectorSlotPair pair = VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot()); CreateVectorSlotPair(property->PropertyFeedbackSlot());
FrameStateBeforeAndAfter states(this, property->obj()->id());
old_value = old_value =
BuildNamedLoad(object, name, pair, property->PropertyFeedbackId()); BuildNamedLoad(object, name, pair, property->PropertyFeedbackId());
PrepareFrameState(old_value, property->LoadId(), states.AddToNode(old_value, property->LoadId(),
OutputFrameStateCombine::Push()); OutputFrameStateCombine::Push());
break; break;
} }
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
...@@ -2037,10 +2053,11 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { ...@@ -2037,10 +2053,11 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
Node* object = environment()->Peek(1); Node* object = environment()->Peek(1);
VectorSlotPair pair = VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot()); CreateVectorSlotPair(property->PropertyFeedbackSlot());
FrameStateBeforeAndAfter states(this, property->key()->id());
old_value = old_value =
BuildKeyedLoad(object, key, pair, property->PropertyFeedbackId()); BuildKeyedLoad(object, key, pair, property->PropertyFeedbackId());
PrepareFrameState(old_value, property->LoadId(), states.AddToNode(old_value, property->LoadId(),
OutputFrameStateCombine::Push()); OutputFrameStateCombine::Push());
break; break;
} }
} }
...@@ -2072,8 +2089,8 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { ...@@ -2072,8 +2089,8 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
switch (assign_type) { switch (assign_type) {
case VARIABLE: { case VARIABLE: {
Variable* variable = expr->target()->AsVariableProxy()->var(); Variable* variable = expr->target()->AsVariableProxy()->var();
BuildVariableAssignment(variable, value, expr->op(), expr->id(), BuildVariableAssignment(store_states, variable, value, expr->op(),
ast_context()->GetStateCombine()); expr->id(), ast_context()->GetStateCombine());
break; break;
} }
case NAMED_PROPERTY: { case NAMED_PROPERTY: {
...@@ -2120,17 +2137,20 @@ void AstGraphBuilder::VisitProperty(Property* expr) { ...@@ -2120,17 +2137,20 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
if (expr->key()->IsPropertyName()) { if (expr->key()->IsPropertyName()) {
VisitForValue(expr->obj()); VisitForValue(expr->obj());
FrameStateBeforeAndAfter states(this, expr->obj()->id());
Node* object = environment()->Pop(); Node* object = environment()->Pop();
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName(); Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
value = BuildNamedLoad(object, name, pair, expr->PropertyFeedbackId()); value = BuildNamedLoad(object, name, pair, expr->PropertyFeedbackId());
states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
} else { } else {
VisitForValue(expr->obj()); VisitForValue(expr->obj());
VisitForValue(expr->key()); VisitForValue(expr->key());
FrameStateBeforeAndAfter states(this, expr->key()->id());
Node* key = environment()->Pop(); Node* key = environment()->Pop();
Node* object = environment()->Pop(); Node* object = environment()->Pop();
value = BuildKeyedLoad(object, key, pair, expr->PropertyFeedbackId()); 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); ast_context()->ProduceValue(value);
} }
...@@ -2149,8 +2169,10 @@ void AstGraphBuilder::VisitCall(Call* expr) { ...@@ -2149,8 +2169,10 @@ void AstGraphBuilder::VisitCall(Call* expr) {
case Call::GLOBAL_CALL: { case Call::GLOBAL_CALL: {
VariableProxy* proxy = callee->AsVariableProxy(); VariableProxy* proxy = callee->AsVariableProxy();
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
FrameStateBeforeAndAfter states(this, BeforeId(proxy));
callee_value = callee_value =
BuildVariableLoad(proxy->var(), expr->expression()->id(), pair); BuildVariableLoad(states, proxy->var(), expr->expression()->id(),
pair, OutputFrameStateCombine::Push());
receiver_value = jsgraph()->UndefinedConstant(); receiver_value = jsgraph()->UndefinedConstant();
break; break;
} }
...@@ -2175,17 +2197,21 @@ void AstGraphBuilder::VisitCall(Call* expr) { ...@@ -2175,17 +2197,21 @@ void AstGraphBuilder::VisitCall(Call* expr) {
VectorSlotPair pair = VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot()); CreateVectorSlotPair(property->PropertyFeedbackSlot());
if (property->key()->IsPropertyName()) { if (property->key()->IsPropertyName()) {
FrameStateBeforeAndAfter states(this, property->obj()->id());
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
callee_value = callee_value =
BuildNamedLoad(object, name, pair, property->PropertyFeedbackId()); BuildNamedLoad(object, name, pair, property->PropertyFeedbackId());
states.AddToNode(callee_value, property->LoadId(),
OutputFrameStateCombine::Push());
} else { } else {
VisitForValue(property->key()); VisitForValue(property->key());
FrameStateBeforeAndAfter states(this, property->key()->id());
Node* key = environment()->Pop(); Node* key = environment()->Pop();
callee_value = callee_value =
BuildKeyedLoad(object, key, pair, property->PropertyFeedbackId()); 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(); receiver_value = environment()->Pop();
// Note that a PROPERTY_CALL requires the receiver to be wrapped into an // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
// object for sloppy callees. This could also be modeled explicitly here, // object for sloppy callees. This could also be modeled explicitly here,
...@@ -2295,12 +2321,12 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { ...@@ -2295,12 +2321,12 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
Node* receiver_value = BuildLoadBuiltinsObject(); Node* receiver_value = BuildLoadBuiltinsObject();
VectorSlotPair pair = CreateVectorSlotPair(expr->CallRuntimeFeedbackSlot()); VectorSlotPair pair = CreateVectorSlotPair(expr->CallRuntimeFeedbackSlot());
// TODO(jarin): bailout ids for runtime calls.
FrameStateBeforeAndAfter states(this, BailoutId::None());
Node* callee_value = Node* callee_value =
BuildNamedLoad(receiver_value, name, pair, expr->CallRuntimeFeedbackId()); BuildNamedLoad(receiver_value, name, pair, expr->CallRuntimeFeedbackId());
// TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft states.AddToNode(callee_value, BailoutId::None(),
// refuses to optimize functions with jsruntime calls). OutputFrameStateCombine::Push());
PrepareFrameState(callee_value, BailoutId::None(),
OutputFrameStateCombine::Push());
environment()->Push(callee_value); environment()->Push(callee_value);
environment()->Push(receiver_value); environment()->Push(receiver_value);
...@@ -2374,35 +2400,39 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { ...@@ -2374,35 +2400,39 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
case VARIABLE: { case VARIABLE: {
VariableProxy* proxy = expr->expression()->AsVariableProxy(); VariableProxy* proxy = expr->expression()->AsVariableProxy();
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
FrameStateBeforeAndAfter states(this, BeforeId(proxy));
old_value = old_value =
BuildVariableLoad(proxy->var(), expr->expression()->id(), pair); BuildVariableLoad(states, proxy->var(), expr->expression()->id(),
pair, OutputFrameStateCombine::Push());
stack_depth = 0; stack_depth = 0;
break; break;
} }
case NAMED_PROPERTY: { case NAMED_PROPERTY: {
VisitForValue(property->obj()); VisitForValue(property->obj());
FrameStateBeforeAndAfter states(this, property->obj()->id());
Node* object = environment()->Top(); Node* object = environment()->Top();
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
VectorSlotPair pair = VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot()); CreateVectorSlotPair(property->PropertyFeedbackSlot());
old_value = old_value =
BuildNamedLoad(object, name, pair, property->PropertyFeedbackId()); BuildNamedLoad(object, name, pair, property->PropertyFeedbackId());
PrepareFrameState(old_value, property->LoadId(), states.AddToNode(old_value, property->LoadId(),
OutputFrameStateCombine::Push()); OutputFrameStateCombine::Push());
stack_depth = 1; stack_depth = 1;
break; break;
} }
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
VisitForValue(property->obj()); VisitForValue(property->obj());
VisitForValue(property->key()); VisitForValue(property->key());
FrameStateBeforeAndAfter states(this, property->key()->id());
Node* key = environment()->Top(); Node* key = environment()->Top();
Node* object = environment()->Peek(1); Node* object = environment()->Peek(1);
VectorSlotPair pair = VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot()); CreateVectorSlotPair(property->PropertyFeedbackSlot());
old_value = old_value =
BuildKeyedLoad(object, key, pair, property->PropertyFeedbackId()); BuildKeyedLoad(object, key, pair, property->PropertyFeedbackId());
PrepareFrameState(old_value, property->LoadId(), states.AddToNode(old_value, property->LoadId(),
OutputFrameStateCombine::Push()); OutputFrameStateCombine::Push());
stack_depth = 2; stack_depth = 2;
break; break;
} }
...@@ -2438,7 +2468,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { ...@@ -2438,7 +2468,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
case VARIABLE: { case VARIABLE: {
Variable* variable = expr->expression()->AsVariableProxy()->var(); Variable* variable = expr->expression()->AsVariableProxy()->var();
environment()->Push(value); environment()->Push(value);
BuildVariableAssignment(variable, value, expr->op(), BuildVariableAssignment(store_states, variable, value, expr->op(),
expr->AssignmentId()); expr->AssignmentId());
environment()->Pop(); environment()->Pop();
break; break;
...@@ -2449,7 +2479,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { ...@@ -2449,7 +2479,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
Node* store = Node* store =
BuildNamedStore(object, name, value, expr->CountStoreFeedbackId()); BuildNamedStore(object, name, value, expr->CountStoreFeedbackId());
environment()->Push(value); environment()->Push(value);
PrepareFrameState(store, expr->AssignmentId()); store_states.AddToNode(store, expr->AssignmentId(),
OutputFrameStateCombine::Ignore());
environment()->Pop(); environment()->Pop();
break; break;
} }
...@@ -2639,8 +2670,10 @@ void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { ...@@ -2639,8 +2670,10 @@ void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
// perform a non-contextual load in case the operand is a variable proxy. // perform a non-contextual load in case the operand is a variable proxy.
VariableProxy* proxy = expr->expression()->AsVariableProxy(); VariableProxy* proxy = expr->expression()->AsVariableProxy();
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
operand = BuildVariableLoad(proxy->var(), expr->expression()->id(), pair, FrameStateBeforeAndAfter states(this, BeforeId(proxy));
NOT_CONTEXTUAL); operand =
BuildVariableLoad(states, proxy->var(), expr->expression()->id(), pair,
OutputFrameStateCombine::Push(), NOT_CONTEXTUAL);
} else { } else {
VisitForValue(expr->expression()); VisitForValue(expr->expression());
operand = environment()->Pop(); operand = environment()->Pop();
...@@ -2810,7 +2843,9 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { ...@@ -2810,7 +2843,9 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
// Assign the object to the arguments variable. // Assign the object to the arguments variable.
DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
// This should never lazy deopt, so it is fine to send invalid bailout id. // 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; return object;
} }
...@@ -2826,7 +2861,9 @@ Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) { ...@@ -2826,7 +2861,9 @@ Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
// Assign the object to the rest array // Assign the object to the rest array
DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
// This should never lazy deopt, so it is fine to send invalid bailout id. // 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; return object;
} }
...@@ -2875,9 +2912,11 @@ Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name, ...@@ -2875,9 +2912,11 @@ Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
} }
Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, Node* AstGraphBuilder::BuildVariableLoad(FrameStateBeforeAndAfter& states,
Variable* variable,
BailoutId bailout_id, BailoutId bailout_id,
const VectorSlotPair& feedback, const VectorSlotPair& feedback,
OutputFrameStateCombine combine,
ContextualMode contextual_mode) { ContextualMode contextual_mode) {
Node* the_hole = jsgraph()->TheHoleConstant(); Node* the_hole = jsgraph()->TheHoleConstant();
VariableMode mode = variable->mode(); VariableMode mode = variable->mode();
...@@ -2888,7 +2927,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, ...@@ -2888,7 +2927,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
Handle<Name> name = variable->name(); Handle<Name> name = variable->name();
Node* node = BuildNamedLoad(global, name, feedback, Node* node = BuildNamedLoad(global, name, feedback,
TypeFeedbackId::None(), contextual_mode); TypeFeedbackId::None(), contextual_mode);
PrepareFrameState(node, bailout_id, OutputFrameStateCombine::Push()); states.AddToNode(node, bailout_id, combine);
return node; return node;
} }
case Variable::PARAMETER: case Variable::PARAMETER:
...@@ -2951,9 +2990,9 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, ...@@ -2951,9 +2990,9 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
} }
Node* AstGraphBuilder::BuildVariableDelete( Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
Variable* variable, BailoutId bailout_id, BailoutId bailout_id,
OutputFrameStateCombine state_combine) { OutputFrameStateCombine combine) {
switch (variable->location()) { switch (variable->location()) {
case Variable::UNALLOCATED: { case Variable::UNALLOCATED: {
// Global var, const, or let variable. // Global var, const, or let variable.
...@@ -2961,7 +3000,7 @@ Node* AstGraphBuilder::BuildVariableDelete( ...@@ -2961,7 +3000,7 @@ Node* AstGraphBuilder::BuildVariableDelete(
Node* name = jsgraph()->Constant(variable->name()); Node* name = jsgraph()->Constant(variable->name());
const Operator* op = javascript()->DeleteProperty(language_mode()); const Operator* op = javascript()->DeleteProperty(language_mode());
Node* result = NewNode(op, global, name); Node* result = NewNode(op, global, name);
PrepareFrameState(result, bailout_id, state_combine); PrepareFrameState(result, bailout_id, combine);
return result; return result;
} }
case Variable::PARAMETER: case Variable::PARAMETER:
...@@ -2975,7 +3014,7 @@ Node* AstGraphBuilder::BuildVariableDelete( ...@@ -2975,7 +3014,7 @@ Node* AstGraphBuilder::BuildVariableDelete(
const Operator* op = const Operator* op =
javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2); javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
Node* result = NewNode(op, current_context(), name); Node* result = NewNode(op, current_context(), name);
PrepareFrameState(result, bailout_id, state_combine); PrepareFrameState(result, bailout_id, combine);
return result; return result;
} }
} }
...@@ -2985,8 +3024,8 @@ Node* AstGraphBuilder::BuildVariableDelete( ...@@ -2985,8 +3024,8 @@ Node* AstGraphBuilder::BuildVariableDelete(
Node* AstGraphBuilder::BuildVariableAssignment( Node* AstGraphBuilder::BuildVariableAssignment(
Variable* variable, Node* value, Token::Value op, BailoutId bailout_id, FrameStateBeforeAndAfter& states, Variable* variable, Node* value,
OutputFrameStateCombine combine) { Token::Value op, BailoutId bailout_id, OutputFrameStateCombine combine) {
Node* the_hole = jsgraph()->TheHoleConstant(); Node* the_hole = jsgraph()->TheHoleConstant();
VariableMode mode = variable->mode(); VariableMode mode = variable->mode();
switch (variable->location()) { switch (variable->location()) {
...@@ -2996,7 +3035,7 @@ Node* AstGraphBuilder::BuildVariableAssignment( ...@@ -2996,7 +3035,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
Handle<Name> name = variable->name(); Handle<Name> name = variable->name();
Node* store = Node* store =
BuildNamedStore(global, name, value, TypeFeedbackId::None()); BuildNamedStore(global, name, value, TypeFeedbackId::None());
PrepareFrameState(store, bailout_id, combine); states.AddToNode(store, bailout_id, combine);
return store; return store;
} }
case Variable::PARAMETER: case Variable::PARAMETER:
...@@ -3215,9 +3254,10 @@ Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object, ...@@ -3215,9 +3254,10 @@ Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
Expression* expr) { Expression* expr) {
if (!FunctionLiteral::NeedsHomeObject(expr)) return value; if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
Handle<Name> name = isolate()->factory()->home_object_symbol(); Handle<Name> name = isolate()->factory()->home_object_symbol();
FrameStateBeforeAndAfter states(this, BailoutId::None());
Node* store = Node* store =
BuildNamedStore(value, name, home_object, TypeFeedbackId::None()); BuildNamedStore(value, name, home_object, TypeFeedbackId::None());
PrepareFrameState(store, BailoutId::None()); states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
return store; return store;
} }
......
...@@ -255,14 +255,15 @@ class AstGraphBuilder : public AstVisitor { ...@@ -255,14 +255,15 @@ class AstGraphBuilder : public AstVisitor {
Node* BuildRestArgumentsArray(Variable* rest, int index); Node* BuildRestArgumentsArray(Variable* rest, int index);
// Builders for variable load and assignment. // Builders for variable load and assignment.
Node* BuildVariableAssignment(Variable* var, Node* value, Token::Value op, Node* BuildVariableAssignment(
BailoutId bailout_id, FrameStateBeforeAndAfter& states, Variable* var, Node* value,
OutputFrameStateCombine state_combine = Token::Value op, BailoutId bailout_id,
OutputFrameStateCombine::Ignore()); OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore());
Node* BuildVariableDelete(Variable* var, BailoutId bailout_id, Node* BuildVariableDelete(Variable* var, BailoutId bailout_id,
OutputFrameStateCombine state_combine); OutputFrameStateCombine combine);
Node* BuildVariableLoad(Variable* var, BailoutId bailout_id, Node* BuildVariableLoad(FrameStateBeforeAndAfter& states, Variable* var,
const VectorSlotPair& feedback, BailoutId bailout_id, const VectorSlotPair& feedback,
OutputFrameStateCombine combine,
ContextualMode mode = CONTEXTUAL); ContextualMode mode = CONTEXTUAL);
// Builders for property loads and stores. // Builders for property loads and stores.
......
...@@ -17,6 +17,19 @@ namespace v8 { ...@@ -17,6 +17,19 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
static CallDescriptor::Flags AdjustFrameStatesForCall(Node* node) {
int count = OperatorProperties::GetFrameStateInputCount(node->op());
if (count > 1) {
int index = NodeProperties::FirstFrameStateIndex(node) + 1;
do {
node->RemoveInput(index);
} while (--count > 1);
}
return count > 0 ? CallDescriptor::kNeedsFrameState
: CallDescriptor::kNoFlags;
}
JSGenericLowering::JSGenericLowering(bool is_typing_enabled, JSGraph* jsgraph) JSGenericLowering::JSGenericLowering(bool is_typing_enabled, JSGraph* jsgraph)
: is_typing_enabled_(is_typing_enabled), jsgraph_(jsgraph) {} : is_typing_enabled_(is_typing_enabled), jsgraph_(jsgraph) {}
...@@ -52,11 +65,13 @@ Reduction JSGenericLowering::Reduce(Node* node) { ...@@ -52,11 +65,13 @@ Reduction JSGenericLowering::Reduce(Node* node) {
} }
#define REPLACE_BINARY_OP_IC_CALL(op, token) \ #define REPLACE_BINARY_OP_IC_CALL(op, token) \
void JSGenericLowering::Lower##op(Node* node) { \ void JSGenericLowering::Lower##op(Node* node) { \
ReplaceWithStubCall(node, CodeFactory::BinaryOpIC(isolate(), token, \ CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); \
OpParameter<LanguageMode>(node)), \ ReplaceWithStubCall( \
CallDescriptor::kPatchableCallSiteWithNop); \ node, CodeFactory::BinaryOpIC(isolate(), token, \
OpParameter<LanguageMode>(node)), \
CallDescriptor::kPatchableCallSiteWithNop | flags); \
} }
REPLACE_BINARY_OP_IC_CALL(JSBitwiseOr, Token::BIT_OR) REPLACE_BINARY_OP_IC_CALL(JSBitwiseOr, Token::BIT_OR)
REPLACE_BINARY_OP_IC_CALL(JSBitwiseXor, Token::BIT_XOR) REPLACE_BINARY_OP_IC_CALL(JSBitwiseXor, Token::BIT_XOR)
...@@ -118,10 +133,6 @@ static CallDescriptor::Flags FlagsForNode(Node* node) { ...@@ -118,10 +133,6 @@ static CallDescriptor::Flags FlagsForNode(Node* node) {
void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) { void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) {
Callable callable = Callable callable =
CodeFactory::CompareIC(isolate(), token, OpParameter<LanguageMode>(node)); CodeFactory::CompareIC(isolate(), token, OpParameter<LanguageMode>(node));
CallDescriptor* desc_compare = Linkage::GetStubCallDescriptor(
isolate(), zone(), callable.descriptor(), 0,
CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node),
Operator::kNoProperties, kMachIntPtr);
// Create a new call node asking a CompareIC for help. // Create a new call node asking a CompareIC for help.
NodeVector inputs(zone()); NodeVector inputs(zone());
...@@ -141,6 +152,10 @@ void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) { ...@@ -141,6 +152,10 @@ void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) {
inputs.push_back(NodeProperties::GetEffectInput(node)); inputs.push_back(NodeProperties::GetEffectInput(node));
inputs.push_back(NodeProperties::GetControlInput(node)); inputs.push_back(NodeProperties::GetControlInput(node));
} }
CallDescriptor* desc_compare = Linkage::GetStubCallDescriptor(
isolate(), zone(), callable.descriptor(), 0,
CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node),
Operator::kNoProperties, kMachIntPtr);
Node* compare = Node* compare =
graph()->NewNode(common()->Call(desc_compare), graph()->NewNode(common()->Call(desc_compare),
static_cast<int>(inputs.size()), &inputs.front()); static_cast<int>(inputs.size()), &inputs.front());
...@@ -194,53 +209,64 @@ void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) { ...@@ -194,53 +209,64 @@ void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) {
void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
CallDescriptor::Flags flags) { CallDescriptor::Flags flags) {
Operator::Properties properties = node->op()->properties(); const Operator* old_op = node->op();
flags |= FlagsForNode(node); Operator::Properties properties = old_op->properties();
CallDescriptor* desc = Linkage::GetStubCallDescriptor( CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), zone(), callable.descriptor(), 0, flags, properties); isolate(), zone(), callable.descriptor(), 0, flags, properties);
const Operator* new_op = common()->Call(desc); const Operator* new_op = common()->Call(desc);
// Take care of frame states.
int old_frame_state_count =
OperatorProperties::GetFrameStateInputCount(node->op());
int new_frame_state_count =
(flags & CallDescriptor::kNeedsFrameState) ? 1 : 0;
DCHECK_GE(old_frame_state_count, new_frame_state_count);
// If there are extra frame states, get rid of them.
for (int i = new_frame_state_count; i < old_frame_state_count; i++) {
node->RemoveInput(NodeProperties::FirstFrameStateIndex(node) +
new_frame_state_count);
}
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->set_op(new_op); node->set_op(new_op);
#if 0 && DEBUG
// Check for at most one framestate and that it's at the right position.
int where = -1;
for (int index = 0; index < node->InputCount(); index++) {
if (node->InputAt(index)->opcode() == IrOpcode::kFrameState) {
if (where >= 0) {
V8_Fatal(__FILE__, __LINE__,
"node #%d:%s already has a framestate at index %d",
node->id(), node->op()->mnemonic(), where);
}
where = index;
DCHECK_EQ(NodeProperties::FirstFrameStateIndex(node), where);
DCHECK(flags & CallDescriptor::kNeedsFrameState);
}
}
if (flags & CallDescriptor::kNeedsFrameState) {
DCHECK_GE(where, 0); // should have found a frame state.
}
#endif
} }
void JSGenericLowering::ReplaceWithBuiltinCall(Node* node, void JSGenericLowering::ReplaceWithBuiltinCall(Node* node,
Builtins::JavaScript id, Builtins::JavaScript id,
int nargs) { int nargs) {
Node* context_input = NodeProperties::GetContextInput(node);
Node* effect_input = NodeProperties::GetEffectInput(node);
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Operator::Properties properties = node->op()->properties(); Operator::Properties properties = node->op()->properties();
Callable callable = Callable callable =
CodeFactory::CallFunction(isolate(), nargs - 1, NO_CALL_FUNCTION_FLAGS); CodeFactory::CallFunction(isolate(), nargs - 1, NO_CALL_FUNCTION_FLAGS);
CallDescriptor* desc = CallDescriptor* desc = Linkage::GetStubCallDescriptor(
Linkage::GetStubCallDescriptor(isolate(), zone(), callable.descriptor(), isolate(), zone(), callable.descriptor(), nargs, flags, properties);
nargs, FlagsForNode(node), properties); Node* global_object =
Node* global_object = graph()->NewNode( graph()->NewNode(machine()->Load(kMachAnyTagged), context_input,
machine()->Load(kMachAnyTagged), NodeProperties::GetContextInput(node), jsgraph()->IntPtrConstant(
jsgraph()->IntPtrConstant( Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)),
Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), effect_input, graph()->start());
NodeProperties::GetEffectInput(node), graph()->start());
Node* builtins_object = graph()->NewNode( Node* builtins_object = graph()->NewNode(
machine()->Load(kMachAnyTagged), global_object, machine()->Load(kMachAnyTagged), global_object,
jsgraph()->IntPtrConstant(GlobalObject::kBuiltinsOffset - kHeapObjectTag), jsgraph()->IntPtrConstant(GlobalObject::kBuiltinsOffset - kHeapObjectTag),
NodeProperties::GetEffectInput(node), graph()->start()); effect_input, graph()->start());
Node* function = graph()->NewNode( Node* function = graph()->NewNode(
machine()->Load(kMachAnyTagged), builtins_object, machine()->Load(kMachAnyTagged), builtins_object,
jsgraph()->IntPtrConstant(JSBuiltinsObject::OffsetOfFunctionWithId(id) - jsgraph()->IntPtrConstant(JSBuiltinsObject::OffsetOfFunctionWithId(id) -
kHeapObjectTag), kHeapObjectTag),
NodeProperties::GetEffectInput(node), graph()->start()); effect_input, graph()->start());
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->InsertInput(zone(), 1, function); node->InsertInput(zone(), 1, function);
...@@ -268,26 +294,32 @@ void JSGenericLowering::ReplaceWithRuntimeCall(Node* node, ...@@ -268,26 +294,32 @@ void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
void JSGenericLowering::LowerJSUnaryNot(Node* node) { void JSGenericLowering::LowerJSUnaryNot(Node* node) {
Callable callable = CodeFactory::ToBoolean( Callable callable = CodeFactory::ToBoolean(
isolate(), ToBooleanStub::RESULT_AS_INVERSE_ODDBALL); isolate(), ToBooleanStub::RESULT_AS_INVERSE_ODDBALL);
ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
ReplaceWithStubCall(node, callable,
CallDescriptor::kPatchableCallSite | flags);
} }
void JSGenericLowering::LowerJSTypeOf(Node* node) { void JSGenericLowering::LowerJSTypeOf(Node* node) {
Callable callable = CodeFactory::Typeof(isolate()); Callable callable = CodeFactory::Typeof(isolate());
ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags); CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
ReplaceWithStubCall(node, callable, flags);
} }
void JSGenericLowering::LowerJSToBoolean(Node* node) { void JSGenericLowering::LowerJSToBoolean(Node* node) {
Callable callable = Callable callable =
CodeFactory::ToBoolean(isolate(), ToBooleanStub::RESULT_AS_ODDBALL); CodeFactory::ToBoolean(isolate(), ToBooleanStub::RESULT_AS_ODDBALL);
ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
ReplaceWithStubCall(node, callable,
CallDescriptor::kPatchableCallSite | flags);
} }
void JSGenericLowering::LowerJSToNumber(Node* node) { void JSGenericLowering::LowerJSToNumber(Node* node) {
Callable callable = CodeFactory::ToNumber(isolate()); Callable callable = CodeFactory::ToNumber(isolate());
ReplaceWithStubCall(node, callable, FlagsForNode(node)); CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
ReplaceWithStubCall(node, callable, flags);
} }
...@@ -307,6 +339,7 @@ void JSGenericLowering::LowerJSToObject(Node* node) { ...@@ -307,6 +339,7 @@ void JSGenericLowering::LowerJSToObject(Node* node) {
void JSGenericLowering::LowerJSLoadProperty(Node* node) { void JSGenericLowering::LowerJSLoadProperty(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
const LoadPropertyParameters& p = LoadPropertyParametersOf(node->op()); const LoadPropertyParameters& p = LoadPropertyParametersOf(node->op());
Callable callable = Callable callable =
CodeFactory::KeyedLoadICInOptimizedCode(isolate(), UNINITIALIZED); CodeFactory::KeyedLoadICInOptimizedCode(isolate(), UNINITIALIZED);
...@@ -315,11 +348,13 @@ void JSGenericLowering::LowerJSLoadProperty(Node* node) { ...@@ -315,11 +348,13 @@ void JSGenericLowering::LowerJSLoadProperty(Node* node) {
node->InsertInput(zone(), 3, node->InsertInput(zone(), 3,
jsgraph()->HeapConstant(p.feedback().vector())); jsgraph()->HeapConstant(p.feedback().vector()));
} }
ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); ReplaceWithStubCall(node, callable,
CallDescriptor::kPatchableCallSite | flags);
} }
void JSGenericLowering::LowerJSLoadNamed(Node* node) { void JSGenericLowering::LowerJSLoadNamed(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
const LoadNamedParameters& p = LoadNamedParametersOf(node->op()); const LoadNamedParameters& p = LoadNamedParametersOf(node->op());
Callable callable = Callable callable =
p.load_ic() == NAMED p.load_ic() == NAMED
...@@ -332,26 +367,31 @@ void JSGenericLowering::LowerJSLoadNamed(Node* node) { ...@@ -332,26 +367,31 @@ void JSGenericLowering::LowerJSLoadNamed(Node* node) {
node->InsertInput(zone(), 3, node->InsertInput(zone(), 3,
jsgraph()->HeapConstant(p.feedback().vector())); jsgraph()->HeapConstant(p.feedback().vector()));
} }
ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); ReplaceWithStubCall(node, callable,
CallDescriptor::kPatchableCallSite | flags);
} }
void JSGenericLowering::LowerJSStoreProperty(Node* node) { void JSGenericLowering::LowerJSStoreProperty(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
LanguageMode language_mode = OpParameter<LanguageMode>(node); LanguageMode language_mode = OpParameter<LanguageMode>(node);
Callable callable = CodeFactory::KeyedStoreICInOptimizedCode( Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
isolate(), language_mode, UNINITIALIZED); isolate(), language_mode, UNINITIALIZED);
ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); ReplaceWithStubCall(node, callable,
CallDescriptor::kPatchableCallSite | flags);
} }
void JSGenericLowering::LowerJSStoreNamed(Node* node) { void JSGenericLowering::LowerJSStoreNamed(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
const StoreNamedParameters& p = StoreNamedParametersOf(node->op()); const StoreNamedParameters& p = StoreNamedParametersOf(node->op());
Callable callable = p.store_ic() == NAMED Callable callable = p.store_ic() == NAMED
? CodeFactory::StoreIC(isolate(), p.language_mode()) ? CodeFactory::StoreIC(isolate(), p.language_mode())
: CodeFactory::KeyedStoreICInOptimizedCode( : CodeFactory::KeyedStoreICInOptimizedCode(
isolate(), p.language_mode(), UNINITIALIZED); isolate(), p.language_mode(), UNINITIALIZED);
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name())); node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); ReplaceWithStubCall(node, callable,
CallDescriptor::kPatchableCallSite | flags);
} }
...@@ -373,8 +413,9 @@ void JSGenericLowering::LowerJSInstanceOf(Node* node) { ...@@ -373,8 +413,9 @@ void JSGenericLowering::LowerJSInstanceOf(Node* node) {
InstanceofStub::kArgsInRegisters); InstanceofStub::kArgsInRegisters);
InstanceofStub stub(isolate(), flags); InstanceofStub stub(isolate(), flags);
CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(isolate(), zone(), d, 0, CallDescriptor::Flags desc_flags = AdjustFrameStatesForCall(node);
FlagsForNode(node)); CallDescriptor* desc =
Linkage::GetStubCallDescriptor(isolate(), zone(), d, 0, desc_flags);
Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); Node* stub_code = jsgraph()->HeapConstant(stub.GetCode());
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->set_op(common()->Call(desc)); node->set_op(common()->Call(desc));
...@@ -451,8 +492,9 @@ void JSGenericLowering::LowerJSCallConstruct(Node* node) { ...@@ -451,8 +492,9 @@ void JSGenericLowering::LowerJSCallConstruct(Node* node) {
int arity = OpParameter<int>(node); int arity = OpParameter<int>(node);
CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
CallDescriptor* desc = Linkage::GetStubCallDescriptor( CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
isolate(), zone(), d, arity, FlagsForNode(node)); CallDescriptor* desc =
Linkage::GetStubCallDescriptor(isolate(), zone(), d, arity, flags);
Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); Node* stub_code = jsgraph()->HeapConstant(stub.GetCode());
Node* construct = NodeProperties::GetValueInput(node, 0); Node* construct = NodeProperties::GetValueInput(node, 0);
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
...@@ -513,9 +555,9 @@ void JSGenericLowering::LowerJSCallFunction(Node* node) { ...@@ -513,9 +555,9 @@ void JSGenericLowering::LowerJSCallFunction(Node* node) {
int arg_count = static_cast<int>(p.arity() - 2); int arg_count = static_cast<int>(p.arity() - 2);
CallFunctionStub stub(isolate(), arg_count, p.flags()); CallFunctionStub stub(isolate(), arg_count, p.flags());
CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
CallDescriptor* desc = Linkage::GetStubCallDescriptor( CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), zone(), d, static_cast<int>(p.arity() - 1), isolate(), zone(), d, static_cast<int>(p.arity() - 1), flags);
FlagsForNode(node));
Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); Node* stub_code = jsgraph()->HeapConstant(stub.GetCode());
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->set_op(common()->Call(desc)); node->set_op(common()->Call(desc));
......
...@@ -61,9 +61,6 @@ Reduction JSTypeFeedbackSpecializer::Reduce(Node* node) { ...@@ -61,9 +61,6 @@ Reduction JSTypeFeedbackSpecializer::Reduce(Node* node) {
// StoreProperty(o, "constant", v) => StoreNamed["constant"](o, v). // StoreProperty(o, "constant", v) => StoreNamed["constant"](o, v).
Unique<Name> name = match.Value(); Unique<Name> name = match.Value();
LanguageMode language_mode = OpParameter<LanguageMode>(node); LanguageMode language_mode = OpParameter<LanguageMode>(node);
// StoreProperty has 2 frame state inputs, but StoreNamed only 1.
DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op()));
node->RemoveInput(NodeProperties::FirstFrameStateIndex(node) + 1);
node->set_op( node->set_op(
jsgraph()->javascript()->StoreNamed(language_mode, name, KEYED)); jsgraph()->javascript()->StoreNamed(language_mode, name, KEYED));
node->RemoveInput(1); node->RemoveInput(1);
......
...@@ -59,17 +59,14 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) { ...@@ -59,17 +59,14 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
// Misc operations // Misc operations
case IrOpcode::kJSStackCheck: case IrOpcode::kJSStackCheck:
case IrOpcode::kJSDeleteProperty:
return 1;
// Properties // We record the frame state immediately before and immediately after
// every property access.
case IrOpcode::kJSLoadNamed: case IrOpcode::kJSLoadNamed:
case IrOpcode::kJSStoreNamed: case IrOpcode::kJSStoreNamed:
case IrOpcode::kJSLoadProperty: case IrOpcode::kJSLoadProperty:
case IrOpcode::kJSDeleteProperty:
return 1;
// StoreProperty provides a second frame state just before
// the operation. This is used to lazy-deoptimize a to-number
// conversion for typed arrays.
case IrOpcode::kJSStoreProperty: case IrOpcode::kJSStoreProperty:
return 2; return 2;
......
...@@ -80,10 +80,13 @@ class JSTypeFeedbackTest : public TypedGraphTest { ...@@ -80,10 +80,13 @@ class JSTypeFeedbackTest : public TypedGraphTest {
Unique<Name> name = Unique<Name>::CreateUninitialized( Unique<Name> name = Unique<Name>::CreateUninitialized(
isolate()->factory()->NewStringFromAsciiChecked(string)); isolate()->factory()->NewStringFromAsciiChecked(string));
Node* load = graph()->NewNode(javascript()->LoadNamed(name, feedback), const Operator* op = javascript()->LoadNamed(name, feedback);
global, context); Node* load = graph()->NewNode(op, global, context);
if (FLAG_turbo_deoptimization) { if (FLAG_turbo_deoptimization) {
load->AppendInput(zone(), EmptyFrameState()); for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(op);
i++) {
load->AppendInput(zone(), EmptyFrameState());
}
} }
load->AppendInput(zone(), effect); load->AppendInput(zone(), effect);
load->AppendInput(zone(), control); load->AppendInput(zone(), control);
......
...@@ -659,9 +659,9 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) { ...@@ -659,9 +659,9 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* effect = graph()->start(); Node* effect = graph()->start();
Node* control = graph()->start(); Node* control = graph()->start();
Reduction r = Reduction r = Reduce(graph()->NewNode(javascript()->LoadProperty(feedback),
Reduce(graph()->NewNode(javascript()->LoadProperty(feedback), base, key, base, key, context, EmptyFrameState(),
context, EmptyFrameState(), effect, control)); EmptyFrameState(), effect, control));
Matcher<Node*> offset_matcher = Matcher<Node*> offset_matcher =
element_size == 1 element_size == 1
...@@ -700,9 +700,9 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) { ...@@ -700,9 +700,9 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* effect = graph()->start(); Node* effect = graph()->start();
Node* control = graph()->start(); Node* control = graph()->start();
Reduction r = Reduction r = Reduce(graph()->NewNode(javascript()->LoadProperty(feedback),
Reduce(graph()->NewNode(javascript()->LoadProperty(feedback), base, key, base, key, context, EmptyFrameState(),
context, EmptyFrameState(), effect, control)); EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT( EXPECT_THAT(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment