From fc146e9e91350eb455e1a5bc71c46733413dd054 Mon Sep 17 00:00:00 2001 From: mbrandy Date: Thu, 21 May 2015 08:35:46 -0700 Subject: [PATCH] PPC: [es6] Spread in array literals Port 9502e91adbed48a546463aa848656d07619d14e6 Original commit message: This allows you to put iterables into your array literals and the will get spread into the array. let x = [0, ...range(1, 3)]; // [0, 1, 2] This is done by treating the array literal up to the first spread element as usual, including using a boiler plate array, and then appending the remaining expressions and rest expressions. R=arv@chromium.org, dstence@us.ibm.com, michael_dawson@ca.ibm.com BUG= Review URL: https://codereview.chromium.org/1149873005 Cr-Commit-Position: refs/heads/master@{#28560} --- src/ppc/full-codegen-ppc.cc | 39 +++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/ppc/full-codegen-ppc.cc b/src/ppc/full-codegen-ppc.cc index abb17a1c4b..75415e14f5 100644 --- a/src/ppc/full-codegen-ppc.cc +++ b/src/ppc/full-codegen-ppc.cc @@ -1848,8 +1848,10 @@ 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; @@ -1862,7 +1864,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); __ LoadP(r8, MemOperand(sp, kPointerSize)); // Copy of array literal. __ LoadP(r4, FieldMemOperand(r8, JSObject::kElementsOffset)); __ StoreP(result_register(), FieldMemOperand(r4, offset), r0); @@ -1871,16 +1873,41 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { kDontSaveFPRegs, EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); } else { - __ LoadSmiLiteral(r6, Smi::FromInt(i)); + __ LoadSmiLiteral(r6, 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(r3); + result_saved = false; + } + for (; array_index < length; array_index++) { + Expression* subexpr = subexprs->at(array_index); + + __ Push(r3); + 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) { - __ pop(); // literal index + __ Drop(1); // literal index context()->PlugTOS(); } else { context()->Plug(r3);