Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 68b913b3707f846877039686a8a8b3a9635de8d2..896c266479632d2edb17b082881b51dc06b0576a 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -15066,4 +15066,135 @@ void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) { |
| set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| } |
| + |
| +class LookupCacheEntry { |
| + public: |
| + LookupCacheEntry(Map* map, LookupResult* result, int depth) |
| + : map_(map), |
| + result_(*result), |
| + depth_(depth) { |
| + } |
| + |
| + Map* map_; |
|
danno
2013/04/29 11:30:11
Oh no! These are naked heap pointers. This approac
|
| + LookupResult result_; |
| + int depth_; |
| +}; |
| + |
| + |
| +LookupCache::LookupCache(Isolate* isolate) : isolate_(isolate), |
| + count_(0), |
| + hidden_count_(0) { |
| +#ifdef DEBUG |
| + for (int i = 0; i < kCacheEntryCount; i++) { |
| + entries_[i] = NULL; |
| + hidden_entries_[i] = NULL; |
| + } |
| +#endif |
| +} |
| + |
| + |
| +LookupCache::~LookupCache() { |
| + for (int i = 0; i < count_; i++) { |
| + delete entries_[i]; |
| + entries_[i] = NULL; |
| + } |
| + count_ = 0; |
| + for (int i = 0; i < hidden_count_; i++) { |
| + delete hidden_entries_[i]; |
| + hidden_entries_[i] = NULL; |
| + } |
| + hidden_count_ = 0; |
| +} |
| + |
| + |
| +void LookupCache::Lookup(Handle<Object> obj, |
| + Handle<Name> name, |
| + LookupResult* result, |
| + bool set_property) { |
| + if (!obj->IsJSReceiver()) return obj->Lookup(*name, result); |
| + |
| + JSReceiver* receiver = JSReceiver::cast(*obj); |
| + Heap* heap = receiver->GetHeap(); |
| + Map* map = receiver->map(); |
| + |
| + int count = set_property ? hidden_count_ : count_; |
| + LookupCacheEntry** entries = set_property ? hidden_entries_ : entries_; |
| + for (int i = 0; i < count; i++) { |
| + LookupCacheEntry* entry = entries[i]; |
| + if (entry->map_ != map) continue; |
| + |
| + // Hit! Dive into prototype chain if needed |
| + Object* current = *obj; |
| + int depth = entry->depth_; |
| + for (int j = 0; j < depth; j++) { |
| + // XXX: Probably this is a fatal condition |
| + if (current == heap->null_value()) break; |
| + |
| + current = JSObject::cast(current)->GetPrototype(); |
| + } |
| + result->CopyFrom(&entry->result_, JSObject::cast(receiver)); |
| + |
| + return; |
| + } |
| + |
| + // Miss |
| + // Ecma-262 3rd 8.6.2.4 |
| + int depth = 0; |
| + if (set_property) { |
| + receiver->LocalLookup(*name, result, true); |
| + if (!result->IsFound()) { |
| + map->LookupTransition(JSObject::cast(*obj), |
| + *name, |
| + result); |
| + } |
| + } else { |
| + Object* current; |
| + for (current = *obj; |
| + current != heap->null_value(); |
| + current = JSObject::cast(current)->GetPrototype(), depth++) { |
| + JSReceiver::cast(current)->LocalLookup(*name, result, false); |
| + if (result->IsFound()) break; |
| + } |
| + if (current == heap->null_value()) result->NotFound(); |
| + } |
| + |
| + // If property wasn't found, or is not cacheable |
| + if (!result->IsFound() && result->IsCacheable()) return; |
| + |
| + // Cache is full, just return result |
| + if (count == kCacheEntryCount) return; |
| + |
| + // Insert new cache entry |
| + entries[count++] = new LookupCacheEntry(map, result, depth); |
| + |
| + // Update count |
| + if (set_property) { |
| + hidden_count_ = count; |
| + } else { |
| + count_ = count; |
| + } |
| +} |
| + |
| + |
| +MUST_USE_RESULT MaybeObject* LookupCache::GetProperty(Handle<Object> obj, |
| + Handle<Name> name) { |
| + PropertyAttributes attributes; |
| + LookupResult result(isolate_); |
| + Lookup(obj, name, &result); |
| + MaybeObject* value = obj->GetProperty(*obj, &result, *name, &attributes); |
| + ASSERT(attributes <= ABSENT); |
| + return value; |
| +} |
| + |
| + |
| +MUST_USE_RESULT MaybeObject* LookupCache::SetProperty(Handle<Object> obj, |
| + Handle<Name> name, |
| + Handle<Object> value) { |
| + ASSERT(obj->IsJSReceiver()); |
| + LookupResult result(isolate_); |
| + Lookup(obj, name, &result, true); |
| + JSReceiver* receiver = JSReceiver::cast(*obj); |
| + return receiver->SetProperty(&result, *name, *value, NONE, kNonStrictMode); |
| +} |
| + |
| } } // namespace v8::internal |