| Index: src/ast.cc
|
| diff --git a/src/ast.cc b/src/ast.cc
|
| index 53d27999ea073768fd0f879121cddf7964974732..bb05c3a21263339bf1613c0d627cdbcdf6783771 100644
|
| --- a/src/ast.cc
|
| +++ b/src/ast.cc
|
| @@ -220,26 +220,142 @@ bool ObjectLiteral::Property::emit_store() {
|
| }
|
|
|
|
|
| +enum ObjectLiteralPropertyState {
|
| + kNoPropertyState = 0,
|
| + kDataPropertyState = 1,
|
| + kGetterPropertyState = 2,
|
| + kSetterPropertyState = 3,
|
| + kAccessorPropertyState = 4 // Getter and setter fixed.
|
| +};
|
| +
|
| +
|
| void ObjectLiteral::CalculateEmitStore(Zone* zone) {
|
| ZoneAllocationPolicy allocator(zone);
|
|
|
| + // Map of Literal -> ObjectLiteralPropertyState
|
| ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity,
|
| allocator);
|
| +
|
| + bool has_dunder_proto = false;
|
| +
|
| + // Visit properties from last to first.
|
| for (int i = properties()->length() - 1; i >= 0; i--) {
|
| ObjectLiteral::Property* property = properties()->at(i);
|
| Literal* literal = property->key();
|
| - if (literal->value()->IsNull()) continue;
|
| + ASSERT(!literal->value()->IsNull());
|
| uint32_t hash = literal->Hash();
|
| - // If the key of a computed property is in the table, do not emit
|
| - // a store for the property later.
|
| - if ((property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL ||
|
| - property->kind() == ObjectLiteral::Property::COMPUTED) &&
|
| - table.Lookup(literal, hash, false, allocator) != NULL) {
|
| +
|
| + if (property->IsCompileTimeValue())
|
| property->set_emit_store(false);
|
| - } else {
|
| - // Add key to the table.
|
| - table.Lookup(literal, hash, true, allocator);
|
| +
|
| + ObjectLiteralPropertyState old_state, new_state;
|
| +
|
| + ZoneHashMap::Entry *entry = table.Lookup(literal, hash, true, allocator);
|
| + uintptr_t old_state_bits = reinterpret_cast<uintptr_t>(entry->value);
|
| + old_state = static_cast<ObjectLiteralPropertyState>(old_state_bits);
|
| + new_state = old_state;
|
| + switch (old_state) {
|
| + case kNoPropertyState:
|
| + switch (property->kind()) {
|
| + case ObjectLiteral::Property::CONSTANT:
|
| + case ObjectLiteral::Property::MATERIALIZED_LITERAL:
|
| + case ObjectLiteral::Property::COMPUTED:
|
| + new_state = kDataPropertyState;
|
| + break;
|
| + case ObjectLiteral::Property::GETTER:
|
| + new_state = kGetterPropertyState;
|
| + break;
|
| + case ObjectLiteral::Property::SETTER:
|
| + new_state = kSetterPropertyState;
|
| + break;
|
| + case ObjectLiteral::Property::PROTOTYPE:
|
| + if (has_dunder_proto) property->set_emit_store(false);
|
| + has_dunder_proto = true;
|
| + continue;
|
| + }
|
| + break;
|
| + case kDataPropertyState:
|
| + // This property is overridden by a later data property.
|
| + switch (property->kind()) {
|
| + case ObjectLiteral::Property::CONSTANT:
|
| + case ObjectLiteral::Property::MATERIALIZED_LITERAL:
|
| + case ObjectLiteral::Property::COMPUTED:
|
| + case ObjectLiteral::Property::GETTER:
|
| + case ObjectLiteral::Property::SETTER:
|
| + property->set_emit_store(false);
|
| + break;
|
| + case ObjectLiteral::Property::PROTOTYPE:
|
| + if (has_dunder_proto) property->set_emit_store(false);
|
| + has_dunder_proto = true;
|
| + break;
|
| + }
|
| + break;
|
| + case kGetterPropertyState:
|
| + switch (property->kind()) {
|
| + case ObjectLiteral::Property::CONSTANT:
|
| + case ObjectLiteral::Property::MATERIALIZED_LITERAL:
|
| + case ObjectLiteral::Property::COMPUTED:
|
| + // This getter will not have a corresponding setter.
|
| + new_state = kAccessorPropertyState;
|
| + property->set_emit_store(false);
|
| + break;
|
| + case ObjectLiteral::Property::GETTER:
|
| + property->set_emit_store(false);
|
| + break;
|
| + case ObjectLiteral::Property::SETTER:
|
| + new_state = kAccessorPropertyState;
|
| + break;
|
| + case ObjectLiteral::Property::PROTOTYPE:
|
| + // This getter will not have a corresponding setter.
|
| + new_state = kAccessorPropertyState;
|
| + if (has_dunder_proto) property->set_emit_store(false);
|
| + has_dunder_proto = true;
|
| + break;
|
| + }
|
| + break;
|
| + case kSetterPropertyState:
|
| + switch (property->kind()) {
|
| + case ObjectLiteral::Property::CONSTANT:
|
| + case ObjectLiteral::Property::MATERIALIZED_LITERAL:
|
| + case ObjectLiteral::Property::COMPUTED:
|
| + // This setter will not have a corresponding getter.
|
| + new_state = kAccessorPropertyState;
|
| + property->set_emit_store(false);
|
| + break;
|
| + case ObjectLiteral::Property::GETTER:
|
| + new_state = kAccessorPropertyState;
|
| + break;
|
| + case ObjectLiteral::Property::SETTER:
|
| + property->set_emit_store(false);
|
| + break;
|
| + case ObjectLiteral::Property::PROTOTYPE:
|
| + // This setter will not have a corresponding getter.
|
| + new_state = kAccessorPropertyState;
|
| + if (has_dunder_proto) property->set_emit_store(false);
|
| + has_dunder_proto = true;
|
| + break;
|
| + }
|
| + break;
|
| + case kAccessorPropertyState:
|
| + // This property is overridden by a later accessor property.
|
| + switch (property->kind()) {
|
| + case ObjectLiteral::Property::CONSTANT:
|
| + case ObjectLiteral::Property::MATERIALIZED_LITERAL:
|
| + case ObjectLiteral::Property::COMPUTED:
|
| + case ObjectLiteral::Property::GETTER:
|
| + case ObjectLiteral::Property::SETTER:
|
| + property->set_emit_store(false);
|
| + break;
|
| + case ObjectLiteral::Property::PROTOTYPE:
|
| + if (has_dunder_proto) property->set_emit_store(false);
|
| + has_dunder_proto = true;
|
| + break;
|
| + }
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| }
|
| + entry->value = reinterpret_cast<void*>(new_state);
|
| }
|
| }
|
|
|
|
|