| Index: src/ast.cc
|
| diff --git a/src/ast.cc b/src/ast.cc
|
| index 19747d8b767be294e3a819db95f7beb14a3c68b2..1b39e3190aa4021ebc6217b063dc219e9582e9d2 100644
|
| --- a/src/ast.cc
|
| +++ b/src/ast.cc
|
| @@ -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;
|
| + 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();
|
| }
|
|
|
|
|
| @@ -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();
|
| - 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);
|
| }
|
|
|
|
|
|
|