Chromium Code Reviews| 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 |
|
Jakob Kummerow
2011/10/18 15:42:36
nit: s/transitions/transition/
danno
2011/10/19 11:36:39
Done.
|
| + // 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) { |
|
Jakob Kummerow
2011/10/18 15:42:36
This code works, but it's brittle, as it subtly re
danno
2011/10/19 11:36:39
Done.
|
| + 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); |
| } |