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:
parent
42fc431078
commit
5450fc07ba
@ -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 __
|
||||
|
||||
|
||||
|
@ -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 __
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
126
src/ast.cc
126
src/ast.cc
@ -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
134
src/ast.h
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 __
|
||||
|
||||
|
||||
|
@ -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 __
|
||||
|
||||
|
||||
|
@ -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 __
|
||||
|
||||
|
||||
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 __
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user