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); |
} |