Vector ICs: The Oracle needs to report feedback for the object literals and the count operation.

The refactoring is because it's awkward and error-prone to deterimine which IC slot an
ObjectLiteralProperty uses for feedback. The fix is for each one to know it's own slot. In the
numbering pass, we allocate slots for the ObjectLiteral, then hand out those slots into the
properties.

It adds one word to the ObjectLiteralProperty expression - I'm investigating if thats a
problem.

This changes makes compiling the object literal cleaner across the three compilers. Also, the
slot allocation logic in ObjectLiteral::ComputeFeedbackRequirements() was refactoring to mimic
the style in full-codegen. This is useful since it must remain in sync with
FullCodegen::VisitObjectLiteral().

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

Cr-Commit-Position: refs/heads/master@{#30686}
This commit is contained in:
mvstanton 2015-09-10 08:02:21 -07:00 committed by Commit bot
parent 33ec0b79b8
commit 752b0308df
17 changed files with 486 additions and 444 deletions

View File

@ -463,6 +463,7 @@ void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
VisitObjectLiteralProperty(node->properties()->at(i));
}
ReserveFeedbackSlots(node);
node->LayoutFeedbackSlots();
}
@ -478,6 +479,7 @@ void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
// marked expressions, no store code will be is emitted.
node->CalculateEmitStore(zone());
ReserveFeedbackSlots(node);
node->LayoutFeedbackSlots();
}

View File

@ -251,6 +251,7 @@ ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
bool is_computed_name)
: key_(key),
value_(value),
ic_slot_or_count_(FeedbackVectorICSlot::Invalid().ToInt()),
kind_(kind),
emit_store_(true),
is_static_(is_static),
@ -263,6 +264,7 @@ ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
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) {
@ -287,35 +289,34 @@ FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements(
// This logic that computes the number of slots needed for vector store
// ICs must mirror FullCodeGenerator::VisitClassLiteral.
int ic_slots = 0;
for (int i = 0; i < properties()->length(); i++) {
ObjectLiteral::Property* property = properties()->at(i);
Expression* value = property->value();
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
}
if (scope() != NULL && class_variable_proxy()->var()->IsUnallocated()) {
if (NeedsProxySlot()) {
ic_slots++;
}
#ifdef DEBUG
// FullCodeGenerator::VisitClassLiteral verifies that it consumes slot_count_
// slots.
slot_count_ = ic_slots;
#endif
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)) {
property->set_ic_slot_count(1);
ic_slots++;
}
}
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();
}
@ -336,55 +337,88 @@ bool ObjectLiteral::Property::emit_store() {
}
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();
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;
}
}
for (; property_index < properties()->length(); property_index++) {
ObjectLiteral::Property* property = properties()->at(property_index);
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++;
if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
if (FunctionLiteral::NeedsHomeObject(value)) {
property->set_ic_slot_count(1);
}
}
}
#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;
// 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);
}

View File

@ -1399,7 +1399,38 @@ class ObjectLiteralProperty final : public ZoneObject {
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;
@ -1413,6 +1444,7 @@ class ObjectLiteralProperty final : public ZoneObject {
private:
Expression* key_;
Expression* value_;
int ic_slot_or_count_;
Kind kind_;
bool emit_store_;
bool is_static_;
@ -1477,8 +1509,8 @@ class ObjectLiteral final : public MaterializedLiteral {
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)); }
@ -1499,18 +1531,10 @@ class ObjectLiteral final : public MaterializedLiteral {
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,
@ -1523,9 +1547,6 @@ class ObjectLiteral final : public MaterializedLiteral {
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(); }
@ -1539,11 +1560,6 @@ class ObjectLiteral final : public MaterializedLiteral {
bool has_elements_;
bool may_store_doubles_;
bool has_function_;
#ifdef DEBUG
// slot_count_ helps validate that the logic to allocate ic slots and the
// logic to use them are in sync.
int slot_count_;
#endif
FeedbackVectorICSlot slot_;
};
@ -2714,18 +2730,17 @@ class ClassLiteral final : public Expression {
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,
@ -2740,9 +2755,6 @@ class ClassLiteral final : public Expression {
constructor_(constructor),
properties_(properties),
end_position_(end_position),
#ifdef DEBUG
slot_count_(0),
#endif
slot_(FeedbackVectorICSlot::Invalid()) {
}
@ -2758,11 +2770,6 @@ class ClassLiteral final : public Expression {
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_;
};

View File

@ -1570,7 +1570,6 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
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);
@ -1593,9 +1592,8 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
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:
@ -1638,10 +1636,9 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
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);
}
@ -1720,7 +1717,6 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
// 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);
@ -1744,17 +1740,12 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
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());
}
@ -1773,9 +1764,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
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;
}
@ -1794,12 +1783,12 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
}
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;
}
@ -1810,16 +1799,8 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
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();
@ -1864,9 +1845,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
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:
@ -1907,14 +1886,21 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
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();
@ -3808,11 +3794,14 @@ Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
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());

View File

@ -326,8 +326,9 @@ class AstGraphBuilder : public AstVisitor {
// 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);
@ -402,6 +403,10 @@ class AstGraphBuilder : public AstVisitor {
const VectorSlotPair& feedback,
BailoutId bailout_id);
// Dispatched from VisitObjectLiteral.
void VisitObjectLiteralAccessor(Node* home_object,
ObjectLiteralProperty* property);
// Dispatched from VisitClassLiteral.
void VisitClassLiteralContents(ClassLiteral* expr);

View File

@ -1250,18 +1250,29 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
}
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();
}
@ -1531,12 +1542,19 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
}
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());
}
}
}
@ -1566,10 +1584,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector IC slot for the next store IC used.
// ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1597,7 +1611,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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());
@ -1605,14 +1619,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1625,8 +1632,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1645,12 +1653,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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;
}
@ -1665,13 +1673,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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);
@ -1706,8 +1708,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} 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:
@ -1753,10 +1756,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(r0);
}
// Verify that compilation exactly consumed the number of store ic slots that
// the ObjectLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
}
@ -2434,8 +2433,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
}
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in r0.
DCHECK(lit != NULL);
__ push(r0);
@ -2469,8 +2467,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
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:

View File

@ -1246,17 +1246,27 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
}
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();
}
@ -1518,12 +1528,19 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
}
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());
}
}
}
@ -1553,10 +1570,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector IC slot for the next store IC used.
// ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1584,7 +1597,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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());
@ -1592,14 +1605,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1611,8 +1617,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1630,12 +1637,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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;
}
@ -1650,13 +1657,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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);
@ -1691,8 +1692,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} 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:
@ -1738,10 +1740,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(x0);
}
// Verify that compilation exactly consumed the number of store ic slots that
// the ObjectLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
}
@ -2145,8 +2143,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
}
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in x0.
DCHECK(lit != NULL);
__ push(x0);
@ -2180,8 +2177,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
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:

View File

@ -1300,23 +1300,13 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
__ 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());

View File

@ -552,7 +552,7 @@ class FullCodeGenerator: public AstVisitor {
void EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
void EmitAccessor(Expression* expression);
void EmitAccessor(ObjectLiteralProperty* property);
bool NeedsHoleCheckForLoad(VariableProxy* proxy);
@ -586,7 +586,7 @@ class FullCodeGenerator: public AstVisitor {
// 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);
@ -640,9 +640,11 @@ class FullCodeGenerator: public AstVisitor {
// Adds the [[HomeObject]] to |initializer| if it is a FunctionLiteral.
// The value of the initializer is expected to be at the top of the stack.
// |offset| is the offset in the stack where the home object can be found.
void EmitSetHomeObjectIfNeeded(
Expression* initializer, int offset,
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);

View File

@ -1180,18 +1180,27 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
}
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();
}
@ -1463,11 +1472,18 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
}
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());
}
}
}
@ -1503,10 +1519,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector IC slot for the next store IC used.
// ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1534,22 +1546,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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);
@ -1560,8 +1564,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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 {
@ -1576,12 +1581,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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;
}
@ -1594,15 +1599,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
++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);
@ -1636,8 +1635,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} 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:
@ -1679,10 +1679,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(eax);
}
// Verify that compilation exactly consumed the number of store ic slots that
// the ObjectLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
}
@ -2353,8 +2349,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
}
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in eax.
DCHECK(lit != NULL);
__ push(eax);
@ -2386,8 +2381,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
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:

View File

@ -1249,18 +1249,29 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
}
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();
}
@ -1530,12 +1541,19 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
}
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());
}
}
}
@ -1564,10 +1582,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector IC slot for the next store IC used.
// ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1596,7 +1610,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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());
@ -1604,14 +1618,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1624,8 +1631,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1643,12 +1651,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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;
}
@ -1663,13 +1671,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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);
@ -1704,8 +1706,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} 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:
@ -1751,10 +1754,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(v0);
}
// Verify that compilation exactly consumed the number of store ic slots that
// the ObjectLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
}
@ -2426,8 +2425,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
}
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in v0.
DCHECK(lit != NULL);
__ push(v0);
@ -2461,8 +2459,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
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:
@ -3164,7 +3163,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// 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());

View File

@ -1247,18 +1247,29 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
}
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();
}
@ -1528,12 +1539,19 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
}
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());
}
}
}
@ -1562,10 +1580,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector IC slot for the next store IC used.
// ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1594,7 +1608,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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());
@ -1602,14 +1616,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1622,8 +1629,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1641,12 +1649,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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;
}
@ -1661,13 +1669,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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);
@ -1702,8 +1704,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} 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:
@ -1749,10 +1752,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(v0);
}
// Verify that compilation exactly consumed the number of store ic slots that
// the ObjectLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
}
@ -2425,8 +2424,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
}
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in v0.
DCHECK(lit != NULL);
__ push(v0);
@ -2460,8 +2458,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
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:

View File

@ -1208,18 +1208,29 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
}
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();
}
@ -1492,11 +1503,18 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
}
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());
}
}
}
@ -1530,10 +1548,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
AccessorTable accessor_table(zone());
int property_index = 0;
// store_slot_index points to the vector IC slot for the next store IC used.
// ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@ -1561,7 +1575,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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());
@ -1569,14 +1583,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -1587,8 +1594,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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 {
@ -1603,12 +1611,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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;
}
@ -1622,13 +1630,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ 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);
}
@ -1661,8 +1663,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} 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:
@ -1704,10 +1707,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(rax);
}
// Verify that compilation exactly consumed the number of store ic slots that
// the ObjectLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
}
@ -2377,8 +2376,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
}
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// Constructor is in rax.
DCHECK(lit != NULL);
__ Push(rax);
@ -2410,8 +2408,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
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:

View File

@ -5894,7 +5894,6 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
// 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);
@ -5918,7 +5917,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
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,
@ -5946,8 +5945,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@ -5966,9 +5964,6 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
}
}
// 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

View File

@ -198,7 +198,8 @@ void TypeFeedbackOracle::GetStoreModeAndKeyType(
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();
@ -414,6 +415,13 @@ void TypeFeedbackOracle::CountReceiverTypes(TypeFeedbackId id,
}
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,
@ -462,8 +470,15 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
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);
}
}

View File

@ -66,6 +66,8 @@ class TypeFeedbackOracle: public ZoneObject {
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,

View File

@ -396,8 +396,13 @@ void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
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());
}
@ -612,12 +617,18 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
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.