From be8528b3bda429bcd2670b8ef39e37d9c341ef13 Mon Sep 17 00:00:00 2001 From: verwaest Date: Fri, 19 Jun 2015 04:21:26 -0700 Subject: [PATCH] Split setting array length from handling new Array(non-number) BUG= Review URL: https://codereview.chromium.org/1193673002 Cr-Commit-Position: refs/heads/master@{#29144} --- src/elements.cc | 144 ++++++++++++++++++++++++-------------------------------- 1 file changed, 62 insertions(+), 82 deletions(-) diff --git a/src/elements.cc b/src/elements.cc index 53bacf1..60d269a 100644 --- a/src/elements.cc +++ b/src/elements.cc @@ -1704,107 +1704,87 @@ void ElementsAccessor::TearDown() { template -MUST_USE_RESULT -MaybeHandle ElementsAccessorBase:: - SetLengthImpl(Handle obj, - Handle length, - Handle backing_store) { - Isolate* isolate = obj->GetIsolate(); +MUST_USE_RESULT MaybeHandle ElementsAccessorBase< + ElementsAccessorSubclass, + ElementsKindTraits>::SetLengthImpl(Handle obj, + Handle length_obj, + Handle backing_store) { Handle array = Handle::cast(obj); - // Fast case: The new length fits into a Smi. - Handle smi_length; - - if (Object::ToSmi(isolate, length).ToHandle(&smi_length) && - smi_length->IsSmi()) { - const int value = Handle::cast(smi_length)->value(); - if (value >= 0) { - Handle new_length = ElementsAccessorSubclass:: - SetLengthWithoutNormalize(backing_store, array, smi_length, value); - DCHECK(!new_length.is_null()); - - // even though the proposed length was a smi, new_length could - // still be a heap number because SetLengthWithoutNormalize doesn't - // allow the array length property to drop below the index of - // non-deletable elements. - DCHECK(new_length->IsSmi() || new_length->IsHeapNumber() || - new_length->IsUndefined()); - if (new_length->IsSmi()) { - array->set_length(*Handle::cast(new_length)); - return array; - } else if (new_length->IsHeapNumber()) { - array->set_length(*new_length); - return array; - } - } else { - return ThrowArrayLengthRangeError(isolate); + uint32_t length = 0; + CHECK(length_obj->ToArrayLength(&length)); + // Fast case: length fits in a smi. + if (length <= Smi::kMaxValue) { + Handle smi(Smi::FromInt(length), obj->GetIsolate()); + Handle new_length = + ElementsAccessorSubclass::SetLengthWithoutNormalize(backing_store, + array, smi, length); + DCHECK(!new_length.is_null()); + + // Even though the proposed length was a smi, new_length could + // still be a heap number because SetLengthWithoutNormalize doesn't + // allow the array length property to drop below the index of + // non-deletable elements. + DCHECK(new_length->IsSmi() || new_length->IsHeapNumber() || + new_length->IsUndefined()); + if (new_length->IsSmi()) { + array->set_length(*Handle::cast(new_length)); + return array; + } else if (new_length->IsHeapNumber()) { + array->set_length(*new_length); + return array; } } // Slow case: The new length does not fit into a Smi or conversion // to slow elements is needed for other reasons. - if (length->IsNumber()) { - uint32_t value; - if (length->ToArrayLength(&value)) { - Handle dictionary = - JSObject::NormalizeElements(array); - DCHECK(!dictionary.is_null()); - - Handle new_length = DictionaryElementsAccessor:: - SetLengthWithoutNormalize(dictionary, array, length, value); - DCHECK(!new_length.is_null()); - - DCHECK(new_length->IsNumber()); - array->set_length(*new_length); - return array; - } else { - return ThrowArrayLengthRangeError(isolate); - } - } + Handle dictionary = + JSObject::NormalizeElements(array); + DCHECK(!dictionary.is_null()); - // Fall-back case: The new length is not a number so make the array - // size one and set only element to length. - Handle new_backing_store = isolate->factory()->NewFixedArray(1); - new_backing_store->set(0, *length); - JSArray::SetContent(array, new_backing_store); + Handle new_length = + DictionaryElementsAccessor::SetLengthWithoutNormalize(dictionary, array, + length_obj, length); + DCHECK(!new_length.is_null()); + + DCHECK(new_length->IsNumber()); + array->set_length(*new_length); return array; } MaybeHandle ArrayConstructInitializeElements(Handle array, Arguments* args) { - // Optimize the case where there is one argument and the argument is a - // small smi. - if (args->length() == 1) { - Handle obj = args->at(0); - if (obj->IsSmi()) { - int len = Handle::cast(obj)->value(); - if (len > 0 && len < JSObject::kInitialMaxFastElementArray) { - ElementsKind elements_kind = array->GetElementsKind(); - JSArray::Initialize(array, len, len); - - if (!IsFastHoleyElementsKind(elements_kind)) { - elements_kind = GetHoleyElementsKind(elements_kind); - JSObject::TransitionElementsKind(array, elements_kind); - } - return array; - } else if (len == 0) { - JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); - return array; + if (args->length() == 0) { + // Optimize the case where there are no parameters passed. + JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); + return array; + + } else if (args->length() == 1 && args->at(0)->IsNumber()) { + uint32_t length; + if (!args->at(0)->ToArrayLength(&length)) { + return ThrowArrayLengthRangeError(array->GetIsolate()); + } + + // Optimize the case where there is one argument and the argument is a small + // smi. + if (length > 0 && length < JSObject::kInitialMaxFastElementArray) { + ElementsKind elements_kind = array->GetElementsKind(); + JSArray::Initialize(array, length, length); + + if (!IsFastHoleyElementsKind(elements_kind)) { + elements_kind = GetHoleyElementsKind(elements_kind); + JSObject::TransitionElementsKind(array, elements_kind); } + return array; + } else if (length == 0) { + JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); + return array; } // Take the argument as the length. JSArray::Initialize(array, 0); - - return JSArray::SetElementsLength(array, obj); - } - - // Optimize the case where there are no parameters passed. - if (args->length() == 0) { - JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); - return array; + return JSArray::SetElementsLength(array, args->at(0)); } Factory* factory = array->GetIsolate()->factory(); -- 2.7.4