Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index fb09978d5770a176b42ec54e0620cd6e205868aa..123218b84d1241db7b9afc13e8d039a222de6f40 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2243,7 +2243,12 @@ Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { |
static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { |
Map* current_map = map; |
int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); |
- int to_index = GetSequenceIndexFromFastElementsKind(to_kind); |
+ int to_index = IsFastElementsKind(to_kind) |
+ ? GetSequenceIndexFromFastElementsKind(to_kind) |
+ : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
+ |
+ ASSERT(index <= to_index); |
+ |
for (; index < to_index; ++index) { |
Map* next_map = current_map->elements_transition_map(); |
if (next_map == NULL) { |
@@ -2251,27 +2256,36 @@ static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { |
} |
current_map = next_map; |
} |
- ASSERT(current_map->elements_kind() == to_kind); |
+ if (!IsFastElementsKind(to_kind)) { |
+ Map* next_map = current_map->elements_transition_map(); |
+ if (next_map != NULL && next_map->elements_kind() == to_kind) { |
+ return next_map; |
+ } |
+ ASSERT(current_map->elements_kind() == TERMINAL_FAST_ELEMENTS_KIND); |
+ } else { |
+ ASSERT(current_map->elements_kind() == to_kind); |
+ } |
return current_map; |
} |
Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { |
- if (this->instance_descriptors()->MayContainTransitions() && |
- IsMoreGeneralElementsKindTransition(this->elements_kind(), to_kind)) { |
- Map* to_map = FindClosestElementsTransition(this, to_kind); |
- if (to_map->elements_kind() == to_kind) { |
- return to_map; |
- } |
- } |
+ Map* to_map = FindClosestElementsTransition(this, to_kind); |
+ if (to_map->elements_kind() == to_kind) return to_map; |
return NULL; |
} |
MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) { |
- ASSERT(elements_transition_map() == NULL); |
- ASSERT(GetSequenceIndexFromFastElementsKind(elements_kind()) == |
- (GetSequenceIndexFromFastElementsKind(next_kind) - 1)); |
+ ASSERT(elements_transition_map() == NULL || |
+ ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || |
+ IsExternalArrayElementsKind( |
+ elements_transition_map()->elements_kind())) && |
+ (next_kind == DICTIONARY_ELEMENTS || |
+ IsExternalArrayElementsKind(next_kind)))); |
+ ASSERT(!IsFastElementsKind(next_kind) || |
+ IsMoreGeneralElementsKindTransition(elements_kind(), next_kind)); |
+ ASSERT(next_kind != elements_kind()); |
Map* next_map; |
MaybeObject* maybe_next_map = |
@@ -2287,19 +2301,31 @@ MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) { |
static MaybeObject* AddMissingElementsTransitions(Map* map, |
ElementsKind to_kind) { |
- int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()) + 1; |
- int to_index = GetSequenceIndexFromFastElementsKind(to_kind); |
+ ASSERT(IsFastElementsKind(map->elements_kind())); |
+ int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); |
+ int to_index = IsFastElementsKind(to_kind) |
+ ? GetSequenceIndexFromFastElementsKind(to_kind) |
+ : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
+ |
ASSERT(index <= to_index); |
Map* current_map = map; |
- for (; index <= to_index; ++index) { |
- ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index); |
+ for (; index < to_index; ++index) { |
+ ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1); |
MaybeObject* maybe_next_map = |
current_map->CreateNextElementsTransition(next_kind); |
if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
} |
+ // In case we are exiting the fast elements kind system, just add the map in |
+ // the end. |
+ if (!IsFastElementsKind(to_kind)) { |
+ MaybeObject* maybe_next_map = |
+ current_map->CreateNextElementsTransition(to_kind); |
+ if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
+ } |
+ |
ASSERT(current_map->elements_kind() == to_kind); |
return current_map; |
} |
@@ -2345,10 +2371,14 @@ MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) { |
// non-matching element transition. |
(global_context->object_function()->map() != map()) && |
!start_map->IsUndefined() && !start_map->is_shared() && |
- // Only store fast element maps in ascending generality. |
- IsTransitionableFastElementsKind(from_kind) && |
- IsFastElementsKind(to_kind) && |
- IsMoreGeneralElementsKindTransition(from_kind, to_kind); |
+ IsFastElementsKind(from_kind); |
+ |
+ // Only store fast element maps in ascending generality. |
+ if (IsFastElementsKind(to_kind)) { |
+ allow_store_transition &= |
+ IsTransitionableFastElementsKind(from_kind) && |
+ IsMoreGeneralElementsKindTransition(from_kind, to_kind); |
+ } |
if (!allow_store_transition) { |
// Create a new free-floating map only if we are not allowed to store it. |
@@ -5063,7 +5093,7 @@ class IntrusiveMapTransitionIterator { |
if (index == descriptor_array_->number_of_descriptors()) { |
Map* elements_transition = descriptor_array_->elements_transition_map(); |
if (elements_transition != NULL) { |
- *DescriptorArrayHeader() = Smi::FromInt(index + 1); |
+ *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2); |
return elements_transition; |
} |
} |
@@ -5765,24 +5795,18 @@ MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, |
Heap* heap = Isolate::Current()->heap(); |
// Do not use DescriptorArray::cast on incomplete object. |
FixedArray* result; |
- if (number_of_descriptors == 0) { |
- if (shared_mode == MAY_BE_SHARED) { |
- return heap->empty_descriptor_array(); |
- } |
- { MaybeObject* maybe_array = |
- heap->AllocateFixedArray(kTransitionsIndex + 1); |
- if (!maybe_array->To(&result)) return maybe_array; |
- } |
- } else { |
- // Allocate the array of keys. |
- { MaybeObject* maybe_array = |
- heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); |
- if (!maybe_array->To(&result)) return maybe_array; |
- } |
- result->set(kEnumerationIndexIndex, |
- Smi::FromInt(PropertyDetails::kInitialIndex)); |
+ if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) { |
+ return heap->empty_descriptor_array(); |
+ } |
+ // Allocate the array of keys. |
+ { MaybeObject* maybe_array = |
+ heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); |
+ if (!maybe_array->To(&result)) return maybe_array; |
} |
+ |
result->set(kBitField3StorageIndex, Smi::FromInt(0)); |
+ result->set(kEnumerationIndexIndex, |
+ Smi::FromInt(PropertyDetails::kInitialIndex)); |
result->set(kTransitionsIndex, Smi::FromInt(0)); |
return result; |
} |