Chromium Code Reviews| Index: src/ia32/full-codegen-ia32.cc |
| diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc |
| index c9c016394f8344c6974c0d13556d530e11c6fc34..f2248ee1caf511e1e72b6b47fbeeaa26599b5ca1 100644 |
| --- a/src/ia32/full-codegen-ia32.cc |
| +++ b/src/ia32/full-codegen-ia32.cc |
| @@ -1815,8 +1815,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; |
| @@ -1831,7 +1834,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| if (has_constant_fast_elements) { |
| // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they |
| // cannot transition and don't need to call the runtime stub. |
| - int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| + int offset = FixedArray::kHeaderSize + (array_index * kPointerSize); |
| __ mov(ebx, Operand(esp, kPointerSize)); // Copy of array literal. |
| __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); |
| // Store the subexpression value in the array's elements. |
| @@ -1843,12 +1846,37 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| INLINE_SMI_CHECK); |
| } else { |
| // Store the subexpression value in the array's elements. |
| - __ mov(ecx, Immediate(Smi::FromInt(i))); |
| + __ mov(ecx, Immediate(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) { |
| + __ add(esp, Immediate(kPointerSize)); // literal index |
|
Dmitry Lomov (no reviews)
2015/05/20 20:36:33
__ Drop(1) should work too AFAIR
arv (Not doing code reviews)
2015/05/20 20:57:44
Done.
Also fixed the old usage and x64.
|
| + __ Pop(eax); |
| + result_saved = false; |
| + } |
| + for (; array_index < length; array_index++) { |
| + Expression* subexpr = subexprs->at(array_index); |
| + |
| + __ Push(eax); |
| + 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) { |