| Index: src/arm64/full-codegen-arm64.cc
|
| diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc
|
| index 174658a4d8e38e2615766ed0527df2b7b311aa5a..632ec5f44ed7236216dc699f340cfebc67bcd97d 100644
|
| --- a/src/arm64/full-codegen-arm64.cc
|
| +++ b/src/arm64/full-codegen-arm64.cc
|
| @@ -1864,8 +1864,11 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|
|
| // Emit code to evaluate all the non-constant subexpressions and to store
|
| // them into the newly cloned array.
|
| - for (int i = 0; i < length; i++) {
|
| - Expression* subexpr = subexprs->at(i);
|
| + int array_index = 0;
|
| + for (; array_index < length; array_index++) {
|
| + Expression* subexpr = subexprs->at(array_index);
|
| + if (subexpr->IsSpread()) break;
|
| +
|
| // If the subexpression is a literal or a simple materialized literal it
|
| // is already set in the cloned array.
|
| if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
|
| @@ -1878,7 +1881,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
| VisitForAccumulatorValue(subexpr);
|
|
|
| if (has_fast_elements) {
|
| - int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
| + int offset = FixedArray::kHeaderSize + (array_index * kPointerSize);
|
| __ Peek(x6, kPointerSize); // Copy of array literal.
|
| __ Ldr(x1, FieldMemOperand(x6, JSObject::kElementsOffset));
|
| __ Str(result_register(), FieldMemOperand(x1, offset));
|
| @@ -1887,12 +1890,37 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
| kLRHasBeenSaved, kDontSaveFPRegs,
|
| EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
|
| } else {
|
| - __ Mov(x3, Smi::FromInt(i));
|
| + __ Mov(x3, Smi::FromInt(array_index));
|
| StoreArrayLiteralElementStub stub(isolate());
|
| __ CallStub(&stub);
|
| }
|
|
|
| - PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
|
| + PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
|
| + }
|
| +
|
| + // In case the array literal contains spread expressions it has two parts. The
|
| + // first part is the "static" array which has a literal index is handled
|
| + // above. The second part is the part after the first spread expression
|
| + // (inclusive) and these elements gets appended to the array. Note that the
|
| + // number elements an iterable produces is unknown ahead of time.
|
| + if (array_index < length && result_saved) {
|
| + __ Drop(1); // literal index
|
| + __ Pop(x0);
|
| + result_saved = false;
|
| + }
|
| + for (; array_index < length; array_index++) {
|
| + Expression* subexpr = subexprs->at(array_index);
|
| +
|
| + __ Push(x0);
|
| + if (subexpr->IsSpread()) {
|
| + VisitForStackValue(subexpr->AsSpread()->expression());
|
| + __ InvokeBuiltin(Builtins::CONCAT_ITERABLE_TO_ARRAY, CALL_FUNCTION);
|
| + } else {
|
| + VisitForStackValue(subexpr);
|
| + __ CallRuntime(Runtime::kAppendElement, 2);
|
| + }
|
| +
|
| + PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
|
| }
|
|
|
| if (result_saved) {
|
|
|