Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 2cdc689059898362b188889eaf37c5ab959eb1bd..862023fa2e5e8a8b62152196189963b1951afd1c 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -2022,6 +2022,70 @@ void Map::LookupInDescriptors(JSObject* holder, |
| } |
| +static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, |
| + ElementsKind elements_kind) { |
| + if (descriptor_contents->IsMap()) { |
| + Map* map = Map::cast(descriptor_contents); |
| + if (map->elements_kind() == elements_kind) { |
| + return map; |
| + } |
| + return NULL; |
| + } |
| + |
| + FixedArray* map_array = FixedArray::cast(descriptor_contents); |
| + for (int i = 0; i < map_array->length(); ++i) { |
| + Map* current_map = Map::cast(map_array->get(i)); |
| + if (current_map->elements_kind() == elements_kind) { |
| + return current_map; |
| + } |
| + } |
| + |
| + return NULL; |
| +} |
| + |
| + |
| +static MaybeObject* AddElementsTransitionMapToDescriptor( |
| + Object* descriptor_contents, |
| + Map* new_map) { |
| + // Nothing was in the descriptor for an ELEMENTS_TRANSITION, |
| + // simply add the map. |
| + if (descriptor_contents == NULL) { |
| + return new_map; |
| + } |
| + |
| + // There was already a map in the descriptor, create a 2-element FixedArray |
| + // to contain the existing map plus the new one. |
| + FixedArray* new_array; |
| + Heap* heap = new_map->GetHeap(); |
| + if (descriptor_contents->IsMap()) { |
| + MaybeObject* maybe_new_array = heap->AllocateFixedArray(2); |
| + if (!maybe_new_array->To<FixedArray>(&new_array)) { |
| + return maybe_new_array; |
| + } |
| + new_array->set(0, descriptor_contents); |
| + new_array->set(1, new_map); |
| + return new_array; |
| + } |
| + |
| + // The descriptor already contained a list of maps for different ElementKinds |
| + // of ELEMENTS_TRANSITION, create a FixedArray to hold the existing maps plus |
| + // the new one and fill it it. |
| + FixedArray* array = FixedArray::cast(descriptor_contents); |
| + MaybeObject* maybe_new_array = |
| + heap->AllocateFixedArray(array->length() + 1); |
| + if (!maybe_new_array->To<FixedArray>(&new_array)) { |
| + return maybe_new_array; |
| + } |
| + int i = 0; |
| + while (i < array->length()) { |
| + new_array->set(i, FixedArray::cast(descriptor_contents)->get(i)); |
|
Jakob Kummerow
2011/09/23 12:12:28
Simplification: s/FixedArray::cast(descriptor_cont
danno
2011/09/23 13:33:45
Done.
|
| + ++i; |
| + } |
| + new_array->set(i, new_map); |
| + return new_array; |
| +} |
| + |
| + |
| MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) { |
| Heap* current_heap = GetHeap(); |
| Map* current_map = map(); |
| @@ -2044,6 +2108,7 @@ MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) { |
| safe_to_add_transition = false; |
| } |
| + Object* descriptor_contents = NULL; |
| if (safe_to_add_transition) { |
| // It's only safe to manipulate the descriptor array if it would be |
| // safe to add a transition. |
| @@ -2063,12 +2128,14 @@ MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) { |
| // return it. |
| if (index != DescriptorArray::kNotFound) { |
| PropertyDetails details(PropertyDetails(descriptors->GetDetails(index))); |
| - if (details.type() == ELEMENTS_TRANSITION && |
| - details.elements_kind() == elements_kind) { |
| - return descriptors->GetValue(index); |
| - } else { |
| - safe_to_add_transition = false; |
| + if (details.type() == ELEMENTS_TRANSITION) { |
| + descriptor_contents = descriptors->GetValue(index); |
| + Map* maybe_transition_map = |
| + GetElementsTransitionMapFromDescriptor(descriptor_contents, |
| + elements_kind); |
| + if (maybe_transition_map) return maybe_transition_map; |
| } |
| + safe_to_add_transition = false; |
| } |
| } |
| @@ -2085,15 +2152,20 @@ MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) { |
| // Only remember the map transition if the object's map is NOT equal to the |
| // global object_function's map and there is not an already existing |
| // non-matching element transition. |
| - bool allow_map_transition = |
| - safe_to_add_transition && |
| - (GetIsolate()->context()->global_context()->object_function()->map() != |
| - map()); |
| + bool allow_map_transition = safe_to_add_transition; |
| + //&& |
| + // (GetIsolate()->context()->global_context()->object_function()->map() != |
| + // map()); |
| if (allow_map_transition) { |
| - // Allocate new instance descriptors for the old map with map transition. |
| + MaybeObject* maybe_new_contents = |
| + AddElementsTransitionMapToDescriptor(descriptor_contents, new_map); |
| + Object* new_contents; |
| + if (!maybe_new_contents->To<Object>(&new_contents)) { |
|
Jakob Kummerow
2011/09/23 12:12:28
Simplification: s/To<Object>/ToObject/
danno
2011/09/23 13:33:45
Done.
|
| + return maybe_new_contents; |
| + } |
| + |
| ElementsTransitionDescriptor desc(elements_transition_sentinel_name, |
| - Map::cast(new_map), |
| - elements_kind); |
| + new_contents); |
| Object* new_descriptors; |
| MaybeObject* maybe_new_descriptors = descriptors->CopyInsert( |
| &desc, |