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