VisitObjectLiteralProperty(node->properties()->at(i));
}
ReserveFeedbackSlots(node);
+ node->LayoutFeedbackSlots();
}
// marked expressions, no store code will be is emitted.
node->CalculateEmitStore(zone());
ReserveFeedbackSlots(node);
+ node->LayoutFeedbackSlots();
}
bool is_computed_name)
: key_(key),
value_(value),
+ ic_slot_or_count_(FeedbackVectorICSlot::Invalid().ToInt()),
kind_(kind),
emit_store_(true),
is_static_(is_static),
bool is_computed_name)
: key_(key),
value_(value),
+ ic_slot_or_count_(FeedbackVectorICSlot::Invalid().ToInt()),
emit_store_(true),
is_static_(is_static),
is_computed_name_(is_computed_name) {
// This logic that computes the number of slots needed for vector store
// ICs must mirror FullCodeGenerator::VisitClassLiteral.
int ic_slots = 0;
+ if (NeedsProxySlot()) {
+ ic_slots++;
+ }
+
for (int i = 0; i < properties()->length(); i++) {
ObjectLiteral::Property* property = properties()->at(i);
+ // In case we don't end up using any slots.
+ property->set_ic_slot_count(0);
Expression* value = property->value();
- if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
- }
-
- if (scope() != NULL && class_variable_proxy()->var()->IsUnallocated()) {
- ic_slots++;
+ if (FunctionLiteral::NeedsHomeObject(value)) {
+ property->set_ic_slot_count(1);
+ ic_slots++;
+ }
}
-#ifdef DEBUG
- // FullCodeGenerator::VisitClassLiteral verifies that it consumes slot_count_
- // slots.
- slot_count_ = ic_slots;
-#endif
return FeedbackVectorRequirements(0, ic_slots);
}
-FeedbackVectorICSlot ClassLiteral::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;
+void ClassLiteral::LayoutFeedbackSlots() {
+ int base_slot = slot_.ToInt();
+ if (NeedsProxySlot()) base_slot++;
+
+ for (int i = 0; i < properties()->length(); i++) {
+ ObjectLiteral::Property* property = properties()->at(i);
+ base_slot += property->set_base_slot(base_slot);
}
- return FeedbackVectorICSlot::Invalid();
}
}
+void ObjectLiteral::LayoutFeedbackSlots() {
+ int base_slot = slot_.ToInt();
+ for (int i = 0; i < properties()->length(); i++) {
+ ObjectLiteral::Property* property = properties()->at(i);
+ base_slot += property->set_base_slot(base_slot);
+ }
+}
+
+
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;
- bool saw_computed_name = false;
- for (int i = 0; i < properties()->length(); i++) {
- ObjectLiteral::Property* property = properties()->at(i);
+ int property_index = 0;
+ for (; property_index < properties()->length(); property_index++) {
+ ObjectLiteral::Property* property = properties()->at(property_index);
+ // In case we don't end up using any slots.
+ property->set_ic_slot_count(0);
+
+ if (property->is_computed_name()) break;
if (property->IsCompileTimeValue()) continue;
- saw_computed_name |= property->is_computed_name();
+ Literal* key = property->key()->AsLiteral();
Expression* value = property->value();
- if (saw_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++;
- }
+ switch (property->kind()) {
+ case ObjectLiteral::Property::CONSTANT:
+ UNREACHABLE();
+ case ObjectLiteral::Property::MATERIALIZED_LITERAL:
+ // Fall through.
+ case ObjectLiteral::Property::COMPUTED:
+ // It is safe to use [[Put]] here because the boilerplate already
+ // contains computed properties with an uninitialized value.
+ if (key->value()->IsInternalizedString()) {
+ if (property->emit_store()) {
+ int slot_count = 1;
+ if (FunctionLiteral::NeedsHomeObject(value)) {
+ slot_count++;
+ }
+ property->set_ic_slot_count(slot_count);
+ }
+ break;
+ }
+ if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
+ property->set_ic_slot_count(1);
+ }
+ break;
+ case ObjectLiteral::Property::PROTOTYPE:
+ break;
+ case ObjectLiteral::Property::GETTER:
+ if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
+ property->set_ic_slot_count(1);
+ }
+ break;
+ case ObjectLiteral::Property::SETTER:
+ if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
+ property->set_ic_slot_count(1);
+ }
+ break;
}
}
-#ifdef DEBUG
- // FullCodeGenerator::VisitObjectLiteral verifies that it consumes slot_count_
- // slots.
- slot_count_ = ic_slots;
-#endif
- return FeedbackVectorRequirements(0, ic_slots);
-}
+ for (; property_index < properties()->length(); property_index++) {
+ ObjectLiteral::Property* property = properties()->at(property_index);
+ Expression* value = property->value();
+ if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
+ if (FunctionLiteral::NeedsHomeObject(value)) {
+ property->set_ic_slot_count(1);
+ }
+ }
+ }
-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;
+ // How many slots did we allocate?
+ int ic_slots = 0;
+ for (int i = 0; i < properties()->length(); i++) {
+ ObjectLiteral::Property* property = properties()->at(i);
+ ic_slots += property->ic_slot_count();
}
- return FeedbackVectorICSlot::Invalid();
+
+ return FeedbackVectorRequirements(0, ic_slots);
}
bool is_static() const { return is_static_; }
bool is_computed_name() const { return is_computed_name_; }
+ FeedbackVectorICSlot GetSlot(int offset = 0) const {
+ if (ic_slot_or_count_ == FeedbackVectorICSlot::Invalid().ToInt()) {
+ return FeedbackVectorICSlot::Invalid();
+ }
+ return FeedbackVectorICSlot(ic_slot_or_count_ + offset);
+ }
+
+ int ic_slot_count() const {
+ if (ic_slot_or_count_ == FeedbackVectorICSlot::Invalid().ToInt()) {
+ return 0;
+ }
+ return ic_slot_or_count_;
+ }
+
void set_receiver_type(Handle<Map> map) { receiver_type_ = map; }
+ void set_ic_slot_count(int count) {
+ // Should only be called once.
+ if (count == 0) {
+ ic_slot_or_count_ = FeedbackVectorICSlot::Invalid().ToInt();
+ } else {
+ ic_slot_or_count_ = count;
+ }
+ }
+
+ int set_base_slot(int slot) {
+ if (ic_slot_count() > 0) {
+ int count = ic_slot_count();
+ ic_slot_or_count_ = slot;
+ return count;
+ }
+ return 0;
+ }
protected:
friend class AstNodeFactory;
private:
Expression* key_;
Expression* value_;
+ int ic_slot_or_count_;
Kind kind_;
bool emit_store_;
bool is_static_;
struct Accessors: public ZoneObject {
Accessors() : getter(NULL), setter(NULL) {}
- Expression* getter;
- Expression* setter;
+ ObjectLiteralProperty* getter;
+ ObjectLiteralProperty* setter;
};
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
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
+ // After feedback slots were assigned, propagate information to the properties
+ // which need it.
+ void LayoutFeedbackSlots();
protected:
ObjectLiteral(Zone* zone, ZoneList<Property*>* properties, int literal_index,
has_elements_(false),
may_store_doubles_(false),
has_function_(has_function),
-#ifdef DEBUG
- slot_count_(0),
-#endif
slot_(FeedbackVectorICSlot::Invalid()) {
}
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
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_;
};
slot_ = slot;
}
Code::Kind FeedbackICSlotKind(int index) override { return Code::STORE_IC; }
- FeedbackVectorICSlot GetNthSlot(int n) const {
- return FeedbackVectorICSlot(slot_.ToInt() + n);
+
+ bool NeedsProxySlot() const {
+ return FLAG_vector_stores && scope() != NULL &&
+ class_variable_proxy()->var()->IsUnallocated();
}
- // 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;
+ FeedbackVectorICSlot ProxySlot() const { return slot_; }
-#ifdef DEBUG
- int slot_count() const { return slot_count_; }
-#endif
+ // After feedback slots were assigned, propagate information to the properties
+ // which need it.
+ void LayoutFeedbackSlots();
protected:
ClassLiteral(Zone* zone, const AstRawString* name, Scope* scope,
constructor_(constructor),
properties_(properties),
end_position_(end_position),
-#ifdef DEBUG
- slot_count_(0),
-#endif
slot_(FeedbackVectorICSlot::Invalid()) {
}
FunctionLiteral* constructor_;
ZoneList<Property*>* properties_;
int end_position_;
-#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_;
};
environment()->Push(proto);
// Create nodes to store method values into the literal.
- int store_slot_index = 0;
for (int i = 0; i < expr->properties()->length(); i++) {
ObjectLiteral::Property* property = expr->properties()->at(i);
environment()->Push(property->is_static() ? literal : proto);
Node* value = environment()->Pop();
Node* key = environment()->Pop();
Node* receiver = environment()->Pop();
- VectorSlotPair feedback = CreateVectorSlotPair(
- expr->SlotForHomeObject(property->value(), &store_slot_index));
- BuildSetHomeObject(value, receiver, property->value(), feedback);
+
+ BuildSetHomeObject(value, receiver, property);
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
DCHECK_NOT_NULL(expr->class_variable_proxy());
Variable* var = expr->class_variable_proxy()->var();
FrameStateBeforeAndAfter states(this, BailoutId::None());
- VectorSlotPair feedback =
- CreateVectorSlotPair(FLAG_vector_stores && var->IsUnallocated()
- ? expr->GetNthSlot(store_slot_index++)
- : FeedbackVectorICSlot::Invalid());
+ VectorSlotPair feedback = CreateVectorSlotPair(
+ expr->NeedsProxySlot() ? expr->ProxySlot()
+ : FeedbackVectorICSlot::Invalid());
BuildVariableAssignment(var, literal, Token::INIT_CONST, feedback,
BailoutId::None(), states);
}
// Create nodes to store computed values into the literal.
int property_index = 0;
- int store_slot_index = 0;
AccessorTable accessor_table(zone());
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
Node* value = environment()->Pop();
Handle<Name> name = key->AsPropertyName();
VectorSlotPair feedback =
- FLAG_vector_stores
- ? CreateVectorSlotPair(expr->GetNthSlot(store_slot_index++))
- : VectorSlotPair();
+ CreateVectorSlotPair(property->GetSlot(0));
Node* store = BuildNamedStore(literal, name, value, feedback,
TypeFeedbackId::None());
states.AddToNode(store, key->id(),
OutputFrameStateCombine::Ignore());
- VectorSlotPair home_feedback = CreateVectorSlotPair(
- expr->SlotForHomeObject(property->value(), &store_slot_index));
- BuildSetHomeObject(value, literal, property->value(),
- home_feedback);
+ BuildSetHomeObject(value, literal, property, 1);
} else {
VisitForEffect(property->value());
}
Node* set_property = NewNode(op, receiver, key, value, language);
// SetProperty should not lazy deopt on an object literal.
PrepareFrameState(set_property, BailoutId::None());
- VectorSlotPair home_feedback = CreateVectorSlotPair(
- expr->SlotForHomeObject(property->value(), &store_slot_index));
- BuildSetHomeObject(value, receiver, property->value(), home_feedback);
+ BuildSetHomeObject(value, receiver, property);
}
break;
}
}
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->getter = property->value();
+ accessor_table.lookup(key)->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->setter = property->value();
+ accessor_table.lookup(key)->second->setter = property;
}
break;
}
for (AccessorTable::Iterator it = accessor_table.begin();
it != accessor_table.end(); ++it) {
VisitForValue(it->first);
- VisitForValueOrNull(it->second->getter);
- VectorSlotPair feedback_getter = CreateVectorSlotPair(
- expr->SlotForHomeObject(it->second->getter, &store_slot_index));
- BuildSetHomeObject(environment()->Top(), literal, it->second->getter,
- feedback_getter);
- VisitForValueOrNull(it->second->setter);
- VectorSlotPair feedback_setter = CreateVectorSlotPair(
- expr->SlotForHomeObject(it->second->setter, &store_slot_index));
- BuildSetHomeObject(environment()->Top(), literal, it->second->setter,
- feedback_setter);
+ VisitObjectLiteralAccessor(literal, it->second->getter);
+ VisitObjectLiteralAccessor(literal, it->second->setter);
Node* setter = environment()->Pop();
Node* getter = environment()->Pop();
Node* name = environment()->Pop();
Node* value = environment()->Pop();
Node* key = environment()->Pop();
Node* receiver = environment()->Pop();
- VectorSlotPair feedback = CreateVectorSlotPair(
- expr->SlotForHomeObject(property->value(), &store_slot_index));
- BuildSetHomeObject(value, receiver, property->value(), feedback);
+ BuildSetHomeObject(value, receiver, property);
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
case ObjectLiteral::Property::COMPUTED:
NewNode(op, literal);
}
- // Verify that compilation exactly consumed the number of store ic slots that
- // the ObjectLiteral node had to offer.
- DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
-
ast_context()->ProduceValue(environment()->Pop());
}
+void AstGraphBuilder::VisitObjectLiteralAccessor(
+ Node* home_object, ObjectLiteralProperty* property) {
+ if (property == nullptr) {
+ VisitForValueOrNull(nullptr);
+ } else {
+ VisitForValue(property->value());
+ BuildSetHomeObject(environment()->Top(), home_object, property);
+ }
+}
+
+
void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
Node* closure = GetFunctionClosure();
Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
- Expression* expr,
- const VectorSlotPair& feedback) {
+ ObjectLiteralProperty* property,
+ int slot_number) {
+ Expression* expr = property->value();
if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
Handle<Name> name = isolate()->factory()->home_object_symbol();
FrameStateBeforeAndAfter states(this, BailoutId::None());
+ VectorSlotPair feedback =
+ CreateVectorSlotPair(property->GetSlot(slot_number));
Node* store = BuildNamedStore(value, name, home_object, feedback,
TypeFeedbackId::None());
states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
// Builder for adding the [[HomeObject]] to a value if the value came from a
// function literal and needs a home object. Do nothing otherwise.
- Node* BuildSetHomeObject(Node* value, Node* home_object, Expression* expr,
- const VectorSlotPair& feedback);
+ Node* BuildSetHomeObject(Node* value, Node* home_object,
+ ObjectLiteralProperty* property,
+ int slot_number = 0);
// Builders for error reporting at runtime.
Node* BuildThrowError(Node* exception, BailoutId bailout_id);
const VectorSlotPair& feedback,
BailoutId bailout_id);
+ // Dispatched from VisitObjectLiteral.
+ void VisitObjectLiteralAccessor(Node* home_object,
+ ObjectLiteralProperty* property);
+
// Dispatched from VisitClassLiteral.
void VisitClassLiteralContents(ClassLiteral* expr);
}
-void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
- 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();
- }
+void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
+ FeedbackVectorICSlot slot) {
+ DCHECK(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();
+}
+
+
+void FullCodeGenerator::EmitSetHomeObjectAccumulator(
+ Expression* initializer, int offset, FeedbackVectorICSlot slot) {
+ DCHECK(NeedsHomeObject(initializer));
+ __ Move(StoreDescriptor::ReceiverRegister(), r0);
+ __ mov(StoreDescriptor::NameRegister(),
+ Operand(isolate()->factory()->home_object_symbol()));
+ __ ldr(StoreDescriptor::ValueRegister(),
+ MemOperand(sp, offset * kPointerSize));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
+ CallStoreIC();
}
}
-void FullCodeGenerator::EmitAccessor(Expression* expression) {
+void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
+ Expression* expression = (property == NULL) ? NULL : property->value();
if (expression == NULL) {
__ LoadRoot(r1, Heap::kNullValueRootIndex);
__ push(r1);
} else {
VisitForStackValue(expression);
+ if (NeedsHomeObject(expression)) {
+ DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
+ property->kind() == ObjectLiteral::Property::SETTER);
+ int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
+ EmitSetHomeObject(expression, offset, property->GetSlot());
+ }
}
}
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;
__ mov(StoreDescriptor::NameRegister(), Operand(key->value()));
__ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
if (FLAG_vector_stores) {
- EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
+ EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
- __ Move(StoreDescriptor::ReceiverRegister(), r0);
- __ 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();
+ EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
}
} else {
VisitForEffect(value);
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- EmitSetHomeObjectIfNeeded(
- value, 2, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
__ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes
__ push(r0);
__ CallRuntime(Runtime::kSetProperty, 4);
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->getter = value;
+ accessor_table.lookup(key)->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->setter = value;
+ accessor_table.lookup(key)->second->setter = property;
}
break;
}
__ push(r0);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
- EmitSetHomeObjectIfNeeded(
- it->second->getter, 2,
- expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
- 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, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
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());
}
}
-void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
- int* used_store_slots) {
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in r0.
DCHECK(lit != NULL);
__ push(r0);
}
VisitForStackValue(value);
- EmitSetHomeObjectIfNeeded(value, 2,
- lit->SlotForHomeObject(value, used_store_slots));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
}
-void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
- 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();
- }
+void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
+ FeedbackVectorICSlot slot) {
+ DCHECK(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();
+}
+
+
+void FullCodeGenerator::EmitSetHomeObjectAccumulator(
+ Expression* initializer, int offset, FeedbackVectorICSlot slot) {
+ DCHECK(NeedsHomeObject(initializer));
+ __ Move(StoreDescriptor::ReceiverRegister(), x0);
+ __ Mov(StoreDescriptor::NameRegister(),
+ Operand(isolate()->factory()->home_object_symbol()));
+ __ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize);
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
+ CallStoreIC();
}
}
-void FullCodeGenerator::EmitAccessor(Expression* expression) {
+void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
+ Expression* expression = (property == NULL) ? NULL : property->value();
if (expression == NULL) {
__ LoadRoot(x10, Heap::kNullValueRootIndex);
__ Push(x10);
} else {
VisitForStackValue(expression);
+ if (NeedsHomeObject(expression)) {
+ DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
+ property->kind() == ObjectLiteral::Property::SETTER);
+ int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
+ EmitSetHomeObject(expression, offset, property->GetSlot());
+ }
}
}
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;
__ Mov(StoreDescriptor::NameRegister(), Operand(key->value()));
__ Peek(StoreDescriptor::ReceiverRegister(), 0);
if (FLAG_vector_stores) {
- EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
+ EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
- __ Mov(StoreDescriptor::ReceiverRegister(), x0);
- __ Mov(StoreDescriptor::NameRegister(),
- Operand(isolate()->factory()->home_object_symbol()));
- __ Peek(StoreDescriptor::ValueRegister(), 0);
- if (FLAG_vector_stores) {
- EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
- }
- CallStoreIC();
+ EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
}
} else {
VisitForEffect(value);
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- EmitSetHomeObjectIfNeeded(
- value, 2, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
__ Mov(x0, Smi::FromInt(SLOPPY)); // Language mode
__ Push(x0);
__ CallRuntime(Runtime::kSetProperty, 4);
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->getter = value;
+ accessor_table.lookup(key)->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->setter = value;
+ accessor_table.lookup(key)->second->setter = property;
}
break;
}
__ Push(x10);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
- EmitSetHomeObjectIfNeeded(
- it->second->getter, 2,
- expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
- 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, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
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());
}
}
-void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
- int* used_store_slots) {
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in x0.
DCHECK(lit != NULL);
__ push(x0);
}
VisitForStackValue(value);
- EmitSetHomeObjectIfNeeded(value, 2,
- lit->SlotForHomeObject(value, used_store_slots));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
__ CallRuntime(Runtime::kDefineClass, 5);
PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);
- int store_slot_index = 0;
- EmitClassDefineProperties(lit, &store_slot_index);
+ EmitClassDefineProperties(lit);
if (lit->scope() != NULL) {
DCHECK_NOT_NULL(lit->class_variable_proxy());
- FeedbackVectorICSlot slot =
- FLAG_vector_stores &&
- lit->class_variable_proxy()->var()->IsUnallocated()
- ? lit->GetNthSlot(store_slot_index++)
- : FeedbackVectorICSlot::Invalid();
EmitVariableAssignment(lit->class_variable_proxy()->var(),
- Token::INIT_CONST, slot);
+ Token::INIT_CONST, lit->ProxySlot());
}
-
- // Verify that compilation exactly consumed the number of store ic slots
- // that the ClassLiteral node had to offer.
- DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
}
context()->Plug(result_register());
void EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
- void EmitAccessor(Expression* expression);
+ void EmitAccessor(ObjectLiteralProperty* property);
bool NeedsHoleCheckForLoad(VariableProxy* proxy);
// Adds the properties to the class (function) object and to its prototype.
// Expects the class (function) in the accumulator. The class (function) is
// in the accumulator after installing all the properties.
- void EmitClassDefineProperties(ClassLiteral* lit, int* used_store_slots);
+ void EmitClassDefineProperties(ClassLiteral* lit);
// Pushes the property key as a Name on the stack.
void EmitPropertyKey(ObjectLiteralProperty* property, BailoutId bailout_id);
// 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,
- FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
+ void EmitSetHomeObject(Expression* initializer, int offset,
+ FeedbackVectorICSlot slot);
+
+ void EmitSetHomeObjectAccumulator(Expression* initializer, int offset,
+ FeedbackVectorICSlot slot);
void EmitLoadSuperConstructor(SuperCallReference* super_call_ref);
}
-void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
- 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();
- }
+void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
+ FeedbackVectorICSlot slot) {
+ DCHECK(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();
+}
+
+
+void FullCodeGenerator::EmitSetHomeObjectAccumulator(
+ Expression* initializer, int offset, FeedbackVectorICSlot slot) {
+ DCHECK(NeedsHomeObject(initializer));
+ __ mov(StoreDescriptor::ReceiverRegister(), eax);
+ __ mov(StoreDescriptor::NameRegister(),
+ Immediate(isolate()->factory()->home_object_symbol()));
+ __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
+ CallStoreIC();
}
}
-void FullCodeGenerator::EmitAccessor(Expression* expression) {
+void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
+ Expression* expression = (property == NULL) ? NULL : property->value();
if (expression == NULL) {
__ push(Immediate(isolate()->factory()->null_value()));
} else {
VisitForStackValue(expression);
+ if (NeedsHomeObject(expression)) {
+ DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
+ property->kind() == ObjectLiteral::Property::SETTER);
+ int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
+ EmitSetHomeObject(expression, offset, property->GetSlot());
+ }
}
}
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;
__ mov(StoreDescriptor::NameRegister(), Immediate(key->value()));
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
if (FLAG_vector_stores) {
- EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
+ EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
}
PrepareForBailoutForId(key->id(), NO_REGISTERS);
-
if (NeedsHomeObject(value)) {
- __ mov(StoreDescriptor::ReceiverRegister(), eax);
- __ 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();
+ EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
}
} else {
VisitForEffect(value);
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- EmitSetHomeObjectIfNeeded(
- value, 2, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
__ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode
__ CallRuntime(Runtime::kSetProperty, 4);
} else {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->getter = value;
+ accessor_table.lookup(key)->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->setter = value;
+ accessor_table.lookup(key)->second->setter = property;
}
break;
}
++it) {
__ push(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
- EmitAccessor(it->second->getter);
- EmitSetHomeObjectIfNeeded(
- it->second->getter, 2,
- expr->SlotForHomeObject(it->second->getter, &store_slot_index));
+ EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
- 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, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
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());
}
}
-void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
- int* used_store_slots) {
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in eax.
DCHECK(lit != NULL);
__ push(eax);
}
VisitForStackValue(value);
- EmitSetHomeObjectIfNeeded(value, 2,
- lit->SlotForHomeObject(value, used_store_slots));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
}
-void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
- 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();
- }
+void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
+ FeedbackVectorICSlot slot) {
+ DCHECK(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();
+}
+
+
+void FullCodeGenerator::EmitSetHomeObjectAccumulator(
+ Expression* initializer, int offset, FeedbackVectorICSlot slot) {
+ DCHECK(NeedsHomeObject(initializer));
+ __ Move(StoreDescriptor::ReceiverRegister(), v0);
+ __ li(StoreDescriptor::NameRegister(),
+ Operand(isolate()->factory()->home_object_symbol()));
+ __ lw(StoreDescriptor::ValueRegister(),
+ MemOperand(sp, offset * kPointerSize));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
+ CallStoreIC();
}
}
-void FullCodeGenerator::EmitAccessor(Expression* expression) {
+void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
+ Expression* expression = (property == NULL) ? NULL : property->value();
if (expression == NULL) {
__ LoadRoot(a1, Heap::kNullValueRootIndex);
__ push(a1);
} else {
VisitForStackValue(expression);
+ if (NeedsHomeObject(expression)) {
+ DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
+ property->kind() == ObjectLiteral::Property::SETTER);
+ int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
+ EmitSetHomeObject(expression, offset, property->GetSlot());
+ }
}
}
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;
__ li(StoreDescriptor::NameRegister(), Operand(key->value()));
__ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
if (FLAG_vector_stores) {
- EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
+ EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
- __ Move(StoreDescriptor::ReceiverRegister(), v0);
- __ 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();
+ EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
}
} else {
VisitForEffect(value);
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- EmitSetHomeObjectIfNeeded(
- value, 2, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
__ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes.
__ push(a0);
__ CallRuntime(Runtime::kSetProperty, 4);
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->getter = value;
+ accessor_table.lookup(key)->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->setter = value;
+ accessor_table.lookup(key)->second->setter = property;
}
break;
}
__ push(a0);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
- EmitSetHomeObjectIfNeeded(
- it->second->getter, 2,
- expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
- 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, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
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());
}
}
-void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
- int* used_store_slots) {
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in v0.
DCHECK(lit != NULL);
__ push(v0);
}
VisitForStackValue(value);
- EmitSetHomeObjectIfNeeded(value, 2,
- lit->SlotForHomeObject(value, used_store_slots));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
// Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
- // ignored.
+ // ignored.g
DCHECK(!expr->expression()->IsSuperPropertyReference());
VisitForStackValue(expr->expression());
}
-void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
- 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();
- }
+void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
+ FeedbackVectorICSlot slot) {
+ DCHECK(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();
+}
+
+
+void FullCodeGenerator::EmitSetHomeObjectAccumulator(
+ Expression* initializer, int offset, FeedbackVectorICSlot slot) {
+ DCHECK(NeedsHomeObject(initializer));
+ __ Move(StoreDescriptor::ReceiverRegister(), v0);
+ __ li(StoreDescriptor::NameRegister(),
+ Operand(isolate()->factory()->home_object_symbol()));
+ __ ld(StoreDescriptor::ValueRegister(),
+ MemOperand(sp, offset * kPointerSize));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
+ CallStoreIC();
}
}
-void FullCodeGenerator::EmitAccessor(Expression* expression) {
+void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
+ Expression* expression = (property == NULL) ? NULL : property->value();
if (expression == NULL) {
__ LoadRoot(a1, Heap::kNullValueRootIndex);
__ push(a1);
} else {
VisitForStackValue(expression);
+ if (NeedsHomeObject(expression)) {
+ DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
+ property->kind() == ObjectLiteral::Property::SETTER);
+ int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
+ EmitSetHomeObject(expression, offset, property->GetSlot());
+ }
}
}
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;
__ li(StoreDescriptor::NameRegister(), Operand(key->value()));
__ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
if (FLAG_vector_stores) {
- EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
+ EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
- __ Move(StoreDescriptor::ReceiverRegister(), v0);
- __ 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();
+ EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
}
} else {
VisitForEffect(value);
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- EmitSetHomeObjectIfNeeded(
- value, 2, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
__ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes.
__ push(a0);
__ CallRuntime(Runtime::kSetProperty, 4);
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->getter = value;
+ accessor_table.lookup(key)->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->setter = value;
+ accessor_table.lookup(key)->second->setter = property;
}
break;
}
__ push(a0);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
- EmitSetHomeObjectIfNeeded(
- it->second->getter, 2,
- expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
- 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, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
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());
}
}
-void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
- int* used_store_slots) {
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in v0.
DCHECK(lit != NULL);
__ push(v0);
}
VisitForStackValue(value);
- EmitSetHomeObjectIfNeeded(value, 2,
- lit->SlotForHomeObject(value, used_store_slots));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
}
-void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
- 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();
- }
+void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
+ FeedbackVectorICSlot slot) {
+ DCHECK(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();
+}
+
+
+void FullCodeGenerator::EmitSetHomeObjectAccumulator(
+ Expression* initializer, int offset, FeedbackVectorICSlot slot) {
+ DCHECK(NeedsHomeObject(initializer));
+ __ movp(StoreDescriptor::ReceiverRegister(), rax);
+ __ Move(StoreDescriptor::NameRegister(),
+ isolate()->factory()->home_object_symbol());
+ __ movp(StoreDescriptor::ValueRegister(),
+ Operand(rsp, offset * kPointerSize));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
+ CallStoreIC();
}
}
-void FullCodeGenerator::EmitAccessor(Expression* expression) {
+void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
+ Expression* expression = (property == NULL) ? NULL : property->value();
if (expression == NULL) {
__ PushRoot(Heap::kNullValueRootIndex);
} else {
VisitForStackValue(expression);
+ if (NeedsHomeObject(expression)) {
+ DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
+ property->kind() == ObjectLiteral::Property::SETTER);
+ int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
+ EmitSetHomeObject(expression, offset, property->GetSlot());
+ }
}
}
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;
__ Move(StoreDescriptor::NameRegister(), key->value());
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
if (FLAG_vector_stores) {
- EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
+ EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
} else {
CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
- __ movp(StoreDescriptor::ReceiverRegister(), rax);
- __ 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();
+ EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
}
} else {
VisitForEffect(value);
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- EmitSetHomeObjectIfNeeded(
- value, 2, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
__ Push(Smi::FromInt(SLOPPY)); // Language mode
__ CallRuntime(Runtime::kSetProperty, 4);
} else {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->getter = value;
+ accessor_table.lookup(key)->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
- accessor_table.lookup(key)->second->setter = value;
+ accessor_table.lookup(key)->second->setter = property;
}
break;
}
__ Push(Operand(rsp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
- EmitSetHomeObjectIfNeeded(
- it->second->getter, 2,
- expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
- 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, expr->SlotForHomeObject(value, &store_slot_index));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
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());
}
}
-void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
- int* used_store_slots) {
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in rax.
DCHECK(lit != NULL);
__ Push(rax);
}
VisitForStackValue(value);
- EmitSetHomeObjectIfNeeded(value, 2,
- lit->SlotForHomeObject(value, used_store_slots));
+ if (NeedsHomeObject(value)) {
+ EmitSetHomeObject(value, 2, property->GetSlot());
+ }
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
// The object is expected in the bailout environment during computation
// of the property values and is the value of the entire expression.
Push(literal);
- int store_slot_index = 0;
for (int i = 0; i < expr->properties()->length(); i++) {
ObjectLiteral::Property* property = expr->properties()->at(i);
if (property->is_computed_name()) return Bailout(kComputedPropertyName);
Handle<Map> map = property->GetReceiverType();
Handle<String> name = key->AsPropertyName();
HValue* store;
- FeedbackVectorICSlot slot = expr->GetNthSlot(store_slot_index++);
+ FeedbackVectorICSlot slot = property->GetSlot();
if (map.is_null()) {
// If we don't know the monomorphic type, do a generic store.
CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
if (FunctionLiteral::NeedsHomeObject(property->value())) {
Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
HInstruction* store_home = BuildNamedGeneric(
- STORE, NULL, expr->GetNthSlot(store_slot_index++), value, sym,
- literal);
+ STORE, NULL, property->GetSlot(1), value, sym, literal);
AddInstruction(store_home);
DCHECK(store_home->HasObservableSideEffects());
Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
}
}
- // Crankshaft may not consume all the slots because it doesn't emit accessors.
- DCHECK(!FLAG_vector_stores || store_slot_index <= expr->slot_count());
-
if (expr->has_function()) {
// Return the result of the transformation to fast properties
// instead of the original since this operation changes the map
void TypeFeedbackOracle::GetStoreModeAndKeyType(
FeedbackVectorICSlot slot, KeyedAccessStoreMode* store_mode,
IcCheckType* key_type) {
- if (!slot.IsInvalid()) {
+ if (!slot.IsInvalid() &&
+ feedback_vector_->GetKind(slot) == Code::KEYED_STORE_IC) {
KeyedStoreICNexus nexus(feedback_vector_, slot);
*store_mode = nexus.GetKeyedAccessStoreMode();
*key_type = nexus.GetKeyType();
}
+void TypeFeedbackOracle::CountReceiverTypes(FeedbackVectorICSlot slot,
+ SmallMapList* receiver_types) {
+ receiver_types->Clear();
+ if (!slot.IsInvalid()) CollectReceiverTypes(slot, receiver_types);
+}
+
+
void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorICSlot slot,
Handle<Name> name,
Code::Flags flags,
void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorICSlot slot,
SmallMapList* types) {
- KeyedStoreICNexus nexus(feedback_vector_, slot);
- CollectReceiverTypes<FeedbackNexus>(&nexus, types);
+ Code::Kind kind = feedback_vector_->GetKind(slot);
+ if (kind == Code::STORE_IC) {
+ StoreICNexus nexus(feedback_vector_, slot);
+ CollectReceiverTypes<FeedbackNexus>(&nexus, types);
+ } else {
+ DCHECK(kind == Code::KEYED_STORE_IC);
+ KeyedStoreICNexus nexus(feedback_vector_, slot);
+ CollectReceiverTypes<FeedbackNexus>(&nexus, types);
+ }
}
IcCheckType* key_type);
void CountReceiverTypes(TypeFeedbackId id,
SmallMapList* receiver_types);
+ void CountReceiverTypes(FeedbackVectorICSlot slot,
+ SmallMapList* receiver_types);
void CollectReceiverTypes(FeedbackVectorICSlot slot, SmallMapList* types);
void CollectReceiverTypes(TypeFeedbackId id,
prop->emit_store()) {
// Record type feed back for the property.
TypeFeedbackId id = prop->key()->AsLiteral()->LiteralFeedbackId();
+ FeedbackVectorICSlot slot = prop->GetSlot();
SmallMapList maps;
- oracle()->CollectReceiverTypes(id, &maps);
+ if (FLAG_vector_stores) {
+ oracle()->CollectReceiverTypes(slot, &maps);
+ } else {
+ oracle()->CollectReceiverTypes(id, &maps);
+ }
prop->set_receiver_type(maps.length() == 1 ? maps.at(0)
: Handle<Map>::null());
}
void AstTyper::VisitCountOperation(CountOperation* expr) {
// Collect type feedback.
TypeFeedbackId store_id = expr->CountStoreFeedbackId();
+ FeedbackVectorICSlot slot = expr->CountSlot();
KeyedAccessStoreMode store_mode;
IcCheckType key_type;
- oracle()->GetStoreModeAndKeyType(store_id, &store_mode, &key_type);
+ if (FLAG_vector_stores) {
+ oracle()->GetStoreModeAndKeyType(slot, &store_mode, &key_type);
+ oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes());
+ } else {
+ oracle()->GetStoreModeAndKeyType(store_id, &store_mode, &key_type);
+ oracle()->CountReceiverTypes(store_id, expr->GetReceiverTypes());
+ }
expr->set_store_mode(store_mode);
expr->set_key_type(key_type);
- oracle()->CountReceiverTypes(store_id, expr->GetReceiverTypes());
expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId()));
// TODO(rossberg): merge the count type with the generic expression type.