Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 556) |
+++ src/runtime.cc (working copy) |
@@ -113,8 +113,8 @@ |
// Based on the number of prefix symbols key we decide whether |
// to use the map cache in the global context. |
const int kMaxKeys = 10; |
- if ((number_of_symbol_keys == number_of_properties) |
- && (number_of_symbol_keys < kMaxKeys)) { |
+ if ((number_of_symbol_keys == number_of_properties) && |
+ (number_of_symbol_keys < kMaxKeys)) { |
// Create the fixed array with the key. |
Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys); |
for (int i = 0; i < number_of_symbol_keys; i++) { |
@@ -1669,23 +1669,57 @@ |
-// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric |
+// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric. |
static Object* Runtime_KeyedGetProperty(Arguments args) { |
NoHandleAllocation ha; |
ASSERT(args.length() == 2); |
- Object* receiver = args[0]; |
- Object* key = args[1]; |
- if (receiver->IsJSObject() && |
- key->IsString() && |
- !JSObject::cast(receiver)->HasFastProperties()) { |
- Dictionary* dictionary = JSObject::cast(receiver)->property_dictionary(); |
- int entry = dictionary->FindStringEntry(String::cast(key)); |
- if ((entry != DescriptorArray::kNotFound) |
- && (dictionary->DetailsAt(entry).type() == NORMAL)) { |
- return dictionary->ValueAt(entry); |
+ // Fast cases for getting named properties of the receiver JSObject |
+ // itself. The global proxy objects has to be excluded since |
+ // LocalLookup on the global proxy object can return a valid result |
+ // eventhough the global proxy object never has properties. This is |
+ // the case because the global proxy object forwards everything to |
+ // its hidden prototype including local lookups. |
+ if (args[0]->IsJSObject() && |
+ !args[0]->IsJSGlobalProxy() && |
+ args[1]->IsString()) { |
+ JSObject* receiver = JSObject::cast(args[0]); |
+ String* key = String::cast(args[1]); |
+ if (receiver->HasFastProperties()) { |
+ // Attempt to use lookup cache. |
+ Object* obj = Heap::GetKeyedLookupCache(); |
+ if (obj->IsFailure()) return obj; |
+ LookupCache* cache = LookupCache::cast(obj); |
+ Map* receiver_map = receiver->map(); |
+ int offset = cache->Lookup(receiver_map, key); |
bak
2008/10/23 06:08:11
It might be a good idea to use a kNotFound constan
|
+ if (offset != -1) { |
+ Object* value = receiver->FastPropertyAt(offset); |
+ return value->IsTheHole() ? Heap::undefined_value() : value; |
+ } |
+ // Lookup cache miss. Perform lookup and update the cache if |
+ // appropriate. |
+ LookupResult result; |
+ receiver->LocalLookup(key, &result); |
+ if (result.IsProperty() && result.IsLoaded() && result.type() == FIELD) { |
+ int offset = result.GetFieldIndex(); |
+ Object* obj = cache->Put(receiver_map, key, offset); |
+ if (obj->IsFailure()) return obj; |
+ Heap::SetKeyedLookupCache(LookupCache::cast(obj)); |
+ Object* value = receiver->FastPropertyAt(offset); |
+ return value->IsTheHole() ? Heap::undefined_value() : value; |
+ } |
+ } else { |
+ // Attempt dictionary lookup. |
+ Dictionary* dictionary = receiver->property_dictionary(); |
+ int entry = dictionary->FindStringEntry(key); |
+ if ((entry != DescriptorArray::kNotFound) && |
+ (dictionary->DetailsAt(entry).type() == NORMAL)) { |
+ return dictionary->ValueAt(entry); |
+ } |
} |
} |
+ |
+ // Fall back to GetObjectProperty. |
return Runtime::GetObjectProperty(args.at<Object>(0), |
args.at<Object>(1)); |
} |