VectorICs: allocating slots for store ics in ast nodes.

Also adapt code generation to pass the slot to the
store/keyed-store ic. AST nodes ObjectLiteral, Assignment,
ForEach, Call and CountOperation now include one or more
feedback vector ic slot ids.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#28659}
This commit is contained in:
mvstanton 2015-05-27 07:26:11 -07:00 committed by Commit bot
parent 42fc431078
commit 5450fc07ba
12 changed files with 746 additions and 205 deletions

View File

@ -1282,7 +1282,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ mov(result_register(), r3);
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each());
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
@ -1344,13 +1344,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
int offset,
FeedbackVectorICSlot slot) {
if (NeedsHomeObject(initializer)) {
__ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
__ mov(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ ldr(StoreDescriptor::ValueRegister(),
MemOperand(sp, offset * kPointerSize));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
}
}
@ -1675,6 +1677,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector ic slot for the next store ic used.
// ObjectLiteral::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 (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1701,7 +1707,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(StoreDescriptor::ValueRegister().is(r0));
__ mov(StoreDescriptor::NameRegister(), Operand(key->value()));
__ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(key->LiteralFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
}
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
@ -1709,6 +1720,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ mov(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ ldr(StoreDescriptor::ValueRegister(), MemOperand(sp));
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
}
CallStoreIC();
}
} else {
@ -1722,7 +1736,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
__ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes
__ push(r0);
__ CallRuntime(Runtime::kSetProperty, 4);
@ -1761,9 +1776,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ push(r0);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitSetHomeObjectIfNeeded(
it->second->getter, 2,
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
EmitSetHomeObjectIfNeeded(
it->second->setter, 3,
expr->SlotForHomeObject(it->second->setter, &store_slot_index));
__ mov(r0, Operand(Smi::FromInt(NONE)));
__ push(r0);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
@ -1798,7 +1817,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
@ -1844,6 +1864,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(r0);
}
// 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());
}
@ -1959,7 +1983,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
Property* property = expr->target()->AsProperty();
LhsKind assign_type = GetAssignType(property);
LhsKind assign_type = Property::GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@ -2072,7 +2096,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op());
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
break;
@ -2606,17 +2630,18 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
}
void FullCodeGenerator::EmitAssignment(Expression* expr) {
void FullCodeGenerator::EmitAssignment(Expression* expr,
FeedbackVectorICSlot slot) {
DCHECK(expr->IsValidReferenceExpression());
Property* prop = expr->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var();
EffectContext context(this);
EmitVariableAssignment(var, Token::ASSIGN);
EmitVariableAssignment(var, Token::ASSIGN, slot);
break;
}
case NAMED_PROPERTY: {
@ -2626,6 +2651,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
__ mov(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
@ -2672,6 +2698,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Move(StoreDescriptor::NameRegister(), r0);
__ Pop(StoreDescriptor::ValueRegister(),
StoreDescriptor::ReceiverRegister());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
@ -2695,11 +2722,13 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
}
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
FeedbackVectorICSlot slot) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ mov(StoreDescriptor::NameRegister(), Operand(var->name()));
__ ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT_LET) {
@ -2796,7 +2825,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
__ mov(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
__ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
} else {
CallStoreIC(expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
@ -2843,7 +2877,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
} else {
CallIC(ic, expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
@ -3088,7 +3127,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() {
void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref) {
SuperReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var();
GetVar(r1, this_var);
__ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
@ -3099,7 +3138,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
EmitVariableAssignment(this_var, Token::INIT_CONST);
EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
@ -3326,7 +3365,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
expr->CallFeedbackICSlot());
context()->Plug(r0);
}
@ -4615,6 +4655,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
@ -4817,7 +4858,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@ -4982,7 +5023,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix()) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(r0);
}
@ -4993,7 +5034,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
}
@ -5002,7 +5043,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ mov(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
__ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
} else {
CallStoreIC(expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -5040,7 +5086,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
StoreDescriptor::NameRegister());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
} else {
CallIC(ic, expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -5375,6 +5426,13 @@ void FullCodeGenerator::ClearPendingMessage() {
}
void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
DCHECK(FLAG_vector_stores && !slot.IsInvalid());
__ mov(VectorStoreICTrampolineDescriptor::SlotRegister(),
Operand(SmiFromSlot(slot)));
}
#undef __

View File

@ -1265,7 +1265,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Mov(result_register(), x3);
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each());
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
@ -1328,12 +1328,14 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
int offset,
FeedbackVectorICSlot slot) {
if (NeedsHomeObject(initializer)) {
__ Peek(StoreDescriptor::ReceiverRegister(), 0);
__ Mov(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize);
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
}
}
@ -1649,6 +1651,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector ic slot for the next store ic used.
// ObjectLiteral::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 (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1675,7 +1681,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(StoreDescriptor::ValueRegister().is(x0));
__ Mov(StoreDescriptor::NameRegister(), Operand(key->value()));
__ Peek(StoreDescriptor::ReceiverRegister(), 0);
CallStoreIC(key->LiteralFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
}
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
@ -1683,6 +1694,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Mov(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ Peek(StoreDescriptor::ValueRegister(), 0);
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
}
CallStoreIC();
}
} else {
@ -1695,7 +1709,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
__ Mov(x0, Smi::FromInt(SLOPPY)); // Language mode
__ Push(x0);
__ CallRuntime(Runtime::kSetProperty, 4);
@ -1733,9 +1748,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Push(x10);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitSetHomeObjectIfNeeded(
it->second->getter, 2,
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
EmitSetHomeObjectIfNeeded(
it->second->setter, 3,
expr->SlotForHomeObject(it->second->setter, &store_slot_index));
__ Mov(x10, Smi::FromInt(NONE));
__ Push(x10);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
@ -1770,7 +1789,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
@ -1816,6 +1836,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(x0);
}
// 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());
}
@ -1928,7 +1952,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
Property* property = expr->target()->AsProperty();
LhsKind assign_type = GetAssignType(property);
LhsKind assign_type = Property::GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@ -2038,7 +2062,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op());
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
break;
@ -2286,17 +2310,18 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
}
void FullCodeGenerator::EmitAssignment(Expression* expr) {
void FullCodeGenerator::EmitAssignment(Expression* expr,
FeedbackVectorICSlot slot) {
DCHECK(expr->IsValidReferenceExpression());
Property* prop = expr->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var();
EffectContext context(this);
EmitVariableAssignment(var, Token::ASSIGN);
EmitVariableAssignment(var, Token::ASSIGN, slot);
break;
}
case NAMED_PROPERTY: {
@ -2308,6 +2333,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Pop(StoreDescriptor::ValueRegister()); // Restore value.
__ Mov(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
@ -2354,6 +2380,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Mov(StoreDescriptor::NameRegister(), x0);
__ Pop(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::ValueRegister());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
@ -2377,13 +2404,14 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
}
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
FeedbackVectorICSlot slot) {
ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment");
if (var->IsUnallocated()) {
// Global var, const, or let.
__ Mov(StoreDescriptor::NameRegister(), Operand(var->name()));
__ Ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT_LET) {
@ -2479,7 +2507,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
__ Mov(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
__ Pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
} else {
CallStoreIC(expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
@ -2528,7 +2561,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
} else {
CallIC(ic, expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
@ -2774,7 +2812,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() {
void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref) {
SuperReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var();
GetVar(x1, this_var);
Label uninitialized_this;
@ -2784,7 +2822,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
EmitVariableAssignment(this_var, Token::INIT_CONST);
EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
@ -3012,7 +3050,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
expr->CallFeedbackICSlot());
context()->Plug(x0);
}
@ -4299,6 +4338,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, x0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
@ -4499,7 +4539,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@ -4662,7 +4702,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix()) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(x0);
}
@ -4673,7 +4713,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
}
@ -4682,7 +4722,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Mov(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
__ Pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
} else {
CallStoreIC(expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -4720,7 +4765,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Pop(StoreDescriptor::ReceiverRegister());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
} else {
CallIC(ic, expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -5386,6 +5436,12 @@ void FullCodeGenerator::ClearPendingMessage() {
}
void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
DCHECK(FLAG_vector_stores && !slot.IsInvalid());
__ Mov(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot));
}
#undef __

View File

@ -313,6 +313,7 @@ void AstNumberingVisitor::VisitAssignment(Assignment* node) {
if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
Visit(node->target());
Visit(node->value());
ReserveFeedbackSlots(node);
}
@ -342,11 +343,11 @@ void AstNumberingVisitor::VisitSpread(Spread* node) {
void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
IncrementNodeCount();
DisableSelfOptimization();
ReserveFeedbackSlots(node);
node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
Visit(node->each());
Visit(node->enumerable());
Visit(node->body());
ReserveFeedbackSlots(node);
}
@ -359,6 +360,7 @@ void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
Visit(node->result_done());
Visit(node->assign_each());
Visit(node->body());
ReserveFeedbackSlots(node);
}
@ -437,6 +439,7 @@ void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
// is shadowed by a later occurrence of the same key. For the
// marked expressions, no store code will be is emitted.
node->CalculateEmitStore(zone());
ReserveFeedbackSlots(node);
}

View File

@ -121,16 +121,73 @@ FeedbackVectorRequirements VariableProxy::ComputeFeedbackRequirements(
}
static int GetStoreICSlots(Expression* expr) {
int ic_slots = 0;
if (FLAG_vector_stores) {
Property* property = expr->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
if ((assign_type == VARIABLE &&
expr->AsVariableProxy()->var()->IsUnallocated()) ||
assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) {
ic_slots++;
}
}
return ic_slots;
}
static Code::Kind GetStoreICKind(Expression* expr) {
LhsKind assign_type = Property::GetAssignType(expr->AsProperty());
return assign_type == KEYED_PROPERTY ? Code::KEYED_STORE_IC : Code::STORE_IC;
}
FeedbackVectorRequirements ForEachStatement::ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) {
int ic_slots = GetStoreICSlots(each());
return FeedbackVectorRequirements(0, ic_slots);
}
Code::Kind ForEachStatement::FeedbackICSlotKind(int index) {
return GetStoreICKind(each());
}
Assignment::Assignment(Zone* zone, Token::Value op, Expression* target,
Expression* value, int pos)
: Expression(zone, pos),
bit_field_(IsUninitializedField::encode(false) |
KeyTypeField::encode(ELEMENT) |
StoreModeField::encode(STANDARD_STORE) |
TokenField::encode(op)),
bit_field_(
IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) |
StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)),
target_(target),
value_(value),
binary_operation_(NULL) {}
binary_operation_(NULL),
slot_(FeedbackVectorICSlot::Invalid()) {}
FeedbackVectorRequirements Assignment::ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) {
int ic_slots = GetStoreICSlots(target());
return FeedbackVectorRequirements(0, ic_slots);
}
Code::Kind Assignment::FeedbackICSlotKind(int index) {
return GetStoreICKind(target());
}
FeedbackVectorRequirements CountOperation::ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) {
int ic_slots = GetStoreICSlots(expression());
return FeedbackVectorRequirements(0, ic_slots);
}
Code::Kind CountOperation::FeedbackICSlotKind(int index) {
return GetStoreICKind(expression());
}
Token::Value Assignment::binary_op() const {
@ -253,6 +310,56 @@ bool ObjectLiteral::Property::emit_store() {
}
FeedbackVectorRequirements ObjectLiteral::ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) {
if (!FLAG_vector_stores) return FeedbackVectorRequirements(0, 0);
// This logic that computes the number of slots needed for vector store
// ics must mirror FullCodeGenerator::VisitObjectLiteral.
int ic_slots = 0;
for (int i = 0; i < properties()->length(); i++) {
ObjectLiteral::Property* property = properties()->at(i);
if (property->IsCompileTimeValue()) continue;
Expression* value = property->value();
if (property->is_computed_name() &&
property->kind() != ObjectLiteral::Property::PROTOTYPE) {
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
} else if (property->emit_store()) {
if (property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL ||
property->kind() == ObjectLiteral::Property::COMPUTED) {
Literal* key = property->key()->AsLiteral();
if (key->value()->IsInternalizedString()) ic_slots++;
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
} else if (property->kind() == ObjectLiteral::Property::GETTER ||
property->kind() == ObjectLiteral::Property::SETTER) {
// We might need a slot for the home object.
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
}
}
}
#ifdef DEBUG
// FullCodeGenerator::VisitObjectLiteral verifies that it consumes slot_count_
// slots.
slot_count_ = ic_slots;
#endif
return FeedbackVectorRequirements(0, ic_slots);
}
FeedbackVectorICSlot ObjectLiteral::SlotForHomeObject(Expression* value,
int* slot_index) const {
if (FLAG_vector_stores && FunctionLiteral::NeedsHomeObject(value)) {
DCHECK(slot_index != NULL && *slot_index >= 0 && *slot_index < slot_count_);
FeedbackVectorICSlot slot = GetNthSlot(*slot_index);
*slot_index += 1;
return slot;
}
return FeedbackVectorICSlot::Invalid();
}
void ObjectLiteral::CalculateEmitStore(Zone* zone) {
const auto GETTER = ObjectLiteral::Property::GETTER;
const auto SETTER = ObjectLiteral::Property::SETTER;
@ -590,7 +697,10 @@ void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const {
CallType call_type = GetCallType(isolate);
if (IsUsingCallFeedbackSlot(isolate) || call_type == POSSIBLY_EVAL_CALL) {
if (call_type == POSSIBLY_EVAL_CALL) {
return false;
}
if (call_type == SUPER_CALL && !FLAG_vector_stores) {
return false;
}
return true;
@ -599,7 +709,7 @@ bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const {
bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const {
// SuperConstructorCall uses a CallConstructStub, which wants
// a Slot, not an IC slot.
// a Slot, in addition to any IC slots requested elsewhere.
return GetCallType(isolate) == SUPER_CALL;
}
@ -608,8 +718,6 @@ FeedbackVectorRequirements Call::ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) {
int ic_slots = IsUsingCallFeedbackICSlot(isolate) ? 1 : 0;
int slots = IsUsingCallFeedbackSlot(isolate) ? 1 : 0;
// A Call uses either a slot or an IC slot.
DCHECK((ic_slots & slots) == 0);
return FeedbackVectorRequirements(slots, ic_slots);
}

134
src/ast.h
View File

@ -796,13 +796,26 @@ class ForEachStatement : public IterationStatement {
Expression* each() const { return each_; }
Expression* subject() const { return subject_; }
FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override;
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
ICSlotCache* cache) override {
each_slot_ = slot;
}
Code::Kind FeedbackICSlotKind(int index) override;
FeedbackVectorICSlot EachFeedbackSlot() const { return each_slot_; }
protected:
ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
: IterationStatement(zone, labels, pos),
each_(NULL),
subject_(NULL),
each_slot_(FeedbackVectorICSlot::Invalid()) {}
private:
Expression* each_;
Expression* subject_;
FeedbackVectorICSlot each_slot_;
};
@ -815,9 +828,12 @@ class ForInStatement final : public ForEachStatement {
}
// Type feedback information.
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override {
return FeedbackVectorRequirements(1, 0);
FeedbackVectorRequirements base =
ForEachStatement::ComputeFeedbackRequirements(isolate, cache);
DCHECK(base.slots() == 0 && base.ic_slots() <= 1);
return FeedbackVectorRequirements(1, base.ic_slots());
}
void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override {
for_in_feedback_slot_ = slot;
@ -1457,17 +1473,44 @@ class ObjectLiteral final : public MaterializedLiteral {
// ObjectLiteral can vary, so num_ids() is not a static method.
int num_ids() const { return parent_num_ids() + 1 + properties()->length(); }
// Object literals need one feedback slot for each non-trivial value, as well
// as some slots for home objects.
FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override;
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
ICSlotCache* cache) override {
slot_ = slot;
}
Code::Kind FeedbackICSlotKind(int index) override { return Code::STORE_IC; }
FeedbackVectorICSlot GetNthSlot(int n) const {
return FeedbackVectorICSlot(slot_.ToInt() + n);
}
// If value needs a home object, returns a valid feedback vector ic slot
// given by slot_index, and increments slot_index.
FeedbackVectorICSlot SlotForHomeObject(Expression* value,
int* slot_index) const;
#ifdef DEBUG
int slot_count() const { return slot_count_; }
#endif
protected:
ObjectLiteral(Zone* zone, ZoneList<Property*>* properties, int literal_index,
int boilerplate_properties, bool has_function,
bool is_strong, int pos)
int boilerplate_properties, bool has_function, bool is_strong,
int pos)
: MaterializedLiteral(zone, literal_index, is_strong, pos),
properties_(properties),
boilerplate_properties_(boilerplate_properties),
fast_elements_(false),
has_elements_(false),
may_store_doubles_(false),
has_function_(has_function) {}
has_function_(has_function),
#ifdef DEBUG
slot_count_(0),
#endif
slot_(FeedbackVectorICSlot::Invalid()) {
}
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
private:
@ -1479,6 +1522,12 @@ class ObjectLiteral final : public MaterializedLiteral {
bool has_elements_;
bool may_store_doubles_;
bool has_function_;
#ifdef DEBUG
// slot_count_ helps validate that the logic to allocate ic slots and the
// logic to use them are in sync.
int slot_count_;
#endif
FeedbackVectorICSlot slot_;
};
@ -1654,6 +1703,17 @@ class VariableProxy final : public Expression {
};
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY,
KEYED_SUPER_PROPERTY
};
class Property final : public Expression {
public:
DECLARE_NODE_TYPE(Property)
@ -1721,6 +1781,14 @@ class Property final : public Expression {
return property_feedback_slot_;
}
static LhsKind GetAssignType(Property* property) {
if (property == NULL) return VARIABLE;
bool super_access = property->IsSuperAccess();
return (property->key()->IsPropertyName())
? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
: (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY);
}
protected:
Property(Zone* zone, Expression* obj, Expression* key, int pos)
: Expression(zone, pos),
@ -1759,22 +1827,14 @@ class Call final : public Expression {
Isolate* isolate, const ICSlotCache* cache) override;
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
ICSlotCache* cache) override {
ic_slot_or_slot_ = slot.ToInt();
}
void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override {
ic_slot_or_slot_ = slot.ToInt();
ic_slot_ = slot;
}
void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override { slot_ = slot; }
Code::Kind FeedbackICSlotKind(int index) override { return Code::CALL_IC; }
FeedbackVectorSlot CallFeedbackSlot() const {
DCHECK(ic_slot_or_slot_ != FeedbackVectorSlot::Invalid().ToInt());
return FeedbackVectorSlot(ic_slot_or_slot_);
}
FeedbackVectorSlot CallFeedbackSlot() const { return slot_; }
FeedbackVectorICSlot CallFeedbackICSlot() const {
DCHECK(ic_slot_or_slot_ != FeedbackVectorICSlot::Invalid().ToInt());
return FeedbackVectorICSlot(ic_slot_or_slot_);
}
FeedbackVectorICSlot CallFeedbackICSlot() const { return ic_slot_; }
SmallMapList* GetReceiverTypes() override {
if (expression()->IsProperty()) {
@ -1846,7 +1906,8 @@ class Call final : public Expression {
Call(Zone* zone, Expression* expression, ZoneList<Expression*>* arguments,
int pos)
: Expression(zone, pos),
ic_slot_or_slot_(FeedbackVectorICSlot::Invalid().ToInt()),
ic_slot_(FeedbackVectorICSlot::Invalid()),
slot_(FeedbackVectorSlot::Invalid()),
expression_(expression),
arguments_(arguments),
bit_field_(IsUninitializedField::encode(false)) {
@ -1859,9 +1920,8 @@ class Call final : public Expression {
private:
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
// We store this as an integer because we don't know if we have a slot or
// an ic slot until scoping time.
int ic_slot_or_slot_;
FeedbackVectorICSlot ic_slot_;
FeedbackVectorSlot slot_;
Expression* expression_;
ZoneList<Expression*>* arguments_;
Handle<JSFunction> target_;
@ -2120,16 +2180,25 @@ class CountOperation final : public Expression {
return TypeFeedbackId(local_id(3));
}
FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override;
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
ICSlotCache* cache) override {
slot_ = slot;
}
Code::Kind FeedbackICSlotKind(int index) override;
FeedbackVectorICSlot CountSlot() const { return slot_; }
protected:
CountOperation(Zone* zone, Token::Value op, bool is_prefix, Expression* expr,
int pos)
: Expression(zone, pos),
bit_field_(IsPrefixField::encode(is_prefix) |
KeyTypeField::encode(ELEMENT) |
StoreModeField::encode(STANDARD_STORE) |
TokenField::encode(op)),
bit_field_(
IsPrefixField::encode(is_prefix) | KeyTypeField::encode(ELEMENT) |
StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)),
type_(NULL),
expression_(expr) {}
expression_(expr),
slot_(FeedbackVectorICSlot::Invalid()) {}
static int parent_num_ids() { return Expression::num_ids(); }
private:
@ -2146,6 +2215,7 @@ class CountOperation final : public Expression {
Type* type_;
Expression* expression_;
SmallMapList receiver_types_;
FeedbackVectorICSlot slot_;
};
@ -2288,6 +2358,15 @@ class Assignment final : public Expression {
bit_field_ = StoreModeField::update(bit_field_, mode);
}
FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override;
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
ICSlotCache* cache) override {
slot_ = slot;
}
Code::Kind FeedbackICSlotKind(int index) override;
FeedbackVectorICSlot AssignmentSlot() const { return slot_; }
protected:
Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value,
int pos);
@ -2308,6 +2387,7 @@ class Assignment final : public Expression {
Expression* value_;
BinaryOperation* binary_operation_;
SmallMapList receiver_types_;
FeedbackVectorICSlot slot_;
};

View File

@ -591,26 +591,6 @@ class FullCodeGenerator: public AstVisitor {
void EmitLoadJSRuntimeFunction(CallRuntime* expr);
void EmitCallJSRuntimeFunction(CallRuntime* expr);
// Platform-specific support for compiling assignments.
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
VARIABLE,
NAMED_PROPERTY,
KEYED_PROPERTY,
NAMED_SUPER_PROPERTY,
KEYED_SUPER_PROPERTY
};
static LhsKind GetAssignType(Property* property) {
if (property == NULL) return VARIABLE;
bool super_access = property->IsSuperAccess();
return (property->key()->IsPropertyName())
? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
: (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY);
}
// Load a value from a named property.
// The receiver is left on the stack by the IC.
void EmitNamedPropertyLoad(Property* expr);
@ -647,13 +627,16 @@ class FullCodeGenerator: public AstVisitor {
Expression* right);
// Assign to the given expression as if via '='. The right-hand-side value
// is expected in the accumulator.
void EmitAssignment(Expression* expr);
// is expected in the accumulator. slot is only used if FLAG_vector_stores
// is true.
void EmitAssignment(Expression* expr, FeedbackVectorICSlot slot =
FeedbackVectorICSlot::Invalid());
// Complete a variable assignment. The right-hand-side value is expected
// in the accumulator.
void EmitVariableAssignment(Variable* var,
Token::Value op);
void EmitVariableAssignment(
Variable* var, Token::Value op,
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
// Helper functions to EmitVariableAssignment
void EmitStoreToStackLocalOrContextSlot(Variable* var,
@ -683,10 +666,14 @@ class FullCodeGenerator: public AstVisitor {
// Adds the [[HomeObject]] to |initializer| if it is a FunctionLiteral.
// The value of the initializer is expected to be at the top of the stack.
// |offset| is the offset in the stack where the home object can be found.
void EmitSetHomeObjectIfNeeded(Expression* initializer, int offset);
void EmitSetHomeObjectIfNeeded(
Expression* initializer, int offset,
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
void EmitLoadSuperConstructor();
void EmitInitializeThisAfterSuper(SuperReference* super_ref);
void EmitInitializeThisAfterSuper(
SuperReference* super_ref,
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
void CallIC(Handle<Code> code,
TypeFeedbackId id = TypeFeedbackId::None());
@ -764,6 +751,8 @@ class FullCodeGenerator: public AstVisitor {
bool MustCreateObjectLiteralWithRuntime(ObjectLiteral* expr) const;
bool MustCreateArrayLiteralWithRuntime(ArrayLiteral* expr) const;
void EmitLoadStoreICSlot(FeedbackVectorICSlot slot);
Handle<HandlerTable> handler_table() { return handler_table_; }
struct BailoutEntry {

View File

@ -1209,7 +1209,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ mov(result_register(), ebx);
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each());
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
@ -1270,13 +1270,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
int offset,
FeedbackVectorICSlot slot) {
if (NeedsHomeObject(initializer)) {
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
__ mov(StoreDescriptor::NameRegister(),
Immediate(isolate()->factory()->home_object_symbol()));
__ mov(StoreDescriptor::ValueRegister(),
Operand(esp, offset * kPointerSize));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
}
}
@ -1610,6 +1612,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector ic slot for the next store ic used.
// ObjectLiteral::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 (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1636,7 +1642,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(StoreDescriptor::ValueRegister().is(eax));
__ mov(StoreDescriptor::NameRegister(), Immediate(key->value()));
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
CallStoreIC(key->LiteralFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
}
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
@ -1644,6 +1655,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ mov(StoreDescriptor::NameRegister(),
Immediate(isolate()->factory()->home_object_symbol()));
__ mov(StoreDescriptor::ValueRegister(), Operand(esp, 0));
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
}
CallStoreIC();
}
} else {
@ -1655,7 +1669,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
__ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode
__ CallRuntime(Runtime::kSetProperty, 4);
} else {
@ -1689,9 +1704,15 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ push(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitSetHomeObjectIfNeeded(
it->second->getter, 2,
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
EmitSetHomeObjectIfNeeded(
it->second->setter, 3,
expr->SlotForHomeObject(it->second->setter, &store_slot_index));
__ push(Immediate(Smi::FromInt(NONE)));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
}
@ -1724,7 +1745,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
@ -1766,6 +1788,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(eax);
}
// 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());
}
@ -1886,7 +1912,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
Property* property = expr->target()->AsProperty();
LhsKind assign_type = GetAssignType(property);
LhsKind assign_type = Property::GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@ -1994,7 +2020,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op());
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
break;
@ -2512,17 +2538,18 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
}
void FullCodeGenerator::EmitAssignment(Expression* expr) {
void FullCodeGenerator::EmitAssignment(Expression* expr,
FeedbackVectorICSlot slot) {
DCHECK(expr->IsValidReferenceExpression());
Property* prop = expr->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var();
EffectContext context(this);
EmitVariableAssignment(var, Token::ASSIGN);
EmitVariableAssignment(var, Token::ASSIGN, slot);
break;
}
case NAMED_PROPERTY: {
@ -2532,6 +2559,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
__ mov(StoreDescriptor::NameRegister(),
prop->key()->AsLiteral()->value());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
@ -2578,6 +2606,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Move(StoreDescriptor::NameRegister(), eax);
__ pop(StoreDescriptor::ReceiverRegister()); // Receiver.
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
@ -2599,12 +2628,13 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
}
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
FeedbackVectorICSlot slot) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ mov(StoreDescriptor::NameRegister(), var->name());
__ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT_LET) {
@ -2700,7 +2730,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
SetSourcePosition(expr->position());
__ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
__ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
} else {
CallStoreIC(expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
}
@ -2748,7 +2783,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
SetSourcePosition(expr->position());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
} else {
CallIC(ic, expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
@ -2977,7 +3017,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() {
void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref) {
SuperReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var();
GetVar(ecx, this_var);
__ cmp(ecx, isolate()->factory()->the_hole_value());
@ -2987,7 +3027,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
EmitVariableAssignment(this_var, Token::INIT_CONST);
EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
@ -3205,7 +3245,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
expr->CallFeedbackICSlot());
context()->Plug(eax);
}
@ -4539,6 +4580,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, eax);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
@ -4742,7 +4784,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@ -4908,7 +4950,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(eax);
}
@ -4920,7 +4962,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} else {
// Perform the assignment as if via '='.
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
}
@ -4929,7 +4971,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ mov(StoreDescriptor::NameRegister(),
prop->key()->AsLiteral()->value());
__ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
} else {
CallStoreIC(expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -4967,7 +5014,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ pop(StoreDescriptor::ReceiverRegister());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
} else {
CallIC(ic, expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
// Result is on the stack
@ -5301,6 +5353,13 @@ void FullCodeGenerator::ClearPendingMessage() {
}
void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
DCHECK(FLAG_vector_stores && !slot.IsInvalid());
__ mov(VectorStoreICTrampolineDescriptor::SlotRegister(),
Immediate(SmiFromSlot(slot)));
}
#undef __

View File

@ -1270,7 +1270,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ mov(result_register(), a3);
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each());
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
@ -1332,13 +1332,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
int offset,
FeedbackVectorICSlot slot) {
if (NeedsHomeObject(initializer)) {
__ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
__ li(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ lw(StoreDescriptor::ValueRegister(),
MemOperand(sp, offset * kPointerSize));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
}
}
@ -1661,6 +1663,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector ic slot for the next store ic used.
// ObjectLiteral::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 (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1688,7 +1694,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(StoreDescriptor::ValueRegister().is(a0));
__ li(StoreDescriptor::NameRegister(), Operand(key->value()));
__ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(key->LiteralFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
}
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
@ -1696,6 +1707,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ li(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ lw(StoreDescriptor::ValueRegister(), MemOperand(sp));
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
}
CallStoreIC();
}
} else {
@ -1709,7 +1723,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
__ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes.
__ push(a0);
__ CallRuntime(Runtime::kSetProperty, 4);
@ -1747,9 +1762,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ push(a0);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitSetHomeObjectIfNeeded(
it->second->getter, 2,
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
EmitSetHomeObjectIfNeeded(
it->second->setter, 3,
expr->SlotForHomeObject(it->second->setter, &store_slot_index));
__ li(a0, Operand(Smi::FromInt(NONE)));
__ push(a0);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
@ -1784,7 +1803,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
@ -1830,6 +1850,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(v0);
}
// 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());
}
@ -1946,7 +1970,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
Property* property = expr->target()->AsProperty();
LhsKind assign_type = GetAssignType(property);
LhsKind assign_type = Property::GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@ -2059,7 +2083,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op());
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
break;
@ -2584,17 +2608,18 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
}
void FullCodeGenerator::EmitAssignment(Expression* expr) {
void FullCodeGenerator::EmitAssignment(Expression* expr,
FeedbackVectorICSlot slot) {
DCHECK(expr->IsValidReferenceExpression());
Property* prop = expr->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var();
EffectContext context(this);
EmitVariableAssignment(var, Token::ASSIGN);
EmitVariableAssignment(var, Token::ASSIGN, slot);
break;
}
case NAMED_PROPERTY: {
@ -2604,6 +2629,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
__ li(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
@ -2650,6 +2676,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ mov(StoreDescriptor::NameRegister(), result_register());
__ Pop(StoreDescriptor::ValueRegister(),
StoreDescriptor::ReceiverRegister());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
@ -2673,12 +2700,14 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
}
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
FeedbackVectorICSlot slot) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ mov(StoreDescriptor::ValueRegister(), result_register());
__ li(StoreDescriptor::NameRegister(), Operand(var->name()));
__ lw(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT_LET) {
@ -2773,7 +2802,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
__ li(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
__ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
} else {
CallStoreIC(expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
@ -2826,7 +2860,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
} else {
CallIC(ic, expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
@ -3064,7 +3103,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() {
void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref) {
SuperReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var();
GetVar(a1, this_var);
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@ -3075,7 +3114,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
EmitVariableAssignment(this_var, Token::INIT_CONST);
EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
@ -3300,7 +3339,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
expr->CallFeedbackICSlot());
context()->Plug(v0);
}
@ -4623,6 +4663,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
@ -4825,7 +4866,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@ -4992,7 +5033,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix()) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(v0);
}
@ -5003,7 +5044,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
}
@ -5013,7 +5054,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ li(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
__ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
} else {
CallStoreIC(expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -5052,7 +5098,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
StoreDescriptor::NameRegister());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
} else {
CallIC(ic, expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -5384,6 +5435,13 @@ void FullCodeGenerator::ClearPendingMessage() {
}
void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
DCHECK(FLAG_vector_stores && !slot.IsInvalid());
__ li(VectorStoreICTrampolineDescriptor::SlotRegister(),
Operand(SmiFromSlot(slot)));
}
#undef __

View File

@ -1267,7 +1267,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ mov(result_register(), a3);
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each());
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
@ -1329,13 +1329,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
int offset,
FeedbackVectorICSlot slot) {
if (NeedsHomeObject(initializer)) {
__ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
__ li(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ ld(StoreDescriptor::ValueRegister(),
MemOperand(sp, offset * kPointerSize));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
}
}
@ -1660,6 +1662,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector ic slot for the next store ic used.
// ObjectLiteral::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 (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1687,7 +1693,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(StoreDescriptor::ValueRegister().is(a0));
__ li(StoreDescriptor::NameRegister(), Operand(key->value()));
__ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(key->LiteralFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
}
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
@ -1695,6 +1706,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ li(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ ld(StoreDescriptor::ValueRegister(), MemOperand(sp));
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
}
CallStoreIC();
}
} else {
@ -1708,7 +1722,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
__ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes.
__ push(a0);
__ CallRuntime(Runtime::kSetProperty, 4);
@ -1746,9 +1761,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ push(a0);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitSetHomeObjectIfNeeded(
it->second->getter, 2,
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
EmitSetHomeObjectIfNeeded(
it->second->setter, 3,
expr->SlotForHomeObject(it->second->setter, &store_slot_index));
__ li(a0, Operand(Smi::FromInt(NONE)));
__ push(a0);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
@ -1783,7 +1802,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
@ -1829,6 +1849,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(v0);
}
// 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());
}
@ -1945,7 +1969,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
Property* property = expr->target()->AsProperty();
LhsKind assign_type = GetAssignType(property);
LhsKind assign_type = Property::GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@ -2058,7 +2082,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op());
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
break;
@ -2583,17 +2607,18 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
}
void FullCodeGenerator::EmitAssignment(Expression* expr) {
void FullCodeGenerator::EmitAssignment(Expression* expr,
FeedbackVectorICSlot slot) {
DCHECK(expr->IsValidReferenceExpression());
Property* prop = expr->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var();
EffectContext context(this);
EmitVariableAssignment(var, Token::ASSIGN);
EmitVariableAssignment(var, Token::ASSIGN, slot);
break;
}
case NAMED_PROPERTY: {
@ -2603,6 +2628,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
__ li(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
@ -2649,6 +2675,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Move(StoreDescriptor::NameRegister(), result_register());
__ Pop(StoreDescriptor::ValueRegister(),
StoreDescriptor::ReceiverRegister());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
@ -2672,12 +2699,14 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
}
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
FeedbackVectorICSlot slot) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ mov(StoreDescriptor::ValueRegister(), result_register());
__ li(StoreDescriptor::NameRegister(), Operand(var->name()));
__ ld(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT_LET) {
@ -2776,7 +2805,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
__ li(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
__ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
} else {
CallStoreIC(expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
@ -2829,7 +2863,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
} else {
CallIC(ic, expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
@ -3066,7 +3105,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() {
void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref) {
SuperReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var();
GetVar(a1, this_var);
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@ -3077,7 +3116,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
EmitVariableAssignment(this_var, Token::INIT_CONST);
EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
@ -3302,7 +3341,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
expr->CallFeedbackICSlot());
context()->Plug(v0);
}
@ -4627,6 +4667,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
@ -4828,7 +4869,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@ -4995,7 +5036,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix()) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(v0);
}
@ -5016,7 +5057,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ li(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
__ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
} else {
CallStoreIC(expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -5055,7 +5101,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
StoreDescriptor::NameRegister());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
} else {
CallIC(ic, expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -5387,6 +5438,13 @@ void FullCodeGenerator::ClearPendingMessage() {
}
void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
DCHECK(FLAG_vector_stores && !slot.IsInvalid());
__ li(VectorStoreICTrampolineDescriptor::SlotRegister(),
Operand(SmiFromSlot(slot)));
}
#undef __

View File

@ -23,6 +23,12 @@ TypeFeedbackVector::VectorICKind TypeFeedbackVector::FromCodeKind(
return KindLoadIC;
case Code::KEYED_LOAD_IC:
return KindKeyedLoadIC;
case Code::STORE_IC:
DCHECK(FLAG_vector_stores);
return KindStoreIC;
case Code::KEYED_STORE_IC:
DCHECK(FLAG_vector_stores);
return KindKeyedStoreIC;
default:
// Shouldn't get here.
UNREACHABLE();
@ -41,6 +47,12 @@ Code::Kind TypeFeedbackVector::FromVectorICKind(VectorICKind kind) {
return Code::LOAD_IC;
case KindKeyedLoadIC:
return Code::KEYED_LOAD_IC;
case KindStoreIC:
DCHECK(FLAG_vector_stores);
return Code::STORE_IC;
case KindKeyedStoreIC:
DCHECK(FLAG_vector_stores);
return Code::KEYED_STORE_IC;
case KindUnused:
break;
}
@ -200,6 +212,8 @@ void TypeFeedbackVector::ClearICSlotsImpl(SharedFunctionInfo* shared,
KeyedLoadICNexus nexus(this, slot);
nexus.Clear(host);
}
// TODO(mvstanton): Handle clearing of store ics when FLAG_vector_stores
// is true.
}
}
}

View File

@ -228,10 +228,12 @@ class TypeFeedbackVector : public FixedArray {
KindUnused = 0x0,
KindCallIC = 0x1,
KindLoadIC = 0x2,
KindKeyedLoadIC = 0x3
KindKeyedLoadIC = 0x3,
KindStoreIC = 0x4,
KindKeyedStoreIC = 0x5,
};
static const int kVectorICKindBits = 2;
static const int kVectorICKindBits = 3;
static VectorICKind FromCodeKind(Code::Kind kind);
static Code::Kind FromVectorICKind(VectorICKind kind);
void SetKind(FeedbackVectorICSlot slot, Code::Kind kind);

View File

@ -1244,7 +1244,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ movp(result_register(), rbx);
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each());
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
@ -1305,13 +1305,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
int offset,
FeedbackVectorICSlot slot) {
if (NeedsHomeObject(initializer)) {
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
__ Move(StoreDescriptor::NameRegister(),
isolate()->factory()->home_object_symbol());
__ movp(StoreDescriptor::ValueRegister(),
Operand(rsp, offset * kPointerSize));
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
}
}
@ -1643,6 +1645,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector ic slot for the next store ic used.
// ObjectLiteral::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 (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1669,7 +1675,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(StoreDescriptor::ValueRegister().is(rax));
__ Move(StoreDescriptor::NameRegister(), key->value());
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
CallStoreIC(key->LiteralFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
}
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
@ -1677,6 +1688,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Move(StoreDescriptor::NameRegister(),
isolate()->factory()->home_object_symbol());
__ movp(StoreDescriptor::ValueRegister(), Operand(rsp, 0));
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
}
CallStoreIC();
}
} else {
@ -1688,7 +1702,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
__ Push(Smi::FromInt(SLOPPY)); // Language mode
__ CallRuntime(Runtime::kSetProperty, 4);
} else {
@ -1722,9 +1737,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Push(Operand(rsp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitSetHomeObjectIfNeeded(
it->second->getter, 2,
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
EmitSetHomeObjectIfNeeded(
it->second->setter, 3,
expr->SlotForHomeObject(it->second->setter, &store_slot_index));
__ Push(Smi::FromInt(NONE));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
}
@ -1757,7 +1776,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
EmitSetHomeObjectIfNeeded(
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
@ -1799,6 +1819,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(rax);
}
// 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());
}
@ -1919,7 +1943,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
Property* property = expr->target()->AsProperty();
LhsKind assign_type = GetAssignType(property);
LhsKind assign_type = Property::GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@ -2026,7 +2050,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op());
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
break;
@ -2513,17 +2537,18 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
}
void FullCodeGenerator::EmitAssignment(Expression* expr) {
void FullCodeGenerator::EmitAssignment(Expression* expr,
FeedbackVectorICSlot slot) {
DCHECK(expr->IsValidReferenceExpression());
Property* prop = expr->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var();
EffectContext context(this);
EmitVariableAssignment(var, Token::ASSIGN);
EmitVariableAssignment(var, Token::ASSIGN, slot);
break;
}
case NAMED_PROPERTY: {
@ -2533,6 +2558,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Pop(StoreDescriptor::ValueRegister()); // Restore value.
__ Move(StoreDescriptor::NameRegister(),
prop->key()->AsLiteral()->value());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
@ -2579,6 +2605,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Move(StoreDescriptor::NameRegister(), rax);
__ Pop(StoreDescriptor::ReceiverRegister());
__ Pop(StoreDescriptor::ValueRegister()); // Restore value.
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
@ -2600,12 +2627,13 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
}
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
FeedbackVectorICSlot slot) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ Move(StoreDescriptor::NameRegister(), var->name());
__ movp(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT_LET) {
@ -2698,7 +2726,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
SetSourcePosition(expr->position());
__ Move(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
__ Pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
} else {
CallStoreIC(expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
@ -2745,7 +2778,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
SetSourcePosition(expr->position());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->AssignmentFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
} else {
CallIC(ic, expr->AssignmentFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
@ -2979,7 +3017,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() {
void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref) {
SuperReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var();
GetVar(rcx, this_var);
__ CompareRoot(rcx, Heap::kTheHoleValueRootIndex);
@ -2989,7 +3027,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
EmitVariableAssignment(this_var, Token::INIT_CONST);
EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
@ -3207,7 +3245,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
expr->CallFeedbackICSlot());
context()->Plug(rax);
}
@ -4560,6 +4599,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, rax);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
@ -4764,7 +4804,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = GetAssignType(prop);
LhsKind assign_type = Property::GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@ -4926,7 +4966,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(rax);
}
@ -4938,7 +4978,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} else {
// Perform the assignment as if via '='.
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN);
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
}
@ -4947,7 +4987,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Move(StoreDescriptor::NameRegister(),
prop->key()->AsLiteral()->value());
__ Pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
} else {
CallStoreIC(expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -4985,7 +5030,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Pop(StoreDescriptor::ReceiverRegister());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic, expr->CountStoreFeedbackId());
if (FLAG_vector_stores) {
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
} else {
CallIC(ic, expr->CountStoreFeedbackId());
}
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@ -5320,6 +5370,12 @@ void FullCodeGenerator::ClearPendingMessage() {
}
void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
DCHECK(FLAG_vector_stores && !slot.IsInvalid());
__ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot));
}
#undef __