| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index b272fa9e07fc9629921c900ab2a94e80619fbf4c..d93d2a6d11898a8c8440dfd7c22bae6dbfd61543 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -3288,9 +3288,11 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
|
| // Update the scope information before the pre-parsing bailout.
|
| int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
|
|
|
| - // Allocate a fixed array with all the literals.
|
| - Handle<FixedArray> literals =
|
| + // Allocate a fixed array to hold all the object literals.
|
| + Handle<FixedArray> object_literals =
|
| isolate()->factory()->NewFixedArray(values->length(), TENURED);
|
| + Handle<FixedDoubleArray> double_literals;
|
| + ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS;
|
|
|
| // Fill in the literals.
|
| bool is_simple = true;
|
| @@ -3302,19 +3304,75 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
|
| }
|
| Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
|
| if (boilerplate_value->IsUndefined()) {
|
| - literals->set_the_hole(i);
|
| + object_literals->set_the_hole(i);
|
| + if (elements_kind == FAST_DOUBLE_ELEMENTS) {
|
| + double_literals->set_the_hole(i);
|
| + }
|
| is_simple = false;
|
| } else {
|
| - literals->set(i, *boilerplate_value);
|
| + // Examine each literal element, and adjust the ElementsKind if the
|
| + // literal element is not of a type that can be stored in the current
|
| + // ElementsKind. Start with FAST_SMI_ONLY_ELEMENTS, and transitions to
|
| + // FAST_DOUBLE_ELEMENTS and FAST_ELEMENTS as necessary. Always remember
|
| + // the tagged value, no matter what the ElementsKind is in case we
|
| + // ultimately end up in FAST_ELEMENTS.
|
| + object_literals->set(i, *boilerplate_value);
|
| + if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
|
| + // Smi only elements. Notice if a transition to FAST_DOUBLE_ELEMENTS or
|
| + // FAST_ELEMENTS is required.
|
| + if (!boilerplate_value->IsSmi()) {
|
| + if (boilerplate_value->IsNumber() && FLAG_smi_only_arrays) {
|
| + // Allocate a double array on the FAST_DOUBLE_ELEMENTS transition to
|
| + // avoid over-allocating in TENURED space.
|
| + double_literals = isolate()->factory()->NewFixedDoubleArray(
|
| + values->length(), TENURED);
|
| + // Copy the contents of the FAST_SMI_ONLY_ELEMENT array to the
|
| + // FAST_DOUBLE_ELEMENTS array so that they are in sync.
|
| + for (int j = 0; j < i; ++j) {
|
| + Object* smi_value = object_literals->get(j);
|
| + if (smi_value->IsTheHole()) {
|
| + double_literals->set_the_hole(j);
|
| + } else {
|
| + double_literals->set(j, Smi::cast(smi_value)->value());
|
| + }
|
| + }
|
| + elements_kind = FAST_DOUBLE_ELEMENTS;
|
| + } else {
|
| + elements_kind = FAST_ELEMENTS;
|
| + }
|
| + }
|
| + }
|
| + if (elements_kind == FAST_DOUBLE_ELEMENTS) {
|
| + // Continue to store double values in to FAST_DOUBLE_ELEMENTS arrays
|
| + // until the first value is seen that can't be stored as a double.
|
| + if (boilerplate_value->IsNumber()) {
|
| + double_literals->set(i, boilerplate_value->Number());
|
| + } else {
|
| + elements_kind = FAST_ELEMENTS;
|
| + }
|
| + }
|
| }
|
| }
|
|
|
| // Simple and shallow arrays can be lazily copied, we transform the
|
| // elements array to a copy-on-write array.
|
| - if (is_simple && depth == 1 && values->length() > 0) {
|
| - literals->set_map(isolate()->heap()->fixed_cow_array_map());
|
| + if (is_simple && depth == 1 && values->length() > 0 &&
|
| + elements_kind != FAST_DOUBLE_ELEMENTS) {
|
| + object_literals->set_map(isolate()->heap()->fixed_cow_array_map());
|
| }
|
|
|
| + Handle<FixedArrayBase> element_values = elements_kind == FAST_DOUBLE_ELEMENTS
|
| + ? Handle<FixedArrayBase>(double_literals)
|
| + : Handle<FixedArrayBase>(object_literals);
|
| +
|
| + // Remember both the literal's constant values as well as the ElementsKind
|
| + // in a 2-element FixedArray.
|
| + Handle<FixedArray> literals =
|
| + isolate()->factory()->NewFixedArray(2, TENURED);
|
| +
|
| + literals->set(0, Smi::FromInt(elements_kind));
|
| + literals->set(1, *element_values);
|
| +
|
| return new(zone()) ArrayLiteral(
|
| isolate(), literals, values, literal_index, is_simple, depth);
|
| }
|
|
|