Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 561273230389c5909163fd1fd253f887b7e66490..a854c7a80caf98d8e298ae350b333dfac0b3e71c 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2085,6 +2085,39 @@ void Map::LookupInDescriptors(JSObject* holder, |
} |
+// If |map| is contained in |maps_list|, returns |map|; otherwise returns NULL. |
+static bool ContainsMap(MapList* maps_list, Map* map) { |
+ for (int i = 0; i < maps_list->length(); ++i) { |
+ if (maps_list->at(i) == map) return true; |
+ } |
+ return false; |
+} |
+ |
+ |
+Map* Map::FindTransitionedMap(MapList* candidates) { |
+ ElementsKind elms_kind = elements_kind(); |
+ if (elms_kind == FAST_DOUBLE_ELEMENTS) { |
+ bool dummy = true; |
+ Map* fast_map = LookupElementsTransitionMap(FAST_ELEMENTS, &dummy); |
+ if (fast_map == NULL) return NULL; |
+ if (ContainsMap(candidates, fast_map)) return fast_map; |
+ return NULL; |
+ } |
+ if (elms_kind == FAST_SMI_ONLY_ELEMENTS) { |
+ bool dummy = true; |
+ Map* double_map = LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy); |
+ // In the current implementation, if the DOUBLE map doesn't exist, the |
+ // FAST map can't exist either. |
+ if (double_map == NULL) return NULL; |
+ Map* fast_map = double_map->LookupElementsTransitionMap(FAST_ELEMENTS, |
+ &dummy); |
+ if (fast_map != NULL && ContainsMap(candidates, fast_map)) return fast_map; |
+ if (ContainsMap(candidates, double_map)) return double_map; |
+ } |
+ return NULL; |
+} |
+ |
+ |
static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, |
ElementsKind elements_kind) { |
if (descriptor_contents->IsMap()) { |
@@ -9313,6 +9346,51 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
} |
+MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( |
+ ElementsKind to_kind) { |
+ ElementsKind from_kind = map()->elements_kind(); |
+ FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
+ uint32_t capacity = static_cast<uint32_t>(elms->length()); |
+ uint32_t length = capacity; |
+ if (IsJSArray()) { |
+ CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
+ } |
+ if (from_kind == FAST_SMI_ONLY_ELEMENTS) { |
+ if (to_kind == FAST_DOUBLE_ELEMENTS) { |
+ MaybeObject* maybe_result = |
+ SetFastDoubleElementsCapacityAndLength(capacity, length); |
+ if (maybe_result->IsFailure()) return maybe_result; |
+ return this; |
+ } else if (to_kind == FAST_ELEMENTS) { |
+ MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); |
+ Map* new_map; |
+ if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
+ set_map(new_map); |
+ return this; |
+ } |
+ } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { |
+ MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
+ capacity, length, kDontAllowSmiOnlyElements); |
+ if (maybe_result->IsFailure()) return maybe_result; |
+ return this; |
+ } |
+ // This method should never be called for any other case than the ones |
+ // handled above. |
+ UNREACHABLE(); |
+ return GetIsolate()->heap()->null_value(); |
+} |
+ |
+ |
+// static |
+bool Map::IsValidElementsTransition(ElementsKind from_kind, |
+ ElementsKind to_kind) { |
+ return |
+ (from_kind == FAST_SMI_ONLY_ELEMENTS && |
+ (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || |
+ (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); |
+} |
+ |
+ |
MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
Object* value) { |
uint32_t old_len = 0; |