Vector ICs: Turbofan vector store ic support
Turbofan needs to pass vector slots around for named and keyed stores. Also, the CL addresses a missing slot for ClassLiterals. BUG= Review URL: https://codereview.chromium.org/1178363002 Cr-Commit-Position: refs/heads/master@{#29173}
This commit is contained in:
parent
ed0bd59440
commit
17c8ffeaa3
@ -2550,7 +2550,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
|
||||||
|
int* used_store_slots) {
|
||||||
// Constructor is in r0.
|
// Constructor is in r0.
|
||||||
DCHECK(lit != NULL);
|
DCHECK(lit != NULL);
|
||||||
__ push(r0);
|
__ push(r0);
|
||||||
@ -2562,10 +2563,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset));
|
FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset));
|
||||||
__ push(scratch);
|
__ push(scratch);
|
||||||
|
|
||||||
// store_slot_index points to the vector IC slot for the next store IC used.
|
|
||||||
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
|
|
||||||
// and must be updated if the number of store ICs emitted here changes.
|
|
||||||
int store_slot_index = 0;
|
|
||||||
for (int i = 0; i < lit->properties()->length(); i++) {
|
for (int i = 0; i < lit->properties()->length(); i++) {
|
||||||
ObjectLiteral::Property* property = lit->properties()->at(i);
|
ObjectLiteral::Property* property = lit->properties()->at(i);
|
||||||
Expression* value = property->value();
|
Expression* value = property->value();
|
||||||
@ -2589,7 +2586,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
EmitSetHomeObjectIfNeeded(value, 2,
|
EmitSetHomeObjectIfNeeded(value, 2,
|
||||||
lit->SlotForHomeObject(value, &store_slot_index));
|
lit->SlotForHomeObject(value, used_store_slots));
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
@ -2622,10 +2619,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
__ CallRuntime(Runtime::kToFastProperties, 1);
|
__ CallRuntime(Runtime::kToFastProperties, 1);
|
||||||
|
|
||||||
// Verify that compilation exactly consumed the number of store ic slots that
|
|
||||||
// the ClassLiteral node had to offer.
|
|
||||||
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2239,7 +2239,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
|
||||||
|
int* used_store_slots) {
|
||||||
// Constructor is in x0.
|
// Constructor is in x0.
|
||||||
DCHECK(lit != NULL);
|
DCHECK(lit != NULL);
|
||||||
__ push(x0);
|
__ push(x0);
|
||||||
@ -2251,10 +2252,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
FieldMemOperand(x0, JSFunction::kPrototypeOrInitialMapOffset));
|
FieldMemOperand(x0, JSFunction::kPrototypeOrInitialMapOffset));
|
||||||
__ Push(scratch);
|
__ Push(scratch);
|
||||||
|
|
||||||
// store_slot_index points to the vector IC slot for the next store IC used.
|
|
||||||
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
|
|
||||||
// and must be updated if the number of store ICs emitted here changes.
|
|
||||||
int store_slot_index = 0;
|
|
||||||
for (int i = 0; i < lit->properties()->length(); i++) {
|
for (int i = 0; i < lit->properties()->length(); i++) {
|
||||||
ObjectLiteral::Property* property = lit->properties()->at(i);
|
ObjectLiteral::Property* property = lit->properties()->at(i);
|
||||||
Expression* value = property->value();
|
Expression* value = property->value();
|
||||||
@ -2278,7 +2275,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
EmitSetHomeObjectIfNeeded(value, 2,
|
EmitSetHomeObjectIfNeeded(value, 2,
|
||||||
lit->SlotForHomeObject(value, &store_slot_index));
|
lit->SlotForHomeObject(value, used_store_slots));
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
@ -2311,10 +2308,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
__ CallRuntime(Runtime::kToFastProperties, 1);
|
__ CallRuntime(Runtime::kToFastProperties, 1);
|
||||||
|
|
||||||
// Verify that compilation exactly consumed the number of store ic slots that
|
|
||||||
// the ClassLiteral node had to offer.
|
|
||||||
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,6 +289,10 @@ FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements(
|
|||||||
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
|
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scope() != NULL && class_variable_proxy()->var()->IsUnallocated()) {
|
||||||
|
ic_slots++;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// FullCodeGenerator::VisitClassLiteral verifies that it consumes slot_count_
|
// FullCodeGenerator::VisitClassLiteral verifies that it consumes slot_count_
|
||||||
// slots.
|
// slots.
|
||||||
|
@ -1365,7 +1365,9 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
test_value.Else();
|
test_value.Else();
|
||||||
{
|
{
|
||||||
// Bind value and do loop body.
|
// Bind value and do loop body.
|
||||||
VisitForInAssignment(stmt->each(), value, stmt->AssignmentId());
|
ResolvedFeedbackSlot slot =
|
||||||
|
ResolveFeedbackSlot(stmt->EachFeedbackSlot());
|
||||||
|
VisitForInAssignment(stmt->each(), value, slot, stmt->AssignmentId());
|
||||||
VisitIterationBody(stmt, &for_loop);
|
VisitIterationBody(stmt, &for_loop);
|
||||||
}
|
}
|
||||||
test_value.End();
|
test_value.End();
|
||||||
@ -1586,6 +1588,7 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
|
|||||||
environment()->Push(proto);
|
environment()->Push(proto);
|
||||||
|
|
||||||
// Create nodes to store method values into the literal.
|
// Create nodes to store method values into the literal.
|
||||||
|
int store_slot_index = 0;
|
||||||
for (int i = 0; i < expr->properties()->length(); i++) {
|
for (int i = 0; i < expr->properties()->length(); i++) {
|
||||||
ObjectLiteral::Property* property = expr->properties()->at(i);
|
ObjectLiteral::Property* property = expr->properties()->at(i);
|
||||||
environment()->Push(property->is_static() ? literal : proto);
|
environment()->Push(property->is_static() ? literal : proto);
|
||||||
@ -1608,7 +1611,9 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
|
|||||||
Node* value = environment()->Pop();
|
Node* value = environment()->Pop();
|
||||||
Node* key = environment()->Pop();
|
Node* key = environment()->Pop();
|
||||||
Node* receiver = environment()->Pop();
|
Node* receiver = environment()->Pop();
|
||||||
BuildSetHomeObject(value, receiver, property->value());
|
ResolvedFeedbackSlot slot = ResolveFeedbackSlot(
|
||||||
|
expr->SlotForHomeObject(property->value(), &store_slot_index));
|
||||||
|
BuildSetHomeObject(value, receiver, property->value(), slot);
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
@ -1648,8 +1653,11 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
|
|||||||
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();
|
||||||
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
||||||
BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None(),
|
ResolvedFeedbackSlot slot = ResolveFeedbackSlot(
|
||||||
states);
|
FLAG_vector_stores ? expr->GetNthSlot(store_slot_index++)
|
||||||
|
: FeedbackVectorICSlot::Invalid());
|
||||||
|
BuildVariableAssignment(var, literal, Token::INIT_CONST, slot,
|
||||||
|
BailoutId::None(), states);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_context()->ProduceValue(literal);
|
ast_context()->ProduceValue(literal);
|
||||||
@ -1727,6 +1735,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
|
|
||||||
// Create nodes to store computed values into the literal.
|
// Create nodes to store computed values into the literal.
|
||||||
int property_index = 0;
|
int property_index = 0;
|
||||||
|
int store_slot_index = 0;
|
||||||
AccessorTable accessor_table(zone());
|
AccessorTable accessor_table(zone());
|
||||||
for (; property_index < expr->properties()->length(); property_index++) {
|
for (; property_index < expr->properties()->length(); property_index++) {
|
||||||
ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
||||||
@ -1749,11 +1758,17 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
FrameStateBeforeAndAfter states(this, property->value()->id());
|
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 =
|
ResolvedFeedbackSlot slot =
|
||||||
BuildNamedStore(literal, name, value, TypeFeedbackId::None());
|
FLAG_vector_stores
|
||||||
|
? ResolveFeedbackSlot(expr->GetNthSlot(store_slot_index++))
|
||||||
|
: ResolvedFeedbackSlot();
|
||||||
|
Node* store = BuildNamedStore(literal, name, value, slot,
|
||||||
|
TypeFeedbackId::None());
|
||||||
states.AddToNode(store, key->id(),
|
states.AddToNode(store, key->id(),
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Ignore());
|
||||||
BuildSetHomeObject(value, literal, property->value());
|
ResolvedFeedbackSlot home_slot = ResolveFeedbackSlot(
|
||||||
|
expr->SlotForHomeObject(property->value(), &store_slot_index));
|
||||||
|
BuildSetHomeObject(value, literal, property->value(), home_slot);
|
||||||
} else {
|
} else {
|
||||||
VisitForEffect(property->value());
|
VisitForEffect(property->value());
|
||||||
}
|
}
|
||||||
@ -1772,7 +1787,9 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
Node* set_property = NewNode(op, receiver, key, value, language);
|
Node* set_property = NewNode(op, receiver, key, value, language);
|
||||||
// SetProperty should not lazy deopt on an object literal.
|
// SetProperty should not lazy deopt on an object literal.
|
||||||
PrepareFrameState(set_property, BailoutId::None());
|
PrepareFrameState(set_property, BailoutId::None());
|
||||||
BuildSetHomeObject(value, receiver, property->value());
|
ResolvedFeedbackSlot home_slot = ResolveFeedbackSlot(
|
||||||
|
expr->SlotForHomeObject(property->value(), &store_slot_index));
|
||||||
|
BuildSetHomeObject(value, receiver, property->value(), home_slot);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1808,9 +1825,15 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
it != accessor_table.end(); ++it) {
|
it != accessor_table.end(); ++it) {
|
||||||
VisitForValue(it->first);
|
VisitForValue(it->first);
|
||||||
VisitForValueOrNull(it->second->getter);
|
VisitForValueOrNull(it->second->getter);
|
||||||
BuildSetHomeObject(environment()->Top(), literal, it->second->getter);
|
ResolvedFeedbackSlot slot_getter = ResolveFeedbackSlot(
|
||||||
|
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
|
||||||
|
BuildSetHomeObject(environment()->Top(), literal, it->second->getter,
|
||||||
|
slot_getter);
|
||||||
VisitForValueOrNull(it->second->setter);
|
VisitForValueOrNull(it->second->setter);
|
||||||
BuildSetHomeObject(environment()->Top(), literal, it->second->setter);
|
ResolvedFeedbackSlot slot_setter = ResolveFeedbackSlot(
|
||||||
|
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
|
||||||
|
BuildSetHomeObject(environment()->Top(), literal, it->second->setter,
|
||||||
|
slot_setter);
|
||||||
Node* setter = environment()->Pop();
|
Node* setter = environment()->Pop();
|
||||||
Node* getter = environment()->Pop();
|
Node* getter = environment()->Pop();
|
||||||
Node* name = environment()->Pop();
|
Node* name = environment()->Pop();
|
||||||
@ -1855,8 +1878,9 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
Node* value = environment()->Pop();
|
Node* value = environment()->Pop();
|
||||||
Node* key = environment()->Pop();
|
Node* key = environment()->Pop();
|
||||||
Node* receiver = environment()->Pop();
|
Node* receiver = environment()->Pop();
|
||||||
BuildSetHomeObject(value, receiver, property->value());
|
ResolvedFeedbackSlot slot = ResolveFeedbackSlot(
|
||||||
|
expr->SlotForHomeObject(property->value(), &store_slot_index));
|
||||||
|
BuildSetHomeObject(value, receiver, property->value(), slot);
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
case ObjectLiteral::Property::COMPUTED:
|
case ObjectLiteral::Property::COMPUTED:
|
||||||
@ -1897,6 +1921,10 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
NewNode(op, literal);
|
NewNode(op, literal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify that compilation exactly consumed the number of store ic slots that
|
||||||
|
// the ObjectLiteral node had to offer.
|
||||||
|
DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
|
||||||
|
|
||||||
ast_context()->ProduceValue(environment()->Pop());
|
ast_context()->ProduceValue(environment()->Pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1935,7 +1963,8 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
Node* value = environment()->Pop();
|
Node* value = environment()->Pop();
|
||||||
Node* index = jsgraph()->Constant(array_index);
|
Node* index = jsgraph()->Constant(array_index);
|
||||||
Node* store =
|
Node* store =
|
||||||
BuildKeyedStore(literal, index, value, TypeFeedbackId::None());
|
BuildKeyedStore(literal, index, value, ResolvedFeedbackSlot(),
|
||||||
|
TypeFeedbackId::None());
|
||||||
states.AddToNode(store, expr->GetIdForElement(array_index),
|
states.AddToNode(store, expr->GetIdForElement(array_index),
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Ignore());
|
||||||
}
|
}
|
||||||
@ -1979,6 +2008,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
|
|
||||||
|
|
||||||
void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
||||||
|
const ResolvedFeedbackSlot& slot,
|
||||||
BailoutId bailout_id) {
|
BailoutId bailout_id) {
|
||||||
DCHECK(expr->IsValidReferenceExpression());
|
DCHECK(expr->IsValidReferenceExpression());
|
||||||
|
|
||||||
@ -1991,7 +2021,8 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
|||||||
case VARIABLE: {
|
case VARIABLE: {
|
||||||
Variable* var = expr->AsVariableProxy()->var();
|
Variable* var = expr->AsVariableProxy()->var();
|
||||||
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
||||||
BuildVariableAssignment(var, value, Token::ASSIGN, bailout_id, states);
|
BuildVariableAssignment(var, value, Token::ASSIGN, slot, bailout_id,
|
||||||
|
states);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAMED_PROPERTY: {
|
case NAMED_PROPERTY: {
|
||||||
@ -2002,7 +2033,7 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
|||||||
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, slot, TypeFeedbackId::None());
|
||||||
states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
|
states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2014,7 +2045,8 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
|||||||
Node* key = environment()->Pop();
|
Node* key = environment()->Pop();
|
||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
value = environment()->Pop();
|
value = environment()->Pop();
|
||||||
Node* store = BuildKeyedStore(object, key, value, TypeFeedbackId::None());
|
Node* store =
|
||||||
|
BuildKeyedStore(object, key, value, slot, TypeFeedbackId::None());
|
||||||
states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
|
states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2176,18 +2208,19 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
|||||||
FrameStateBeforeAndAfter store_states(this, before_store_id);
|
FrameStateBeforeAndAfter store_states(this, before_store_id);
|
||||||
// Store the value.
|
// Store the value.
|
||||||
Node* value = environment()->Pop();
|
Node* value = environment()->Pop();
|
||||||
|
ResolvedFeedbackSlot slot = ResolveFeedbackSlot(expr->AssignmentSlot());
|
||||||
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(variable, value, expr->op(), slot, expr->id(),
|
||||||
store_states, ast_context()->GetStateCombine());
|
store_states, ast_context()->GetStateCombine());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAMED_PROPERTY: {
|
case NAMED_PROPERTY: {
|
||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||||
Node* store =
|
Node* store = BuildNamedStore(object, name, value, slot,
|
||||||
BuildNamedStore(object, name, value, expr->AssignmentFeedbackId());
|
expr->AssignmentFeedbackId());
|
||||||
store_states.AddToNode(store, expr->id(),
|
store_states.AddToNode(store, expr->id(),
|
||||||
ast_context()->GetStateCombine());
|
ast_context()->GetStateCombine());
|
||||||
break;
|
break;
|
||||||
@ -2195,8 +2228,8 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
|||||||
case KEYED_PROPERTY: {
|
case KEYED_PROPERTY: {
|
||||||
Node* key = environment()->Pop();
|
Node* key = environment()->Pop();
|
||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Node* store =
|
Node* store = BuildKeyedStore(object, key, value, slot,
|
||||||
BuildKeyedStore(object, key, value, expr->AssignmentFeedbackId());
|
expr->AssignmentFeedbackId());
|
||||||
store_states.AddToNode(store, expr->id(),
|
store_states.AddToNode(store, expr->id(),
|
||||||
ast_context()->GetStateCombine());
|
ast_context()->GetStateCombine());
|
||||||
break;
|
break;
|
||||||
@ -2647,20 +2680,21 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store the value.
|
// Store the value.
|
||||||
|
ResolvedFeedbackSlot slot = ResolveFeedbackSlot(expr->CountSlot());
|
||||||
switch (assign_type) {
|
switch (assign_type) {
|
||||||
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(), expr->AssignmentId(),
|
BuildVariableAssignment(variable, value, expr->op(), slot,
|
||||||
store_states);
|
expr->AssignmentId(), store_states);
|
||||||
environment()->Pop();
|
environment()->Pop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAMED_PROPERTY: {
|
case NAMED_PROPERTY: {
|
||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||||
Node* store =
|
Node* store = BuildNamedStore(object, name, value, slot,
|
||||||
BuildNamedStore(object, name, value, expr->CountStoreFeedbackId());
|
expr->CountStoreFeedbackId());
|
||||||
environment()->Push(value);
|
environment()->Push(value);
|
||||||
store_states.AddToNode(store, expr->AssignmentId(),
|
store_states.AddToNode(store, expr->AssignmentId(),
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Ignore());
|
||||||
@ -2670,8 +2704,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
|||||||
case KEYED_PROPERTY: {
|
case KEYED_PROPERTY: {
|
||||||
Node* key = environment()->Pop();
|
Node* key = environment()->Pop();
|
||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Node* store =
|
Node* store = BuildKeyedStore(object, key, value, slot,
|
||||||
BuildKeyedStore(object, key, value, expr->CountStoreFeedbackId());
|
expr->CountStoreFeedbackId());
|
||||||
environment()->Push(value);
|
environment()->Push(value);
|
||||||
store_states.AddToNode(store, expr->AssignmentId(),
|
store_states.AddToNode(store, expr->AssignmentId(),
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Ignore());
|
||||||
@ -3112,8 +3146,9 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
|
|||||||
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.
|
||||||
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
||||||
BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None(),
|
ResolvedFeedbackSlot slot;
|
||||||
states);
|
BuildVariableAssignment(arguments, object, Token::ASSIGN, slot,
|
||||||
|
BailoutId::None(), states);
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
@ -3131,7 +3166,8 @@ Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
|
|||||||
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.
|
||||||
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
||||||
BuildVariableAssignment(rest, object, Token::ASSIGN, BailoutId::None(),
|
ResolvedFeedbackSlot slot;
|
||||||
|
BuildVariableAssignment(rest, object, Token::ASSIGN, slot, BailoutId::None(),
|
||||||
states);
|
states);
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
@ -3143,8 +3179,9 @@ Node* AstGraphBuilder::BuildThisFunctionVar(Variable* this_function_var) {
|
|||||||
|
|
||||||
Node* this_function = GetFunctionClosure();
|
Node* this_function = GetFunctionClosure();
|
||||||
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
||||||
|
ResolvedFeedbackSlot slot;
|
||||||
BuildVariableAssignment(this_function_var, this_function, Token::INIT_CONST,
|
BuildVariableAssignment(this_function_var, this_function, Token::INIT_CONST,
|
||||||
BailoutId::None(), states);
|
slot, BailoutId::None(), states);
|
||||||
return this_function;
|
return this_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3329,7 +3366,8 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
|
|||||||
|
|
||||||
|
|
||||||
Node* AstGraphBuilder::BuildVariableAssignment(
|
Node* AstGraphBuilder::BuildVariableAssignment(
|
||||||
Variable* variable, Node* value, Token::Value op, BailoutId bailout_id,
|
Variable* variable, Node* value, Token::Value op,
|
||||||
|
const ResolvedFeedbackSlot& slot, BailoutId bailout_id,
|
||||||
FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
|
FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
|
||||||
Node* the_hole = jsgraph()->TheHoleConstant();
|
Node* the_hole = jsgraph()->TheHoleConstant();
|
||||||
VariableMode mode = variable->mode();
|
VariableMode mode = variable->mode();
|
||||||
@ -3339,7 +3377,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
|
|||||||
Node* global = BuildLoadGlobalObject();
|
Node* global = BuildLoadGlobalObject();
|
||||||
Handle<Name> name = variable->name();
|
Handle<Name> name = variable->name();
|
||||||
Node* store =
|
Node* store =
|
||||||
BuildNamedStore(global, name, value, TypeFeedbackId::None());
|
BuildNamedStore(global, name, value, slot, TypeFeedbackId::None());
|
||||||
states.AddToNode(store, bailout_id, combine);
|
states.AddToNode(store, bailout_id, combine);
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
@ -3472,16 +3510,19 @@ Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
|
|||||||
|
|
||||||
|
|
||||||
Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
|
Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
|
||||||
|
const ResolvedFeedbackSlot& feedback,
|
||||||
TypeFeedbackId id) {
|
TypeFeedbackId id) {
|
||||||
const Operator* op = javascript()->StoreProperty(language_mode());
|
const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
|
||||||
return Record(js_type_feedback_, NewNode(op, object, key, value), id);
|
return Record(js_type_feedback_, NewNode(op, object, key, value), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
|
Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
|
||||||
Node* value, TypeFeedbackId id) {
|
Node* value,
|
||||||
|
const ResolvedFeedbackSlot& feedback,
|
||||||
|
TypeFeedbackId id) {
|
||||||
const Operator* op =
|
const Operator* op =
|
||||||
javascript()->StoreNamed(language_mode(), MakeUnique(name));
|
javascript()->StoreNamed(language_mode(), MakeUnique(name), feedback);
|
||||||
return Record(js_type_feedback_, NewNode(op, object, value), id);
|
return Record(js_type_feedback_, NewNode(op, object, value), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3626,12 +3667,13 @@ Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
|
|||||||
|
|
||||||
|
|
||||||
Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
|
Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
|
||||||
Expression* expr) {
|
Expression* expr,
|
||||||
|
const ResolvedFeedbackSlot& slot) {
|
||||||
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());
|
FrameStateBeforeAndAfter states(this, BailoutId::None());
|
||||||
Node* store =
|
Node* store =
|
||||||
BuildNamedStore(value, name, home_object, TypeFeedbackId::None());
|
BuildNamedStore(value, name, home_object, slot, TypeFeedbackId::None());
|
||||||
states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
|
states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,9 @@ class AstGraphBuilder : public AstVisitor {
|
|||||||
|
|
||||||
// Builders for variable load and assignment.
|
// Builders for variable load and assignment.
|
||||||
Node* BuildVariableAssignment(Variable* variable, Node* value,
|
Node* BuildVariableAssignment(Variable* variable, Node* value,
|
||||||
Token::Value op, BailoutId bailout_id,
|
Token::Value op,
|
||||||
|
const ResolvedFeedbackSlot& slot,
|
||||||
|
BailoutId bailout_id,
|
||||||
FrameStateBeforeAndAfter& states,
|
FrameStateBeforeAndAfter& states,
|
||||||
OutputFrameStateCombine framestate_combine =
|
OutputFrameStateCombine framestate_combine =
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Ignore());
|
||||||
@ -288,8 +290,10 @@ class AstGraphBuilder : public AstVisitor {
|
|||||||
const ResolvedFeedbackSlot& feedback,
|
const ResolvedFeedbackSlot& feedback,
|
||||||
ContextualMode mode = NOT_CONTEXTUAL);
|
ContextualMode mode = NOT_CONTEXTUAL);
|
||||||
Node* BuildKeyedStore(Node* receiver, Node* key, Node* value,
|
Node* BuildKeyedStore(Node* receiver, Node* key, Node* value,
|
||||||
|
const ResolvedFeedbackSlot& feedback,
|
||||||
TypeFeedbackId id);
|
TypeFeedbackId id);
|
||||||
Node* BuildNamedStore(Node* receiver, Handle<Name>, Node* value,
|
Node* BuildNamedStore(Node* receiver, Handle<Name>, Node* value,
|
||||||
|
const ResolvedFeedbackSlot& feedback,
|
||||||
TypeFeedbackId id);
|
TypeFeedbackId id);
|
||||||
|
|
||||||
// Builders for super property loads and stores.
|
// Builders for super property loads and stores.
|
||||||
@ -321,7 +325,8 @@ class AstGraphBuilder : public AstVisitor {
|
|||||||
|
|
||||||
// Builder for adding the [[HomeObject]] to a value if the value came from a
|
// Builder for adding the [[HomeObject]] to a value if the value came from a
|
||||||
// function literal and needs a home object. Do nothing otherwise.
|
// function literal and needs a home object. Do nothing otherwise.
|
||||||
Node* BuildSetHomeObject(Node* value, Node* home_object, Expression* expr);
|
Node* BuildSetHomeObject(Node* value, Node* home_object, Expression* expr,
|
||||||
|
const ResolvedFeedbackSlot& slot);
|
||||||
|
|
||||||
// Builders for error reporting at runtime.
|
// Builders for error reporting at runtime.
|
||||||
Node* BuildThrowError(Node* exception, BailoutId bailout_id);
|
Node* BuildThrowError(Node* exception, BailoutId bailout_id);
|
||||||
@ -387,6 +392,7 @@ class AstGraphBuilder : public AstVisitor {
|
|||||||
|
|
||||||
// Dispatched from VisitForInStatement.
|
// Dispatched from VisitForInStatement.
|
||||||
void VisitForInAssignment(Expression* expr, Node* value,
|
void VisitForInAssignment(Expression* expr, Node* value,
|
||||||
|
const ResolvedFeedbackSlot& slot,
|
||||||
BailoutId bailout_id);
|
BailoutId bailout_id);
|
||||||
|
|
||||||
// Dispatched from VisitClassLiteral.
|
// Dispatched from VisitClassLiteral.
|
||||||
|
@ -248,7 +248,8 @@ const LoadNamedParameters& LoadNamedParametersOf(const Operator* op) {
|
|||||||
|
|
||||||
bool operator==(StoreNamedParameters const& lhs,
|
bool operator==(StoreNamedParameters const& lhs,
|
||||||
StoreNamedParameters const& rhs) {
|
StoreNamedParameters const& rhs) {
|
||||||
return lhs.language_mode() == rhs.language_mode() && lhs.name() == rhs.name();
|
return lhs.language_mode() == rhs.language_mode() &&
|
||||||
|
lhs.name() == rhs.name() && lhs.feedback() == rhs.feedback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -259,7 +260,7 @@ bool operator!=(StoreNamedParameters const& lhs,
|
|||||||
|
|
||||||
|
|
||||||
size_t hash_value(StoreNamedParameters const& p) {
|
size_t hash_value(StoreNamedParameters const& p) {
|
||||||
return base::hash_combine(p.language_mode(), p.name());
|
return base::hash_combine(p.language_mode(), p.name(), p.feedback());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -274,6 +275,35 @@ const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator==(StorePropertyParameters const& lhs,
|
||||||
|
StorePropertyParameters const& rhs) {
|
||||||
|
return lhs.language_mode() == rhs.language_mode() &&
|
||||||
|
lhs.feedback() == rhs.feedback();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator!=(StorePropertyParameters const& lhs,
|
||||||
|
StorePropertyParameters const& rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t hash_value(StorePropertyParameters const& p) {
|
||||||
|
return base::hash_combine(p.language_mode(), p.feedback());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, StorePropertyParameters const& p) {
|
||||||
|
return os << p.language_mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const StorePropertyParameters& StorePropertyParametersOf(const Operator* op) {
|
||||||
|
DCHECK_EQ(IrOpcode::kJSStoreProperty, op->opcode());
|
||||||
|
return OpParameter<StorePropertyParameters>(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool operator==(CreateClosureParameters const& lhs,
|
bool operator==(CreateClosureParameters const& lhs,
|
||||||
CreateClosureParameters const& rhs) {
|
CreateClosureParameters const& rhs) {
|
||||||
return lhs.pretenure() == rhs.pretenure() &&
|
return lhs.pretenure() == rhs.pretenure() &&
|
||||||
@ -348,8 +378,7 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
|
|||||||
V(Subtract, Operator::kNoProperties, 2, 1) \
|
V(Subtract, Operator::kNoProperties, 2, 1) \
|
||||||
V(Multiply, Operator::kNoProperties, 2, 1) \
|
V(Multiply, Operator::kNoProperties, 2, 1) \
|
||||||
V(Divide, Operator::kNoProperties, 2, 1) \
|
V(Divide, Operator::kNoProperties, 2, 1) \
|
||||||
V(Modulus, Operator::kNoProperties, 2, 1) \
|
V(Modulus, Operator::kNoProperties, 2, 1)
|
||||||
V(StoreProperty, Operator::kNoProperties, 3, 0)
|
|
||||||
|
|
||||||
|
|
||||||
struct JSOperatorGlobalCache final {
|
struct JSOperatorGlobalCache final {
|
||||||
@ -480,9 +509,10 @@ const Operator* JSOperatorBuilder::LoadProperty(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
|
const Operator* JSOperatorBuilder::StoreNamed(
|
||||||
const Unique<Name>& name) {
|
LanguageMode language_mode, const Unique<Name>& name,
|
||||||
StoreNamedParameters parameters(language_mode, name);
|
const ResolvedFeedbackSlot& feedback) {
|
||||||
|
StoreNamedParameters parameters(language_mode, feedback, name);
|
||||||
return new (zone()) Operator1<StoreNamedParameters>( // --
|
return new (zone()) Operator1<StoreNamedParameters>( // --
|
||||||
IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode
|
IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode
|
||||||
"JSStoreNamed", // name
|
"JSStoreNamed", // name
|
||||||
@ -491,6 +521,17 @@ const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Operator* JSOperatorBuilder::StoreProperty(
|
||||||
|
LanguageMode language_mode, const ResolvedFeedbackSlot& feedback) {
|
||||||
|
StorePropertyParameters parameters(language_mode, feedback);
|
||||||
|
return new (zone()) Operator1<StorePropertyParameters>( // --
|
||||||
|
IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode
|
||||||
|
"JSStoreProperty", // name
|
||||||
|
3, 1, 1, 0, 1, 2, // counts
|
||||||
|
parameters); // parameter
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) {
|
const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) {
|
||||||
return new (zone()) Operator1<LanguageMode>( // --
|
return new (zone()) Operator1<LanguageMode>( // --
|
||||||
IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode
|
IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode
|
||||||
|
@ -274,15 +274,19 @@ const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op);
|
|||||||
// used as a parameter by JSStoreNamed operators.
|
// used as a parameter by JSStoreNamed operators.
|
||||||
class StoreNamedParameters final {
|
class StoreNamedParameters final {
|
||||||
public:
|
public:
|
||||||
StoreNamedParameters(LanguageMode language_mode, const Unique<Name>& name)
|
StoreNamedParameters(LanguageMode language_mode,
|
||||||
: language_mode_(language_mode), name_(name) {}
|
const ResolvedFeedbackSlot& feedback,
|
||||||
|
const Unique<Name>& name)
|
||||||
|
: language_mode_(language_mode), name_(name), feedback_(feedback) {}
|
||||||
|
|
||||||
LanguageMode language_mode() const { return language_mode_; }
|
LanguageMode language_mode() const { return language_mode_; }
|
||||||
|
const ResolvedFeedbackSlot& feedback() const { return feedback_; }
|
||||||
const Unique<Name>& name() const { return name_; }
|
const Unique<Name>& name() const { return name_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const LanguageMode language_mode_;
|
const LanguageMode language_mode_;
|
||||||
const Unique<Name> name_;
|
const Unique<Name> name_;
|
||||||
|
const ResolvedFeedbackSlot feedback_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(StoreNamedParameters const&, StoreNamedParameters const&);
|
bool operator==(StoreNamedParameters const&, StoreNamedParameters const&);
|
||||||
@ -295,6 +299,32 @@ std::ostream& operator<<(std::ostream&, StoreNamedParameters const&);
|
|||||||
const StoreNamedParameters& StoreNamedParametersOf(const Operator* op);
|
const StoreNamedParameters& StoreNamedParametersOf(const Operator* op);
|
||||||
|
|
||||||
|
|
||||||
|
// Defines the property being stored to an object. This is used as a parameter
|
||||||
|
// by JSStoreProperty operators.
|
||||||
|
class StorePropertyParameters final {
|
||||||
|
public:
|
||||||
|
StorePropertyParameters(LanguageMode language_mode,
|
||||||
|
const ResolvedFeedbackSlot& feedback)
|
||||||
|
: language_mode_(language_mode), feedback_(feedback) {}
|
||||||
|
|
||||||
|
LanguageMode language_mode() const { return language_mode_; }
|
||||||
|
const ResolvedFeedbackSlot& feedback() const { return feedback_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const LanguageMode language_mode_;
|
||||||
|
const ResolvedFeedbackSlot feedback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(StorePropertyParameters const&, StorePropertyParameters const&);
|
||||||
|
bool operator!=(StorePropertyParameters const&, StorePropertyParameters const&);
|
||||||
|
|
||||||
|
size_t hash_value(StorePropertyParameters const&);
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream&, StorePropertyParameters const&);
|
||||||
|
|
||||||
|
const StorePropertyParameters& StorePropertyParametersOf(const Operator* op);
|
||||||
|
|
||||||
|
|
||||||
// Defines shared information for the closure that should be created. This is
|
// Defines shared information for the closure that should be created. This is
|
||||||
// used as a parameter by JSCreateClosure operators.
|
// used as a parameter by JSCreateClosure operators.
|
||||||
class CreateClosureParameters final {
|
class CreateClosureParameters final {
|
||||||
@ -373,9 +403,11 @@ class JSOperatorBuilder final : public ZoneObject {
|
|||||||
const ResolvedFeedbackSlot& feedback,
|
const ResolvedFeedbackSlot& feedback,
|
||||||
ContextualMode contextual_mode = NOT_CONTEXTUAL);
|
ContextualMode contextual_mode = NOT_CONTEXTUAL);
|
||||||
|
|
||||||
const Operator* StoreProperty(LanguageMode language_mode);
|
const Operator* StoreProperty(LanguageMode language_mode,
|
||||||
|
const ResolvedFeedbackSlot& feedback);
|
||||||
const Operator* StoreNamed(LanguageMode language_mode,
|
const Operator* StoreNamed(LanguageMode language_mode,
|
||||||
const Unique<Name>& name);
|
const Unique<Name>& name,
|
||||||
|
const ResolvedFeedbackSlot& feedback);
|
||||||
|
|
||||||
const Operator* DeleteProperty(LanguageMode language_mode);
|
const Operator* DeleteProperty(LanguageMode language_mode);
|
||||||
|
|
||||||
|
@ -1424,13 +1424,22 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
|
|||||||
|
|
||||||
__ CallRuntime(Runtime::kDefineClass, 6);
|
__ CallRuntime(Runtime::kDefineClass, 6);
|
||||||
PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);
|
||||||
EmitClassDefineProperties(lit);
|
|
||||||
|
int store_slot_index = 0;
|
||||||
|
EmitClassDefineProperties(lit, &store_slot_index);
|
||||||
|
|
||||||
if (lit->scope() != NULL) {
|
if (lit->scope() != NULL) {
|
||||||
DCHECK_NOT_NULL(lit->class_variable_proxy());
|
DCHECK_NOT_NULL(lit->class_variable_proxy());
|
||||||
|
FeedbackVectorICSlot slot = FLAG_vector_stores
|
||||||
|
? lit->GetNthSlot(store_slot_index++)
|
||||||
|
: FeedbackVectorICSlot::Invalid();
|
||||||
EmitVariableAssignment(lit->class_variable_proxy()->var(),
|
EmitVariableAssignment(lit->class_variable_proxy()->var(),
|
||||||
Token::INIT_CONST);
|
Token::INIT_CONST, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify that compilation exactly consumed the number of store ic slots
|
||||||
|
// that the ClassLiteral node had to offer.
|
||||||
|
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
context()->Plug(result_register());
|
context()->Plug(result_register());
|
||||||
|
@ -615,7 +615,7 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
// Adds the properties to the class (function) object and to its prototype.
|
// Adds the properties to the class (function) object and to its prototype.
|
||||||
// Expects the class (function) in the accumulator. The class (function) is
|
// Expects the class (function) in the accumulator. The class (function) is
|
||||||
// in the accumulator after installing all the properties.
|
// in the accumulator after installing all the properties.
|
||||||
void EmitClassDefineProperties(ClassLiteral* lit);
|
void EmitClassDefineProperties(ClassLiteral* lit, int* used_store_slots);
|
||||||
|
|
||||||
// Pushes the property key as a Name on the stack.
|
// Pushes the property key as a Name on the stack.
|
||||||
void EmitPropertyKey(ObjectLiteralProperty* property, BailoutId bailout_id);
|
void EmitPropertyKey(ObjectLiteralProperty* property, BailoutId bailout_id);
|
||||||
@ -634,14 +634,12 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
// Assign to the given expression as if via '='. The right-hand-side value
|
// Assign to the given expression as if via '='. The right-hand-side value
|
||||||
// is expected in the accumulator. slot is only used if FLAG_vector_stores
|
// is expected in the accumulator. slot is only used if FLAG_vector_stores
|
||||||
// is true.
|
// is true.
|
||||||
void EmitAssignment(Expression* expr, FeedbackVectorICSlot slot =
|
void EmitAssignment(Expression* expr, FeedbackVectorICSlot slot);
|
||||||
FeedbackVectorICSlot::Invalid());
|
|
||||||
|
|
||||||
// Complete a variable assignment. The right-hand-side value is expected
|
// Complete a variable assignment. The right-hand-side value is expected
|
||||||
// in the accumulator.
|
// in the accumulator.
|
||||||
void EmitVariableAssignment(
|
void EmitVariableAssignment(Variable* var, Token::Value op,
|
||||||
Variable* var, Token::Value op,
|
FeedbackVectorICSlot slot);
|
||||||
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
|
|
||||||
|
|
||||||
// Helper functions to EmitVariableAssignment
|
// Helper functions to EmitVariableAssignment
|
||||||
void EmitStoreToStackLocalOrContextSlot(Variable* var,
|
void EmitStoreToStackLocalOrContextSlot(Variable* var,
|
||||||
|
@ -2463,7 +2463,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
|
||||||
|
int* used_store_slots) {
|
||||||
// Constructor is in eax.
|
// Constructor is in eax.
|
||||||
DCHECK(lit != NULL);
|
DCHECK(lit != NULL);
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
@ -2474,10 +2475,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
__ mov(scratch, FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset));
|
__ mov(scratch, FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset));
|
||||||
__ Push(scratch);
|
__ Push(scratch);
|
||||||
|
|
||||||
// store_slot_index points to the vector IC slot for the next store IC used.
|
|
||||||
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
|
|
||||||
// and must be updated if the number of store ICs emitted here changes.
|
|
||||||
int store_slot_index = 0;
|
|
||||||
for (int i = 0; i < lit->properties()->length(); i++) {
|
for (int i = 0; i < lit->properties()->length(); i++) {
|
||||||
ObjectLiteral::Property* property = lit->properties()->at(i);
|
ObjectLiteral::Property* property = lit->properties()->at(i);
|
||||||
Expression* value = property->value();
|
Expression* value = property->value();
|
||||||
@ -2500,7 +2497,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
EmitSetHomeObjectIfNeeded(value, 2,
|
EmitSetHomeObjectIfNeeded(value, 2,
|
||||||
lit->SlotForHomeObject(value, &store_slot_index));
|
lit->SlotForHomeObject(value, used_store_slots));
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
@ -2528,10 +2525,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
__ CallRuntime(Runtime::kToFastProperties, 1);
|
__ CallRuntime(Runtime::kToFastProperties, 1);
|
||||||
|
|
||||||
// Verify that compilation exactly consumed the number of store ic slots that
|
|
||||||
// the ClassLiteral node had to offer.
|
|
||||||
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2526,7 +2526,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
|
||||||
|
int* used_store_slots) {
|
||||||
// Constructor is in v0.
|
// Constructor is in v0.
|
||||||
DCHECK(lit != NULL);
|
DCHECK(lit != NULL);
|
||||||
__ push(v0);
|
__ push(v0);
|
||||||
@ -2538,10 +2539,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
|
FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
|
||||||
__ push(scratch);
|
__ push(scratch);
|
||||||
|
|
||||||
// store_slot_index points to the vector IC slot for the next store IC used.
|
|
||||||
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
|
|
||||||
// and must be updated if the number of store ICs emitted here changes.
|
|
||||||
int store_slot_index = 0;
|
|
||||||
for (int i = 0; i < lit->properties()->length(); i++) {
|
for (int i = 0; i < lit->properties()->length(); i++) {
|
||||||
ObjectLiteral::Property* property = lit->properties()->at(i);
|
ObjectLiteral::Property* property = lit->properties()->at(i);
|
||||||
Expression* value = property->value();
|
Expression* value = property->value();
|
||||||
@ -2565,7 +2562,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
EmitSetHomeObjectIfNeeded(value, 2,
|
EmitSetHomeObjectIfNeeded(value, 2,
|
||||||
lit->SlotForHomeObject(value, &store_slot_index));
|
lit->SlotForHomeObject(value, used_store_slots));
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
@ -2598,10 +2595,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
__ CallRuntime(Runtime::kToFastProperties, 1);
|
__ CallRuntime(Runtime::kToFastProperties, 1);
|
||||||
|
|
||||||
// Verify that compilation exactly consumed the number of store ic slots that
|
|
||||||
// the ClassLiteral node had to offer.
|
|
||||||
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2525,7 +2525,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
|
||||||
|
int* used_store_slots) {
|
||||||
// Constructor is in v0.
|
// Constructor is in v0.
|
||||||
DCHECK(lit != NULL);
|
DCHECK(lit != NULL);
|
||||||
__ push(v0);
|
__ push(v0);
|
||||||
@ -2537,10 +2538,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
|
FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
|
||||||
__ push(scratch);
|
__ push(scratch);
|
||||||
|
|
||||||
// store_slot_index points to the vector IC slot for the next store IC used.
|
|
||||||
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
|
|
||||||
// and must be updated if the number of store ICs emitted here changes.
|
|
||||||
int store_slot_index = 0;
|
|
||||||
for (int i = 0; i < lit->properties()->length(); i++) {
|
for (int i = 0; i < lit->properties()->length(); i++) {
|
||||||
ObjectLiteral::Property* property = lit->properties()->at(i);
|
ObjectLiteral::Property* property = lit->properties()->at(i);
|
||||||
Expression* value = property->value();
|
Expression* value = property->value();
|
||||||
@ -2564,7 +2561,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
EmitSetHomeObjectIfNeeded(value, 2,
|
EmitSetHomeObjectIfNeeded(value, 2,
|
||||||
lit->SlotForHomeObject(value, &store_slot_index));
|
lit->SlotForHomeObject(value, used_store_slots));
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
@ -2597,10 +2594,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
__ CallRuntime(Runtime::kToFastProperties, 1);
|
__ CallRuntime(Runtime::kToFastProperties, 1);
|
||||||
|
|
||||||
// Verify that compilation exactly consumed the number of store ic slots that
|
|
||||||
// the ClassLiteral node had to offer.
|
|
||||||
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5089,7 +5082,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
||||||
Token::ASSIGN);
|
Token::ASSIGN, expr->CountSlot());
|
||||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||||
context()->Plug(v0);
|
context()->Plug(v0);
|
||||||
}
|
}
|
||||||
|
@ -2458,7 +2458,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
|
||||||
|
int* used_store_slots) {
|
||||||
// Constructor is in rax.
|
// Constructor is in rax.
|
||||||
DCHECK(lit != NULL);
|
DCHECK(lit != NULL);
|
||||||
__ Push(rax);
|
__ Push(rax);
|
||||||
@ -2469,10 +2470,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
__ movp(scratch, FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset));
|
__ movp(scratch, FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset));
|
||||||
__ Push(scratch);
|
__ Push(scratch);
|
||||||
|
|
||||||
// store_slot_index points to the vector IC slot for the next store IC used.
|
|
||||||
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
|
|
||||||
// and must be updated if the number of store ICs emitted here changes.
|
|
||||||
int store_slot_index = 0;
|
|
||||||
for (int i = 0; i < lit->properties()->length(); i++) {
|
for (int i = 0; i < lit->properties()->length(); i++) {
|
||||||
ObjectLiteral::Property* property = lit->properties()->at(i);
|
ObjectLiteral::Property* property = lit->properties()->at(i);
|
||||||
Expression* value = property->value();
|
Expression* value = property->value();
|
||||||
@ -2495,7 +2492,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
EmitSetHomeObjectIfNeeded(value, 2,
|
EmitSetHomeObjectIfNeeded(value, 2,
|
||||||
lit->SlotForHomeObject(value, &store_slot_index));
|
lit->SlotForHomeObject(value, used_store_slots));
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
@ -2526,10 +2523,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
__ CallRuntime(Runtime::kToFastProperties, 1);
|
__ CallRuntime(Runtime::kToFastProperties, 1);
|
||||||
|
|
||||||
// Verify that compilation exactly consumed the number of store ic slots that
|
|
||||||
// the ClassLiteral node had to offer.
|
|
||||||
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -201,7 +201,6 @@ const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
|
|||||||
SHARED(Multiply, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
|
SHARED(Multiply, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
|
||||||
SHARED(Divide, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
|
SHARED(Divide, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
|
||||||
SHARED(Modulus, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
|
SHARED(Modulus, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
|
||||||
SHARED(StoreProperty, Operator::kNoProperties, 3, 2, 1, 1, 0, 1, 2),
|
|
||||||
#undef SHARED
|
#undef SHARED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -739,7 +739,9 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
|
|||||||
Node* context = UndefinedConstant();
|
Node* context = UndefinedConstant();
|
||||||
Node* effect = graph()->start();
|
Node* effect = graph()->start();
|
||||||
Node* control = graph()->start();
|
Node* control = graph()->start();
|
||||||
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
|
ResolvedFeedbackSlot slot;
|
||||||
|
Node* node =
|
||||||
|
graph()->NewNode(javascript()->StoreProperty(language_mode, slot),
|
||||||
base, key, value, context);
|
base, key, value, context);
|
||||||
for (int i = 0;
|
for (int i = 0;
|
||||||
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
|
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
|
||||||
@ -785,7 +787,9 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) {
|
|||||||
Node* context = UndefinedConstant();
|
Node* context = UndefinedConstant();
|
||||||
Node* effect = graph()->start();
|
Node* effect = graph()->start();
|
||||||
Node* control = graph()->start();
|
Node* control = graph()->start();
|
||||||
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
|
ResolvedFeedbackSlot slot;
|
||||||
|
Node* node =
|
||||||
|
graph()->NewNode(javascript()->StoreProperty(language_mode, slot),
|
||||||
base, key, value, context);
|
base, key, value, context);
|
||||||
for (int i = 0;
|
for (int i = 0;
|
||||||
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
|
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
|
||||||
@ -844,7 +848,9 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) {
|
|||||||
Node* context = UndefinedConstant();
|
Node* context = UndefinedConstant();
|
||||||
Node* effect = graph()->start();
|
Node* effect = graph()->start();
|
||||||
Node* control = graph()->start();
|
Node* control = graph()->start();
|
||||||
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
|
ResolvedFeedbackSlot slot;
|
||||||
|
Node* node =
|
||||||
|
graph()->NewNode(javascript()->StoreProperty(language_mode, slot),
|
||||||
base, key, value, context);
|
base, key, value, context);
|
||||||
for (int i = 0;
|
for (int i = 0;
|
||||||
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
|
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user