| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 41b4fd4dbcdb7a8179e912efb007553618a098f9..89d8c42e0ae65cefa2f3b2623222e958615c22cc 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -1999,17 +1999,32 @@ void Map::LookupInDescriptors(JSObject* holder,
|
| }
|
|
|
|
|
| -MaybeObject* Map::GetElementsTransitionMap(ElementsKind elements_kind,
|
| - bool safe_to_add_transition) {
|
| - Heap* current_heap = heap();
|
| - DescriptorArray* descriptors = instance_descriptors();
|
| +MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) {
|
| + Heap* current_heap = GetHeap();
|
| + Map* current_map = map();
|
| + DescriptorArray* descriptors = current_map->instance_descriptors();
|
| String* elements_transition_sentinel_name = current_heap->empty_symbol();
|
|
|
| + if (current_map->elements_kind() == elements_kind) return current_map;
|
| +
|
| + // Only objects with FastProperties can have DescriptorArrays and can track
|
| + // element-related maps. Also don't add descriptors to maps that are shared.
|
| + bool safe_to_add_transition = HasFastProperties() &&
|
| + !current_map->IsUndefined() &&
|
| + !current_map->is_shared();
|
| +
|
| + // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps cause by objects
|
| + // with elements that switch back and forth between dictionary and fast
|
| + // element mode.
|
| + if ((current_map->elements_kind() == DICTIONARY_ELEMENTS &&
|
| + elements_kind == FAST_ELEMENTS)) {
|
| + safe_to_add_transition = false;
|
| + }
|
| +
|
| if (safe_to_add_transition) {
|
| // It's only safe to manipulate the descriptor array if it would be
|
| // safe to add a transition.
|
|
|
| - ASSERT(!is_shared()); // no transitions can be added to shared maps.
|
| // Check if the elements transition already exists.
|
| DescriptorLookupCache* cache =
|
| current_heap->isolate()->descriptor_lookup_cache();
|
| @@ -2037,13 +2052,12 @@ MaybeObject* Map::GetElementsTransitionMap(ElementsKind elements_kind,
|
| // No transition to an existing map for the given ElementsKind. Make a new
|
| // one.
|
| Object* obj;
|
| - { MaybeObject* maybe_map = CopyDropTransitions();
|
| + { MaybeObject* maybe_map = current_map->CopyDropTransitions();
|
| if (!maybe_map->ToObject(&obj)) return maybe_map;
|
| }
|
| Map* new_map = Map::cast(obj);
|
|
|
| new_map->set_elements_kind(elements_kind);
|
| - GetIsolate()->counters()->map_to_external_array_elements()->Increment();
|
|
|
| // 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
|
| @@ -2065,7 +2079,7 @@ MaybeObject* Map::GetElementsTransitionMap(ElementsKind elements_kind,
|
| return maybe_new_descriptors;
|
| }
|
| descriptors = DescriptorArray::cast(new_descriptors);
|
| - set_instance_descriptors(descriptors);
|
| + current_map->set_instance_descriptors(descriptors);
|
| }
|
|
|
| return new_map;
|
| @@ -2973,7 +2987,7 @@ MaybeObject* JSObject::NormalizeElements() {
|
| // Set the new map first to satify the elements type assert in
|
| // set_elements().
|
| Object* new_map;
|
| - MaybeObject* maybe = map()->GetSlowElementsMap();
|
| + MaybeObject* maybe = GetElementsTransitionMap(DICTIONARY_ELEMENTS);
|
| if (!maybe->ToObject(&new_map)) return maybe;
|
| set_map(Map::cast(new_map));
|
| set_elements(dictionary);
|
| @@ -7281,7 +7295,7 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
|
| Map* new_map = NULL;
|
| if (elements()->map() != heap->non_strict_arguments_elements_map()) {
|
| Object* object;
|
| - MaybeObject* maybe = map()->GetFastElementsMap();
|
| + MaybeObject* maybe = GetElementsTransitionMap(FAST_ELEMENTS);
|
| if (!maybe->ToObject(&object)) return maybe;
|
| new_map = Map::cast(object);
|
| }
|
| @@ -7384,7 +7398,8 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
|
| }
|
| FixedDoubleArray* elems = FixedDoubleArray::cast(obj);
|
|
|
| - { MaybeObject* maybe_obj = map()->GetFastDoubleElementsMap();
|
| + { MaybeObject* maybe_obj =
|
| + GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS);
|
| if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
| }
|
| Map* new_map = Map::cast(obj);
|
| @@ -10141,7 +10156,7 @@ MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
|
| // Convert to fast elements.
|
|
|
| Object* obj;
|
| - { MaybeObject* maybe_obj = map()->GetFastElementsMap();
|
| + { MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS);
|
| if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
| }
|
| Map* new_map = Map::cast(obj);
|
|
|