| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index 1cc5c8ba299c4a8a350388d5f437e5cd967ed239..7c2d3ef1dc9cb34e0a627938c9502b318ba86bef 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -2854,17 +2854,18 @@ void ElementsAccessor::TearDown() {
|
|
|
| Handle<JSArray> 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);
|
| @@ -2874,42 +2875,45 @@ Handle<JSArray> 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<JSArray> 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<FixedArrayBase> 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;
|
| }
|
|
|
|
|