Ensure that generated code for object literals will call...

Ensure that generated code for object literals will call Runtime_DefineOrRedefineAccessorProperty only once per accessor property.

To do this, we collect all accessor properties in a first pass and emit code for
defining those properties afterwards in a second pass.

As a finger exercise, the table used for collecting accessors has a (subset of
an) STL-like iterator interface, including STL-like names and operators.
Although C++ is quite verbose here (as usual, but partly this is caused by our
current slightly clumsy classes/templates), things work out quite nicely and it
cleans up some confusion, e.g. a table entry is not an iterator etc.
Everything compiles into very efficient code, e.g. the loop condition 'it !=
accessor_table.end()' compiles into a single 'testl' instruction on ia32.
+1 for using standard APIs!

Review URL: https://chromiumcodereview.appspot.com/9691040

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11051 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2c7f0edd
...@@ -1410,6 +1410,16 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -1410,6 +1410,16 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
} }
void FullCodeGenerator::EmitAccessor(Expression* expression) {
if (expression == NULL) {
__ LoadRoot(r1, Heap::kNullValueRootIndex);
__ push(r1);
} else {
VisitForStackValue(expression);
}
}
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral"); Comment cmnt(masm_, "[ ObjectLiteral");
Handle<FixedArray> constant_properties = expr->constant_properties(); Handle<FixedArray> constant_properties = expr->constant_properties();
...@@ -1445,6 +1455,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1445,6 +1455,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// marked expressions, no store code is emitted. // marked expressions, no store code is emitted.
expr->CalculateEmitStore(); expr->CalculateEmitStore();
AccessorTable accessor_table(isolate()->zone());
for (int i = 0; i < expr->properties()->length(); i++) { for (int i = 0; i < expr->properties()->length(); i++) {
ObjectLiteral::Property* property = expr->properties()->at(i); ObjectLiteral::Property* property = expr->properties()->at(i);
if (property->IsCompileTimeValue()) continue; if (property->IsCompileTimeValue()) continue;
...@@ -1493,27 +1504,29 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1493,27 +1504,29 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} }
break; break;
case ObjectLiteral::Property::GETTER: case ObjectLiteral::Property::GETTER:
accessor_table.find(key)->second->getter = value;
break;
case ObjectLiteral::Property::SETTER: case ObjectLiteral::Property::SETTER:
// Duplicate receiver on stack. accessor_table.find(key)->second->setter = value;
__ ldr(r0, MemOperand(sp));
__ push(r0);
VisitForStackValue(key);
if (property->kind() == ObjectLiteral::Property::GETTER) {
VisitForStackValue(value);
__ LoadRoot(r1, Heap::kNullValueRootIndex);
__ push(r1);
} else {
__ LoadRoot(r1, Heap::kNullValueRootIndex);
__ push(r1);
VisitForStackValue(value);
}
__ mov(r0, Operand(Smi::FromInt(NONE)));
__ push(r0);
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
break; break;
} }
} }
// Emit code to define accessors, using only a single call to the runtime for
// each pair of corresponding getters and setters.
for (AccessorTable::Iterator it = accessor_table.begin();
it != accessor_table.end();
++it) {
__ ldr(r0, MemOperand(sp)); // Duplicate receiver.
__ push(r0);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
__ mov(r0, Operand(Smi::FromInt(NONE)));
__ push(r0);
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
}
if (expr->has_function()) { if (expr->has_function()) {
ASSERT(result_saved); ASSERT(result_saved);
__ ldr(r0, MemOperand(sp)); __ ldr(r0, MemOperand(sp));
......
...@@ -1366,6 +1366,12 @@ class ObjectLiteral: public MaterializedLiteral { ...@@ -1366,6 +1366,12 @@ class ObjectLiteral: public MaterializedLiteral {
kHasFunction = 1 << 1 kHasFunction = 1 << 1
}; };
struct Accessors: public ZoneObject {
Accessors() : getter(NULL), setter(NULL) { }
Expression* getter;
Expression* setter;
};
protected: protected:
template<class> friend class AstNodeFactory; template<class> friend class AstNodeFactory;
......
...@@ -470,6 +470,8 @@ class FullCodeGenerator: public AstVisitor { ...@@ -470,6 +470,8 @@ class FullCodeGenerator: public AstVisitor {
Label* done); Label* done);
void EmitVariableLoad(VariableProxy* proxy); void EmitVariableLoad(VariableProxy* proxy);
void EmitAccessor(Expression* expression);
// Expects the arguments and the function already pushed. // Expects the arguments and the function already pushed.
void EmitResolvePossiblyDirectEval(int arg_count); void EmitResolvePossiblyDirectEval(int arg_count);
...@@ -804,6 +806,28 @@ class FullCodeGenerator: public AstVisitor { ...@@ -804,6 +806,28 @@ class FullCodeGenerator: public AstVisitor {
}; };
// A map from property names to getter/setter pairs allocated in the zone.
class AccessorTable: public TemplateHashMap<Literal,
ObjectLiteral::Accessors,
ZoneListAllocationPolicy> {
public:
explicit AccessorTable(Zone* zone) :
TemplateHashMap<Literal,
ObjectLiteral::Accessors,
ZoneListAllocationPolicy>(Literal::Match),
zone_(zone) { }
Iterator lookup(Literal* literal) {
Iterator it = find(literal, true);
if (it->second == NULL) it->second = new(zone_) ObjectLiteral::Accessors();
return it;
}
private:
Zone* zone_;
};
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_FULL_CODEGEN_H_ #endif // V8_FULL_CODEGEN_H_
...@@ -36,15 +36,15 @@ namespace v8 { ...@@ -36,15 +36,15 @@ namespace v8 {
namespace internal { namespace internal {
template<class AllocationPolicy> template<class AllocationPolicy>
class TemplateHashMap { class TemplateHashMapImpl {
public: public:
typedef bool (*MatchFun) (void* key1, void* key2); typedef bool (*MatchFun) (void* key1, void* key2);
// initial_capacity is the size of the initial hash map; // initial_capacity is the size of the initial hash map;
// it must be a power of 2 (and thus must not be 0). // it must be a power of 2 (and thus must not be 0).
TemplateHashMap(MatchFun match, uint32_t initial_capacity = 8); TemplateHashMapImpl(MatchFun match, uint32_t initial_capacity = 8);
~TemplateHashMap(); ~TemplateHashMapImpl();
// HashMap entries are (key, value, hash) triplets. // HashMap entries are (key, value, hash) triplets.
// Some clients may not need to use the value slot // Some clients may not need to use the value slot
...@@ -99,10 +99,10 @@ class TemplateHashMap { ...@@ -99,10 +99,10 @@ class TemplateHashMap {
void Resize(); void Resize();
}; };
typedef TemplateHashMap<FreeStoreAllocationPolicy> HashMap; typedef TemplateHashMapImpl<FreeStoreAllocationPolicy> HashMap;
template<class P> template<class P>
TemplateHashMap<P>::TemplateHashMap(MatchFun match, TemplateHashMapImpl<P>::TemplateHashMapImpl(MatchFun match,
uint32_t initial_capacity) { uint32_t initial_capacity) {
match_ = match; match_ = match;
Initialize(initial_capacity); Initialize(initial_capacity);
...@@ -110,13 +110,13 @@ TemplateHashMap<P>::TemplateHashMap(MatchFun match, ...@@ -110,13 +110,13 @@ TemplateHashMap<P>::TemplateHashMap(MatchFun match,
template<class P> template<class P>
TemplateHashMap<P>::~TemplateHashMap() { TemplateHashMapImpl<P>::~TemplateHashMapImpl() {
P::Delete(map_); P::Delete(map_);
} }
template<class P> template<class P>
typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Lookup( typename TemplateHashMapImpl<P>::Entry* TemplateHashMapImpl<P>::Lookup(
void* key, uint32_t hash, bool insert) { void* key, uint32_t hash, bool insert) {
// Find a matching entry. // Find a matching entry.
Entry* p = Probe(key, hash); Entry* p = Probe(key, hash);
...@@ -146,7 +146,7 @@ typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Lookup( ...@@ -146,7 +146,7 @@ typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Lookup(
template<class P> template<class P>
void TemplateHashMap<P>::Remove(void* key, uint32_t hash) { void TemplateHashMapImpl<P>::Remove(void* key, uint32_t hash) {
// Lookup the entry for the key to remove. // Lookup the entry for the key to remove.
Entry* p = Probe(key, hash); Entry* p = Probe(key, hash);
if (p->key == NULL) { if (p->key == NULL) {
...@@ -206,7 +206,7 @@ void TemplateHashMap<P>::Remove(void* key, uint32_t hash) { ...@@ -206,7 +206,7 @@ void TemplateHashMap<P>::Remove(void* key, uint32_t hash) {
template<class P> template<class P>
void TemplateHashMap<P>::Clear() { void TemplateHashMapImpl<P>::Clear() {
// Mark all entries as empty. // Mark all entries as empty.
const Entry* end = map_end(); const Entry* end = map_end();
for (Entry* p = map_; p < end; p++) { for (Entry* p = map_; p < end; p++) {
...@@ -217,13 +217,14 @@ void TemplateHashMap<P>::Clear() { ...@@ -217,13 +217,14 @@ void TemplateHashMap<P>::Clear() {
template<class P> template<class P>
typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Start() const { typename TemplateHashMapImpl<P>::Entry* TemplateHashMapImpl<P>::Start() const {
return Next(map_ - 1); return Next(map_ - 1);
} }
template<class P> template<class P>
typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Next(Entry* p) const { typename TemplateHashMapImpl<P>::Entry* TemplateHashMapImpl<P>::Next(Entry* p)
const {
const Entry* end = map_end(); const Entry* end = map_end();
ASSERT(map_ - 1 <= p && p < end); ASSERT(map_ - 1 <= p && p < end);
for (p++; p < end; p++) { for (p++; p < end; p++) {
...@@ -236,7 +237,7 @@ typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Next(Entry* p) const { ...@@ -236,7 +237,7 @@ typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Next(Entry* p) const {
template<class P> template<class P>
typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Probe(void* key, typename TemplateHashMapImpl<P>::Entry* TemplateHashMapImpl<P>::Probe(void* key,
uint32_t hash) { uint32_t hash) {
ASSERT(key != NULL); ASSERT(key != NULL);
...@@ -258,7 +259,7 @@ typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Probe(void* key, ...@@ -258,7 +259,7 @@ typename TemplateHashMap<P>::Entry* TemplateHashMap<P>::Probe(void* key,
template<class P> template<class P>
void TemplateHashMap<P>::Initialize(uint32_t capacity) { void TemplateHashMapImpl<P>::Initialize(uint32_t capacity) {
ASSERT(IsPowerOf2(capacity)); ASSERT(IsPowerOf2(capacity));
map_ = reinterpret_cast<Entry*>(P::New(capacity * sizeof(Entry))); map_ = reinterpret_cast<Entry*>(P::New(capacity * sizeof(Entry)));
if (map_ == NULL) { if (map_ == NULL) {
...@@ -271,7 +272,7 @@ void TemplateHashMap<P>::Initialize(uint32_t capacity) { ...@@ -271,7 +272,7 @@ void TemplateHashMap<P>::Initialize(uint32_t capacity) {
template<class P> template<class P>
void TemplateHashMap<P>::Resize() { void TemplateHashMapImpl<P>::Resize() {
Entry* map = map_; Entry* map = map_;
uint32_t n = occupancy_; uint32_t n = occupancy_;
...@@ -290,6 +291,50 @@ void TemplateHashMap<P>::Resize() { ...@@ -290,6 +291,50 @@ void TemplateHashMap<P>::Resize() {
P::Delete(map); P::Delete(map);
} }
// A hash map for pointer keys and values with an STL-like interface.
template<class Key, class Value, class AllocationPolicy>
class TemplateHashMap: private TemplateHashMapImpl<AllocationPolicy> {
public:
STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT
STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT
struct value_type {
Key* first;
Value* second;
};
class Iterator {
public:
Iterator& operator++() {
entry_ = map_->Next(entry_);
return *this;
}
value_type* operator->() { return reinterpret_cast<value_type*>(entry_); }
bool operator!=(const Iterator& other) { return entry_ != other.entry_; }
private:
Iterator(const TemplateHashMapImpl<AllocationPolicy>* map,
typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry) :
map_(map), entry_(entry) { }
const TemplateHashMapImpl<AllocationPolicy>* map_;
typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry_;
friend class TemplateHashMap;
};
TemplateHashMap(
typename TemplateHashMapImpl<AllocationPolicy>::MatchFun match)
: TemplateHashMapImpl<AllocationPolicy>(match) { }
Iterator begin() const { return Iterator(this, this->Start()); }
Iterator end() const { return Iterator(this, NULL); }
Iterator find(Key* key, bool insert = false) {
return Iterator(this, Lookup(key, key->Hash(), insert));
}
};
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_HASHMAP_H_ #endif // V8_HASHMAP_H_
...@@ -1411,6 +1411,15 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -1411,6 +1411,15 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
} }
void FullCodeGenerator::EmitAccessor(Expression* expression) {
if (expression == NULL) {
__ push(Immediate(isolate()->factory()->null_value()));
} else {
VisitForStackValue(expression);
}
}
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral"); Comment cmnt(masm_, "[ ObjectLiteral");
Handle<FixedArray> constant_properties = expr->constant_properties(); Handle<FixedArray> constant_properties = expr->constant_properties();
...@@ -1445,6 +1454,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1445,6 +1454,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// marked expressions, no store code is emitted. // marked expressions, no store code is emitted.
expr->CalculateEmitStore(); expr->CalculateEmitStore();
AccessorTable accessor_table(isolate()->zone());
for (int i = 0; i < expr->properties()->length(); i++) { for (int i = 0; i < expr->properties()->length(); i++) {
ObjectLiteral::Property* property = expr->properties()->at(i); ObjectLiteral::Property* property = expr->properties()->at(i);
if (property->IsCompileTimeValue()) continue; if (property->IsCompileTimeValue()) continue;
...@@ -1456,6 +1466,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1456,6 +1466,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
result_saved = true; result_saved = true;
} }
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
UNREACHABLE();
case ObjectLiteral::Property::MATERIALIZED_LITERAL: case ObjectLiteral::Property::MATERIALIZED_LITERAL:
ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
// Fall through. // Fall through.
...@@ -1487,24 +1499,28 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1487,24 +1499,28 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Drop(3); __ Drop(3);
} }
break; break;
case ObjectLiteral::Property::SETTER:
case ObjectLiteral::Property::GETTER: case ObjectLiteral::Property::GETTER:
__ push(Operand(esp, 0)); // Duplicate receiver. accessor_table.lookup(key)->second->getter = value;
VisitForStackValue(key); break;
if (property->kind() == ObjectLiteral::Property::GETTER) { case ObjectLiteral::Property::SETTER:
VisitForStackValue(value); accessor_table.lookup(key)->second->setter = value;
__ push(Immediate(isolate()->factory()->null_value()));
} else {
__ push(Immediate(isolate()->factory()->null_value()));
VisitForStackValue(value);
}
__ push(Immediate(Smi::FromInt(NONE)));
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
break; break;
default: UNREACHABLE();
} }
} }
// Emit code to define accessors, using only a single call to the runtime for
// each pair of corresponding getters and setters.
for (AccessorTable::Iterator it = accessor_table.begin();
it != accessor_table.end();
++it) {
__ push(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
__ push(Immediate(Smi::FromInt(NONE)));
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
}
if (expr->has_function()) { if (expr->has_function()) {
ASSERT(result_saved); ASSERT(result_saved);
__ push(Operand(esp, 0)); __ push(Operand(esp, 0));
......
...@@ -1421,6 +1421,16 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -1421,6 +1421,16 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
} }
void FullCodeGenerator::EmitAccessor(Expression* expression) {
if (expression == NULL) {
__ LoadRoot(a1, Heap::kNullValueRootIndex);
__ push(a1);
} else {
VisitForStackValue(expression);
}
}
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral"); Comment cmnt(masm_, "[ ObjectLiteral");
Handle<FixedArray> constant_properties = expr->constant_properties(); Handle<FixedArray> constant_properties = expr->constant_properties();
...@@ -1456,6 +1466,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1456,6 +1466,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// marked expressions, no store code is emitted. // marked expressions, no store code is emitted.
expr->CalculateEmitStore(); expr->CalculateEmitStore();
AccessorTable accessor_table(isolate()->zone());
for (int i = 0; i < expr->properties()->length(); i++) { for (int i = 0; i < expr->properties()->length(); i++) {
ObjectLiteral::Property* property = expr->properties()->at(i); ObjectLiteral::Property* property = expr->properties()->at(i);
if (property->IsCompileTimeValue()) continue; if (property->IsCompileTimeValue()) continue;
...@@ -1505,27 +1516,29 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1505,27 +1516,29 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} }
break; break;
case ObjectLiteral::Property::GETTER: case ObjectLiteral::Property::GETTER:
accessor_table.find(key)->second->getter = value;
break;
case ObjectLiteral::Property::SETTER: case ObjectLiteral::Property::SETTER:
// Duplicate receiver on stack. accessor_table.find(key)->second->setter = value;
__ lw(a0, MemOperand(sp));
__ push(a0);
VisitForStackValue(key);
if (property->kind() == ObjectLiteral::Property::GETTER) {
VisitForStackValue(value);
__ LoadRoot(a1, Heap::kNullValueRootIndex);
__ push(a1);
} else {
__ LoadRoot(a1, Heap::kNullValueRootIndex);
__ push(a1);
VisitForStackValue(value);
}
__ li(a0, Operand(Smi::FromInt(NONE)));
__ push(a0);
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
break; break;
} }
} }
// Emit code to define accessors, using only a single call to the runtime for
// each pair of corresponding getters and setters.
for (AccessorTable::Iterator it = accessor_table.begin();
it != accessor_table.end();
++it) {
__ lw(a0, MemOperand(sp)); // Duplicate receiver.
__ push(a0);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
__ li(a0, Operand(Smi::FromInt(NONE)));
__ push(a0);
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
}
if (expr->has_function()) { if (expr->has_function()) {
ASSERT(result_saved); ASSERT(result_saved);
__ lw(a0, MemOperand(sp)); __ lw(a0, MemOperand(sp));
......
...@@ -1377,6 +1377,15 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -1377,6 +1377,15 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
} }
void FullCodeGenerator::EmitAccessor(Expression* expression) {
if (expression == NULL) {
__ PushRoot(Heap::kNullValueRootIndex);
} else {
VisitForStackValue(expression);
}
}
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral"); Comment cmnt(masm_, "[ ObjectLiteral");
Handle<FixedArray> constant_properties = expr->constant_properties(); Handle<FixedArray> constant_properties = expr->constant_properties();
...@@ -1411,6 +1420,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1411,6 +1420,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// marked expressions, no store code is emitted. // marked expressions, no store code is emitted.
expr->CalculateEmitStore(); expr->CalculateEmitStore();
AccessorTable accessor_table(isolate()->zone());
for (int i = 0; i < expr->properties()->length(); i++) { for (int i = 0; i < expr->properties()->length(); i++) {
ObjectLiteral::Property* property = expr->properties()->at(i); ObjectLiteral::Property* property = expr->properties()->at(i);
if (property->IsCompileTimeValue()) continue; if (property->IsCompileTimeValue()) continue;
...@@ -1455,23 +1465,28 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1455,23 +1465,28 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Drop(3); __ Drop(3);
} }
break; break;
case ObjectLiteral::Property::SETTER:
case ObjectLiteral::Property::GETTER: case ObjectLiteral::Property::GETTER:
__ push(Operand(rsp, 0)); // Duplicate receiver. accessor_table.find(key)->second->getter = value;
VisitForStackValue(key); break;
if (property->kind() == ObjectLiteral::Property::GETTER) { case ObjectLiteral::Property::SETTER:
VisitForStackValue(value); accessor_table.find(key)->second->setter = value;
__ PushRoot(Heap::kNullValueRootIndex);
} else {
__ PushRoot(Heap::kNullValueRootIndex);
VisitForStackValue(value);
}
__ Push(Smi::FromInt(NONE));
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
break; break;
} }
} }
// Emit code to define accessors, using only a single call to the runtime for
// each pair of corresponding getters and setters.
for (AccessorTable::Iterator it = accessor_table.begin();
it != accessor_table.end();
++it) {
__ push(Operand(rsp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
__ Push(Smi::FromInt(NONE));
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
}
if (expr->has_function()) { if (expr->has_function()) {
ASSERT(result_saved); ASSERT(result_saved);
__ push(Operand(rsp, 0)); __ push(Operand(rsp, 0));
......
...@@ -240,7 +240,7 @@ class ZoneSplayTree: public SplayTree<Config, ZoneListAllocationPolicy> { ...@@ -240,7 +240,7 @@ class ZoneSplayTree: public SplayTree<Config, ZoneListAllocationPolicy> {
}; };
typedef TemplateHashMap<ZoneListAllocationPolicy> ZoneHashMap; typedef TemplateHashMapImpl<ZoneListAllocationPolicy> ZoneHashMap;
} } // namespace v8::internal } } // namespace v8::internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment