| Index: src/compiler/ast-graph-builder.cc
|
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
|
| index 2d92ca5d82626edae4bf3dfb9b4f82a0233c7f85..1c9809958c33cf3fdb97c34b7120514b12b23db0 100644
|
| --- a/src/compiler/ast-graph-builder.cc
|
| +++ b/src/compiler/ast-graph-builder.cc
|
| @@ -1927,23 +1927,64 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
|
|
| // Create nodes to evaluate all the non-constant subexpressions and to store
|
| // them into the newly cloned array.
|
| - for (int i = 0; i < expr->values()->length(); i++) {
|
| - Expression* subexpr = expr->values()->at(i);
|
| + int array_index = 0;
|
| + for (; array_index < expr->values()->length(); array_index++) {
|
| + Expression* subexpr = expr->values()->at(array_index);
|
| + if (subexpr->IsSpread()) break;
|
| if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
|
|
|
| VisitForValue(subexpr);
|
| {
|
| FrameStateBeforeAndAfter states(this, subexpr->id());
|
| Node* value = environment()->Pop();
|
| - Node* index = jsgraph()->Constant(i);
|
| + Node* index = jsgraph()->Constant(array_index);
|
| Node* store =
|
| BuildKeyedStore(literal, index, value, TypeFeedbackId::None());
|
| - states.AddToNode(store, expr->GetIdForElement(i),
|
| + states.AddToNode(store, expr->GetIdForElement(array_index),
|
| OutputFrameStateCombine::Ignore());
|
| }
|
| }
|
|
|
| - environment()->Pop(); // Array literal index.
|
| + // 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.
|
| + bool has_spread = array_index < expr->values()->length();
|
| + if (has_spread) {
|
| + environment()->Pop(); // Array literal index.
|
| + }
|
| +
|
| + for (; array_index < expr->values()->length(); array_index++) {
|
| + Expression* subexpr = expr->values()->at(array_index);
|
| + Node* array = environment()->Pop();
|
| + Node* result;
|
| +
|
| + if (subexpr->IsSpread()) {
|
| + VisitForValue(subexpr->AsSpread()->expression());
|
| + Node* iterable = environment()->Pop();
|
| + Node* builtins = BuildLoadBuiltinsObject();
|
| + Node* function = BuildLoadObjectField(
|
| + builtins, JSBuiltinsObject::OffsetOfFunctionWithId(
|
| + Builtins::CONCAT_ITERABLE_TO_ARRAY));
|
| + result = NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS,
|
| + language_mode()),
|
| + function, array, iterable);
|
| + } else {
|
| + VisitForValue(subexpr);
|
| + Node* value = environment()->Pop();
|
| + const Operator* op =
|
| + javascript()->CallRuntime(Runtime::kAppendElement, 2);
|
| + result = NewNode(op, array, value);
|
| + }
|
| +
|
| + PrepareFrameState(result, expr->GetIdForElement(array_index));
|
| + environment()->Push(result);
|
| + }
|
| +
|
| + if (!has_spread) {
|
| + environment()->Pop(); // Array literal index.
|
| + }
|
| ast_context()->ProduceValue(environment()->Pop());
|
| }
|
|
|
|
|