diff options
Diffstat (limited to 'chromium/v8/src/json-parser.cc')
-rw-r--r-- | chromium/v8/src/json-parser.cc | 76 |
1 files changed, 70 insertions, 6 deletions
diff --git a/chromium/v8/src/json-parser.cc b/chromium/v8/src/json-parser.cc index de404e4c629..93d305df7ad 100644 --- a/chromium/v8/src/json-parser.cc +++ b/chromium/v8/src/json-parser.cc @@ -13,6 +13,7 @@ #include "src/objects-inl.h" #include "src/parsing/token.h" #include "src/property-descriptor.h" +#include "src/string-hasher.h" #include "src/transitions.h" #include "src/unicode-cache.h" @@ -487,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() { @@ -494,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); } |