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); |