diff --git a/src/elements.cc b/src/elements.cc index 6dd2a491950..6906fd47de7 100644 --- a/src/elements.cc +++ b/src/elements.cc @@ -2880,17 +2880,18 @@ void ElementsAccessor::TearDown() { Handle ElementsAccessor::Concat(Isolate* isolate, Arguments* args, uint32_t concat_size) { - int result_len = 0; - ElementsKind elements_kind = GetInitialFastElementsKind(); - bool has_double = false; + uint32_t result_len = 0; + bool has_raw_doubles = false; + ElementsKind result_elements_kind = GetInitialFastElementsKind(); { DisallowHeapAllocation no_gc; + bool is_holey = false; // Iterate through all the arguments performing checks // and calculating total length. - bool is_holey = false; for (uint32_t i = 0; i < concat_size; i++) { - Object* arg = (*args)[i]; - int len = Smi::cast(JSArray::cast(arg)->length())->value(); + JSArray* array = JSArray::cast((*args)[i]); + uint32_t len = 0; + array->length()->ToArrayLength(&len); // We shouldn't overflow when adding another len. const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); @@ -2900,42 +2901,45 @@ Handle ElementsAccessor::Concat(Isolate* isolate, Arguments* args, DCHECK(0 <= result_len); DCHECK(result_len <= FixedDoubleArray::kMaxLength); - ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); - has_double = has_double || IsFastDoubleElementsKind(arg_kind); + ElementsKind arg_kind = array->GetElementsKind(); + has_raw_doubles = has_raw_doubles || IsFastDoubleElementsKind(arg_kind); is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); - elements_kind = GetMoreGeneralElementsKind(elements_kind, arg_kind); + result_elements_kind = + GetMoreGeneralElementsKind(result_elements_kind, arg_kind); } if (is_holey) { - elements_kind = GetHoleyElementsKind(elements_kind); + result_elements_kind = GetHoleyElementsKind(result_elements_kind); } } // If a double array is concatted into a fast elements array, the fast // elements array needs to be initialized to contain proper holes, since // boxing doubles may cause incremental marking. - ArrayStorageAllocationMode mode = - has_double && IsFastObjectElementsKind(elements_kind) - ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE - : DONT_INITIALIZE_ARRAY_ELEMENTS; + bool requires_double_boxing = + has_raw_doubles && !IsFastDoubleElementsKind(result_elements_kind); + ArrayStorageAllocationMode mode = requires_double_boxing + ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE + : DONT_INITIALIZE_ARRAY_ELEMENTS; Handle result_array = isolate->factory()->NewJSArray( - elements_kind, result_len, result_len, mode); + result_elements_kind, result_len, result_len, mode); if (result_len == 0) return result_array; - int j = 0; + + uint32_t insertion_index = 0; Handle storage(result_array->elements(), isolate); - ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); + ElementsAccessor* accessor = ElementsAccessor::ForKind(result_elements_kind); for (uint32_t i = 0; i < concat_size; i++) { // It is crucial to keep |array| in a raw pointer form to avoid // performance degradation. JSArray* array = JSArray::cast((*args)[i]); - int len = Smi::cast(array->length())->value(); - if (len > 0) { - ElementsKind from_kind = array->GetElementsKind(); - accessor->CopyElements(array, 0, from_kind, storage, j, len); - j += len; - } + uint32_t len = 0; + array->length()->ToArrayLength(&len); + if (len == 0) continue; + ElementsKind from_kind = array->GetElementsKind(); + accessor->CopyElements(array, 0, from_kind, storage, insertion_index, len); + insertion_index += len; } - DCHECK(j == result_len); + DCHECK_EQ(insertion_index, result_len); return result_array; }