During parsing, we now keep track of the first spread seen in an array
literal (if any), and make use of that information when creating the
FixedArray backing store representing the constant elements for array
literal materialization.
The old code tried to do this by setting the generated JSArray's length
in ArrayLiteral::BuildConstantElements(), but that Array length is never
read by the rest of the literal materialization code (it always uses
the length of the FixedArray backing store).
BUG=v8:4298
LOG=n
Review URL: https://codereview.chromium.org/
1225223004
Cr-Commit-Position: refs/heads/master@{#29684}
void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
if (!constant_elements_.is_null()) return;
+ int constants_length =
+ first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
+
// Allocate a fixed array to hold all the object literals.
Handle<JSArray> array = isolate->factory()->NewJSArray(
- FAST_HOLEY_SMI_ELEMENTS, values()->length(), values()->length(),
+ FAST_HOLEY_SMI_ELEMENTS, constants_length, constants_length,
Strength::WEAK, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
// Fill in the literals.
int depth_acc = 1;
bool is_holey = false;
int array_index = 0;
- for (int n = values()->length(); array_index < n; array_index++) {
+ for (; array_index < constants_length; array_index++) {
Expression* element = values()->at(array_index);
- if (element->IsSpread()) break;
+ DCHECK(!element->IsSpread());
MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
if (m_literal != NULL) {
m_literal->BuildConstants(isolate);
.Assert();
}
- if (array_index != values()->length()) {
- JSArray::SetLength(array, array_index);
- }
JSObject::ValidateElements(array);
Handle<FixedArrayBase> element_values(array->elements());
};
protected:
- ArrayLiteral(Zone* zone, ZoneList<Expression*>* values, int literal_index,
- bool is_strong, int pos)
+ ArrayLiteral(Zone* zone, ZoneList<Expression*>* values,
+ int first_spread_index, int literal_index, bool is_strong,
+ int pos)
: MaterializedLiteral(zone, literal_index, is_strong, pos),
- values_(values) {}
+ values_(values),
+ first_spread_index_(first_spread_index) {}
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
private:
Handle<FixedArray> constant_elements_;
ZoneList<Expression*>* values_;
+ int first_spread_index_;
};
int literal_index,
bool is_strong,
int pos) {
- return new (zone_) ArrayLiteral(zone_, values, literal_index, is_strong,
- pos);
+ return new (zone_)
+ ArrayLiteral(zone_, values, -1, literal_index, is_strong, pos);
+ }
+
+ ArrayLiteral* NewArrayLiteral(ZoneList<Expression*>* values,
+ int first_spread_index, int literal_index,
+ bool is_strong, int pos) {
+ return new (zone_) ArrayLiteral(zone_, values, first_spread_index,
+ literal_index, is_strong, pos);
}
VariableProxy* NewVariableProxy(Variable* var,
int pos) {
return PreParserExpression::Default();
}
+ PreParserExpression NewArrayLiteral(PreParserExpressionList values,
+ int first_spread_index, int literal_index,
+ bool is_strong, int pos) {
+ return PreParserExpression::Default();
+ }
PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
PreParserExpression value,
ObjectLiteralProperty::Kind kind,
int pos = peek_position();
typename Traits::Type::ExpressionList values =
this->NewExpressionList(4, zone_);
+ int first_spread_index = -1;
Expect(Token::LBRACK, CHECK_OK);
while (peek() != Token::RBRACK) {
bool seen_spread = false;
this->ParseAssignmentExpression(true, classifier, CHECK_OK);
elem = factory()->NewSpread(argument, start_pos);
seen_spread = true;
+ if (first_spread_index < 0) {
+ first_spread_index = values->length();
+ }
} else {
elem = this->ParseAssignmentExpression(true, classifier, CHECK_OK);
}
// Update the scope information before the pre-parsing bailout.
int literal_index = function_state_->NextMaterializedLiteralIndex();
- return factory()->NewArrayLiteral(values, literal_index,
+ return factory()->NewArrayLiteral(values, first_spread_index, literal_index,
is_strong(language_mode()), pos);
}
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --harmony-spread-arrays
+
+var arr = [1, 2, ...[3]];
+assertEquals([1, 2, 3], arr);