break;
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = value;
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = value;
+ }
break;
}
}
__ CallRuntime(Runtime::kInternalSetPrototype, 2);
break;
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = value;
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = value;
+ }
break;
}
}
void ObjectLiteral::CalculateEmitStore(Zone* zone) {
+ const auto GETTER = ObjectLiteral::Property::GETTER;
+ const auto SETTER = ObjectLiteral::Property::SETTER;
+
ZoneAllocationPolicy allocator(zone);
ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity,
for (int i = properties()->length() - 1; i >= 0; i--) {
ObjectLiteral::Property* property = properties()->at(i);
if (property->is_computed_name()) continue;
+ if (property->kind() == ObjectLiteral::Property::PROTOTYPE) continue;
Literal* literal = property->key()->AsLiteral();
- if (literal->value()->IsNull()) continue;
+ DCHECK(!literal->value()->IsNull());
+
+ // If there is an existing entry do not emit a store unless the previous
+ // entry was also an accessor.
uint32_t hash = literal->Hash();
- // If the key of a computed property value 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) {
- property->set_emit_store(false);
- } else if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
- // Add key to the table.
- table.Lookup(literal, hash, true, allocator);
+ ZoneHashMap::Entry* entry = table.Lookup(literal, hash, true, allocator);
+ if (entry->value != NULL) {
+ auto previous_kind =
+ static_cast<ObjectLiteral::Property*>(entry->value)->kind();
+ if (!((property->kind() == GETTER && previous_kind == SETTER) ||
+ (property->kind() == SETTER && previous_kind == GETTER))) {
+ property->set_emit_store(false);
+ }
}
+ entry->value = property;
}
}
break;
}
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = property->value();
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = property->value();
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = property->value();
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = property->value();
+ }
break;
}
}
__ CallRuntime(Runtime::kInternalSetPrototype, 2);
break;
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = value;
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = value;
+ }
break;
}
}
__ CallRuntime(Runtime::kInternalSetPrototype, 2);
break;
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = value;
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = value;
+ }
break;
}
}
__ CallRuntime(Runtime::kInternalSetPrototype, 2);
break;
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = value;
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = value;
+ }
break;
}
}
__ CallRuntime(Runtime::kInternalSetPrototype, 2);
break;
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = value;
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = value;
+ }
break;
}
}
__ CallRuntime(Runtime::kInternalSetPrototype, 2);
break;
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = value;
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = value;
+ }
break;
}
}
__ CallRuntime(Runtime::kInternalSetPrototype, 2);
break;
case ObjectLiteral::Property::GETTER:
- accessor_table.lookup(key)->second->getter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->getter = value;
+ }
break;
case ObjectLiteral::Property::SETTER:
- accessor_table.lookup(key)->second->setter = value;
+ if (property->emit_store()) {
+ accessor_table.lookup(key)->second->setter = value;
+ }
break;
}
}
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function TestConstants() {
+ var o = {
+ p: 1,
+ p: 2,
+ };
+ assertEquals(2, o.p);
+})();
+
+
+(function TestMaterialized() {
+ var o = {
+ p: [1],
+ p: [2],
+ };
+ assertEquals(2, o.p[0]);
+})();
+
+
+(function TestMaterialize2() {
+ var o = {
+ p: function() {},
+ p: 2,
+ };
+ assertEquals(2, o.p);
+})();
+
+
+
+(function TestComputed() {
+ var o = {
+ p: (function() { return 1; })(),
+ p: (function() { return 2; })(),
+ };
+ assertEquals(2, o.p);
+})();
+
+
+(function TestComputed2() {
+ var o = {
+ p: (function() { return 1; })(),
+ p: 2,
+ };
+ assertEquals(2, o.p);
+})();
+
+
+
+(function TestGetter() {
+ var o = {
+ get p() { return 1; },
+ get p() { return 2; },
+ };
+ assertEquals(2, o.p);
+})();
+
+
+(function TestGetterSetter() {
+ var o = {
+ get p() { return 1; },
+ set p(_) {},
+ };
+ assertEquals(1, o.p);
+
+ o = {
+ set p(_) {},
+ get p() { return 2; },
+ };
+ assertEquals(2, o.p);
+})();
+
+
+(function TestCombined() {
+ var o = {
+ get p() { return 1; },
+ p: 2,
+ };
+ assertEquals(2, o.p);
+
+ o = {
+ get p() { return 1; },
+ p: 2,
+ get p() { return 3; },
+ };
+ assertEquals(3, o.p);
+
+ o = {
+ get p() { return 1; },
+ p: 2,
+ set p(_) {},
+ };
+ assertEquals(undefined, o.p);
+})();