__ 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);
}
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();
}
}
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;
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)) {
__ 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 {
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);
__ 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);
} 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:
} 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());
}
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) {
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;
}
-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: {
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
__ mov(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
__ 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);
}
-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) {
__ 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);
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);
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);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
- EmitVariableAssignment(this_var, Token::INIT_CONST);
+ EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
+ EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
+ expr->CallFeedbackICSlot());
context()->Plug(r0);
}
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r0);
+ // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
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) {
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);
}
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
- Token::ASSIGN);
+ Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
}
__ 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()) {
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()) {
}
+void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
+ DCHECK(FLAG_vector_stores && !slot.IsInvalid());
+ __ mov(VectorStoreICTrampolineDescriptor::SlotRegister(),
+ Operand(SmiFromSlot(slot)));
+}
+
+
#undef __
__ 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);
}
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();
}
}
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;
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)) {
__ 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 {
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);
__ 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);
} 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:
} 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());
}
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) {
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;
}
-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: {
__ Pop(StoreDescriptor::ValueRegister()); // Restore value.
__ Mov(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
__ 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);
}
-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) {
__ 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);
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);
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;
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
- EmitVariableAssignment(this_var, Token::INIT_CONST);
+ EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
+ EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
+ expr->CallFeedbackICSlot());
context()->Plug(x0);
}
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, x0);
+ // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
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) {
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);
}
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
- Token::ASSIGN);
+ Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
}
__ 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()) {
__ 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()) {
}
+void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
+ DCHECK(FLAG_vector_stores && !slot.IsInvalid());
+ __ Mov(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot));
+}
+
+
#undef __
if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
Visit(node->target());
Visit(node->value());
+ ReserveFeedbackSlots(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);
}
Visit(node->result_done());
Visit(node->assign_each());
Visit(node->body());
+ ReserveFeedbackSlots(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);
}
}
+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 {
}
+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;
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;
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;
}
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);
}
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_;
};
}
// 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;
// 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:
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_;
};
};
+// 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)
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),
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()) {
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)) {
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_;
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:
Type* type_;
Expression* expression_;
SmallMapList receiver_types_;
+ FeedbackVectorICSlot slot_;
};
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);
Expression* value_;
BinaryOperation* binary_operation_;
SmallMapList receiver_types_;
+ FeedbackVectorICSlot slot_;
};
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);
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,
// 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());
bool MustCreateObjectLiteralWithRuntime(ObjectLiteral* expr) const;
bool MustCreateArrayLiteralWithRuntime(ArrayLiteral* expr) const;
+ void EmitLoadStoreICSlot(FeedbackVectorICSlot slot);
+
Handle<HandlerTable> handler_table() { return handler_table_; }
struct BailoutEntry {
__ 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);
}
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();
}
}
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;
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)) {
__ 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 {
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 {
__ 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);
}
} 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:
} 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());
}
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) {
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;
}
-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: {
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
__ mov(StoreDescriptor::NameRegister(),
prop->key()->AsLiteral()->value());
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
__ 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);
}
-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) {
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);
}
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);
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());
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
- EmitVariableAssignment(this_var, Token::INIT_CONST);
+ EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
+ EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
+ expr->CallFeedbackICSlot());
context()->Plug(eax);
}
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, eax);
+ // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
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) {
// 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);
}
} 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);
}
__ 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()) {
__ 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
}
+void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
+ DCHECK(FLAG_vector_stores && !slot.IsInvalid());
+ __ mov(VectorStoreICTrampolineDescriptor::SlotRegister(),
+ Immediate(SmiFromSlot(slot)));
+}
+
+
#undef __
__ 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);
}
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();
}
}
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;
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)) {
__ 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 {
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);
__ 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);
} 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:
} 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());
}
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) {
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;
}
-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: {
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
__ li(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
__ 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);
}
-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) {
__ 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);
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);
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);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
- EmitVariableAssignment(this_var, Token::INIT_CONST);
+ EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
+ EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
+ expr->CallFeedbackICSlot());
context()->Plug(v0);
}
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
+ // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
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) {
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);
}
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
- Token::ASSIGN);
+ Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
}
__ 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()) {
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()) {
}
+void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
+ DCHECK(FLAG_vector_stores && !slot.IsInvalid());
+ __ li(VectorStoreICTrampolineDescriptor::SlotRegister(),
+ Operand(SmiFromSlot(slot)));
+}
+
+
#undef __
__ 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);
}
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();
}
}
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;
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)) {
__ 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 {
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);
__ 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);
} 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:
} 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());
}
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) {
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;
}
-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: {
__ pop(StoreDescriptor::ValueRegister()); // Restore value.
__ li(StoreDescriptor::NameRegister(),
Operand(prop->key()->AsLiteral()->value()));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
__ 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);
}
-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) {
__ 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);
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);
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);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
- EmitVariableAssignment(this_var, Token::INIT_CONST);
+ EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
+ EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
+ expr->CallFeedbackICSlot());
context()->Plug(v0);
}
__ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
+ // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
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) {
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);
}
__ 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()) {
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()) {
}
+void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
+ DCHECK(FLAG_vector_stores && !slot.IsInvalid());
+ __ li(VectorStoreICTrampolineDescriptor::SlotRegister(),
+ Operand(SmiFromSlot(slot)));
+}
+
+
#undef __
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();
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;
}
KeyedLoadICNexus nexus(this, slot);
nexus.Clear(host);
}
+ // TODO(mvstanton): Handle clearing of store ics when FLAG_vector_stores
+ // is true.
}
}
}
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);
__ 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);
}
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();
}
}
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;
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)) {
__ 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 {
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 {
__ 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);
}
} 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:
} 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());
}
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) {
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;
}
-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: {
__ Pop(StoreDescriptor::ValueRegister()); // Restore value.
__ Move(StoreDescriptor::NameRegister(),
prop->key()->AsLiteral()->value());
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
__ 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);
}
-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) {
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);
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);
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);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
- EmitVariableAssignment(this_var, Token::INIT_CONST);
+ EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
}
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
+ EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
+ expr->CallFeedbackICSlot());
context()->Plug(rax);
}
__ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, rax);
+ // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference);
}
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) {
// 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);
}
} 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);
}
__ 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()) {
__ 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()) {
}
+void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
+ DCHECK(FLAG_vector_stores && !slot.IsInvalid());
+ __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot));
+}
+
+
#undef __