| Index: src/json-parser.cc
|
| diff --git a/src/json-parser.cc b/src/json-parser.cc
|
| index ec1329a1c74c53d9c5f293f53b78d9d27f8b5be5..93d305df7ade2c9486b060148c23b7583c519457 100644
|
| --- a/src/json-parser.cc
|
| +++ b/src/json-parser.cc
|
| @@ -488,6 +488,46 @@ void JsonParser<seq_one_byte>::CommitStateToJsonObject(
|
| }
|
| }
|
|
|
| +class ElementKindLattice {
|
| + private:
|
| + enum {
|
| + SMI_ELEMENTS,
|
| + NUMBER_ELEMENTS,
|
| + OBJECT_ELEMENTS,
|
| + };
|
| +
|
| + public:
|
| + ElementKindLattice() : value_(SMI_ELEMENTS) {}
|
| +
|
| + void Update(Handle<Object> o) {
|
| + if (o->IsSmi()) {
|
| + return;
|
| + } else if (o->IsHeapNumber()) {
|
| + if (value_ < NUMBER_ELEMENTS) value_ = NUMBER_ELEMENTS;
|
| + } else {
|
| + DCHECK(!o->IsNumber());
|
| + value_ = OBJECT_ELEMENTS;
|
| + }
|
| + }
|
| +
|
| + ElementsKind GetElementsKind() const {
|
| + switch (value_) {
|
| + case SMI_ELEMENTS:
|
| + return FAST_SMI_ELEMENTS;
|
| + case NUMBER_ELEMENTS:
|
| + return FAST_DOUBLE_ELEMENTS;
|
| + case OBJECT_ELEMENTS:
|
| + return FAST_ELEMENTS;
|
| + default:
|
| + UNREACHABLE();
|
| + return FAST_ELEMENTS;
|
| + }
|
| + }
|
| +
|
| + private:
|
| + int value_;
|
| +};
|
| +
|
| // Parse a JSON array. Position must be right at '['.
|
| template <bool seq_one_byte>
|
| Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
|
| @@ -495,26 +535,49 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
|
| ZoneList<Handle<Object> > elements(4, zone());
|
| DCHECK_EQ(c0_, '[');
|
|
|
| + ElementKindLattice lattice;
|
| +
|
| AdvanceSkipWhitespace();
|
| if (c0_ != ']') {
|
| do {
|
| Handle<Object> element = ParseJsonValue();
|
| if (element.is_null()) return ReportUnexpectedCharacter();
|
| elements.Add(element, zone());
|
| + lattice.Update(element);
|
| } while (MatchSkipWhiteSpace(','));
|
| if (c0_ != ']') {
|
| return ReportUnexpectedCharacter();
|
| }
|
| }
|
| AdvanceSkipWhitespace();
|
| +
|
| // Allocate a fixed array with all the elements.
|
| - Handle<FixedArray> fast_elements =
|
| - factory()->NewFixedArray(elements.length(), pretenure_);
|
| - for (int i = 0, n = elements.length(); i < n; i++) {
|
| - fast_elements->set(i, *elements[i]);
|
| +
|
| + Handle<Object> json_array;
|
| + const ElementsKind kind = lattice.GetElementsKind();
|
| +
|
| + switch (kind) {
|
| + case FAST_ELEMENTS:
|
| + case FAST_SMI_ELEMENTS: {
|
| + Handle<FixedArray> elems =
|
| + factory()->NewFixedArray(elements.length(), pretenure_);
|
| + for (int i = 0; i < elements.length(); i++) elems->set(i, *elements[i]);
|
| + json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
|
| + break;
|
| + }
|
| + case FAST_DOUBLE_ELEMENTS: {
|
| + Handle<FixedDoubleArray> elems = Handle<FixedDoubleArray>::cast(
|
| + factory()->NewFixedDoubleArray(elements.length(), pretenure_));
|
| + for (int i = 0; i < elements.length(); i++) {
|
| + elems->set(i, elements[i]->Number());
|
| + }
|
| + json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
|
| + break;
|
| + }
|
| + default:
|
| + UNREACHABLE();
|
| }
|
| - Handle<Object> json_array = factory()->NewJSArrayWithElements(
|
| - fast_elements, FAST_ELEMENTS, pretenure_);
|
| +
|
| return scope.CloseAndEscape(json_array);
|
| }
|
|
|
|
|