Chromium Code Reviews| Index: src/objects.cc | 
| diff --git a/src/objects.cc b/src/objects.cc | 
| index c3a900d0dc8b655356a5bb5f69dded0de548d159..a069f195a59af7565e765a32482125c19ad4e95d 100644 | 
| --- a/src/objects.cc | 
| +++ b/src/objects.cc | 
| @@ -6883,6 +6883,46 @@ MaybeObject* JSObject::SetElementsLength(Object* len) { | 
| } | 
| +Object* Map::GetPrototypeTransition(Object* prototype) { | 
| + FixedArray* cache = prototype_transitions(); | 
| + int capacity = cache->length(); | 
| + if (capacity == 0) return NULL; | 
| + int finger = Smi::cast(cache->get(0))->value(); | 
| + for (int i = 1; i < finger; i += 2) { | 
| + if (cache->get(i) == prototype) return cache->get(i + 1); | 
| + } | 
| + return NULL; | 
| +} | 
| + | 
| + | 
| +MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { | 
| + // Don't cache prototype transition if this map is shared. | 
| + if (is_shared() || !FLAG_cache_prototype_transitions) return this; | 
| + | 
| + FixedArray* cache = prototype_transitions(); | 
| + | 
| + int capacity = cache->length(); | 
| + int finger = (capacity == 0) ? 1 : Smi::cast(cache->get(0))->value(); | 
| + | 
| + if (finger >= capacity) { | 
| 
 
Mads Ager (chromium)
2011/04/26 09:14:23
I think we want to put a limit on the number of pr
 
 | 
| + FixedArray* new_cache; | 
| + { MaybeObject* maybe_cache = heap()->AllocateFixedArray(finger * 2 + 1); | 
| + if (!maybe_cache->To<FixedArray>(&new_cache)) return maybe_cache; | 
| + } | 
| + | 
| + for (int i = 1; i < capacity; i++) new_cache->set(i, cache->get(i)); | 
| + cache = new_cache; | 
| + set_prototype_transitions(cache); | 
| + } | 
| + | 
| + cache->set(finger, prototype); | 
| + cache->set(finger + 1, map); | 
| + cache->set(0, Smi::FromInt(finger + 2)); | 
| + | 
| + return cache; | 
| +} | 
| + | 
| + | 
| MaybeObject* JSObject::SetPrototype(Object* value, | 
| bool skip_hidden_prototypes) { | 
| Heap* heap = GetHeap(); | 
| @@ -6933,11 +6973,25 @@ MaybeObject* JSObject::SetPrototype(Object* value, | 
| } | 
| // Set the new prototype of the object. | 
| - Object* new_map; | 
| - { MaybeObject* maybe_new_map = real_receiver->map()->CopyDropTransitions(); | 
| - if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 
| + Map* map = real_receiver->map(); | 
| + | 
| + // Nothing to do if prototype is already set. | 
| + if (map->prototype() == value) return value; | 
| + | 
| + Object* new_map = map->GetPrototypeTransition(value); | 
| + if (new_map == NULL) { | 
| + { MaybeObject* maybe_new_map = map->CopyDropTransitions(); | 
| + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 
| + } | 
| + | 
| + { MaybeObject* maybe_new_cache = | 
| + map->PutPrototypeTransition(value, Map::cast(new_map)); | 
| + if (maybe_new_cache->IsFailure()) return maybe_new_cache; | 
| + } | 
| + | 
| + Map::cast(new_map)->set_prototype(value); | 
| } | 
| - Map::cast(new_map)->set_prototype(value); | 
| + ASSERT(Map::cast(new_map)->prototype() == value); | 
| real_receiver->set_map(Map::cast(new_map)); | 
| heap->ClearInstanceofCache(); |