LCOV - code coverage report
Current view: top level - src - json-parser.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 310 323 96.0 %
Date: 2017-10-20 Functions: 31 43 72.1 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/json-parser.h"
       6             : 
       7             : #include "src/char-predicates-inl.h"
       8             : #include "src/conversions.h"
       9             : #include "src/debug/debug.h"
      10             : #include "src/factory.h"
      11             : #include "src/field-type.h"
      12             : #include "src/messages.h"
      13             : #include "src/objects-inl.h"
      14             : #include "src/parsing/token.h"
      15             : #include "src/property-descriptor.h"
      16             : #include "src/string-hasher.h"
      17             : #include "src/transitions.h"
      18             : #include "src/unicode-cache.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : 
      23         153 : MaybeHandle<Object> JsonParseInternalizer::Internalize(Isolate* isolate,
      24             :                                                        Handle<Object> object,
      25             :                                                        Handle<Object> reviver) {
      26             :   DCHECK(reviver->IsCallable());
      27             :   JsonParseInternalizer internalizer(isolate,
      28             :                                      Handle<JSReceiver>::cast(reviver));
      29             :   Handle<JSObject> holder =
      30         153 :       isolate->factory()->NewJSObject(isolate->object_function());
      31             :   Handle<String> name = isolate->factory()->empty_string();
      32         153 :   JSObject::AddProperty(holder, name, object, NONE);
      33         153 :   return internalizer.InternalizeJsonProperty(holder, name);
      34             : }
      35             : 
      36       68353 : MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
      37             :     Handle<JSReceiver> holder, Handle<String> name) {
      38       68353 :   HandleScope outer_scope(isolate_);
      39             :   Handle<Object> value;
      40      136706 :   ASSIGN_RETURN_ON_EXCEPTION(
      41             :       isolate_, value, Object::GetPropertyOrElement(holder, name), Object);
      42       68353 :   if (value->IsJSReceiver()) {
      43             :     Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
      44             :     Maybe<bool> is_array = Object::IsArray(object);
      45       46201 :     if (is_array.IsNothing()) return MaybeHandle<Object>();
      46       46201 :     if (is_array.FromJust()) {
      47             :       Handle<Object> length_object;
      48       43710 :       ASSIGN_RETURN_ON_EXCEPTION(
      49             :           isolate_, length_object,
      50             :           Object::GetLengthFromArrayLike(isolate_, object), Object);
      51             :       double length = length_object->Number();
      52       43804 :       for (double i = 0; i < length; i++) {
      53       43739 :         HandleScope inner_scope(isolate_);
      54       43739 :         Handle<Object> index = isolate_->factory()->NewNumber(i);
      55       43739 :         Handle<String> name = isolate_->factory()->NumberToString(index);
      56       43739 :         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
      57             :       }
      58             :     } else {
      59             :       Handle<FixedArray> contents;
      60       48692 :       ASSIGN_RETURN_ON_EXCEPTION(
      61             :           isolate_, contents,
      62             :           KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
      63             :                                   ENUMERABLE_STRINGS,
      64             :                                   GetKeysConversion::kConvertToString),
      65             :           Object);
      66       24868 :       for (int i = 0; i < contents->length(); i++) {
      67       24471 :         HandleScope inner_scope(isolate_);
      68       24471 :         Handle<String> name(String::cast(contents->get(i)), isolate_);
      69       24471 :         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
      70             :       }
      71             :     }
      72             :   }
      73       22353 :   Handle<Object> argv[] = {name, value};
      74             :   Handle<Object> result;
      75       44706 :   ASSIGN_RETURN_ON_EXCEPTION(
      76             :       isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
      77             :       Object);
      78       22344 :   return outer_scope.CloseAndEscape(result);
      79             : }
      80             : 
      81       68210 : bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
      82             :                                             Handle<String> name) {
      83      136420 :   STACK_CHECK(isolate_, false);
      84             : 
      85             :   Handle<Object> result;
      86      136400 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
      87             :       isolate_, result, InternalizeJsonProperty(holder, name), false);
      88             :   Maybe<bool> change_result = Nothing<bool>();
      89       44420 :   if (result->IsUndefined(isolate_)) {
      90             :     change_result = JSReceiver::DeletePropertyOrElement(holder, name,
      91         116 :                                                         LanguageMode::kSloppy);
      92             :   } else {
      93             :     PropertyDescriptor desc;
      94             :     desc.set_value(result);
      95             :     desc.set_configurable(true);
      96             :     desc.set_enumerable(true);
      97             :     desc.set_writable(true);
      98             :     change_result = JSReceiver::DefineOwnProperty(isolate_, holder, name, &desc,
      99       22094 :                                                   Object::DONT_THROW);
     100             :   }
     101       22210 :   MAYBE_RETURN(change_result, false);
     102       22210 :   return true;
     103             : }
     104             : 
     105             : template <bool seq_one_byte>
     106      481563 : JsonParser<seq_one_byte>::JsonParser(Isolate* isolate, Handle<String> source)
     107             :     : source_(source),
     108             :       source_length_(source->length()),
     109             :       isolate_(isolate),
     110      481563 :       factory_(isolate_->factory()),
     111             :       zone_(isolate_->allocator(), ZONE_NAME),
     112      481563 :       object_constructor_(isolate_->native_context()->object_function(),
     113             :                           isolate_),
     114     2889378 :       position_(-1) {
     115      481563 :   source_ = String::Flatten(source_);
     116      481563 :   pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
     117             : 
     118             :   // Optimized fast case where we only have Latin1 characters.
     119             :   if (seq_one_byte) {
     120      481526 :     seq_source_ = Handle<SeqOneByteString>::cast(source_);
     121             :   }
     122      481563 : }
     123             : 
     124             : template <bool seq_one_byte>
     125      481563 : MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
     126             :   // Advance to the first character (possibly EOS)
     127             :   AdvanceSkipWhitespace();
     128      481563 :   Handle<Object> result = ParseJsonValue();
     129      481563 :   if (result.is_null() || c0_ != kEndOfString) {
     130             :     // Some exception (for example stack overflow) is already pending.
     131         715 :     if (isolate_->has_pending_exception()) return Handle<Object>::null();
     132             : 
     133             :     // Parse failed. Current character is the unexpected token.
     134             :     Factory* factory = this->factory();
     135             :     MessageTemplate::Template message;
     136             :     Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
     137             :     Handle<Object> arg2;
     138             : 
     139         686 :     switch (c0_) {
     140             :       case kEndOfString:
     141             :         message = MessageTemplate::kJsonParseUnexpectedEOS;
     142             :         break;
     143             :       case '-':
     144             :       case '0':
     145             :       case '1':
     146             :       case '2':
     147             :       case '3':
     148             :       case '4':
     149             :       case '5':
     150             :       case '6':
     151             :       case '7':
     152             :       case '8':
     153             :       case '9':
     154             :         message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
     155         100 :         break;
     156             :       case '"':
     157             :         message = MessageTemplate::kJsonParseUnexpectedTokenString;
     158         130 :         break;
     159             :       default:
     160             :         message = MessageTemplate::kJsonParseUnexpectedToken;
     161         326 :         arg2 = arg1;
     162         326 :         arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
     163         326 :         break;
     164             :     }
     165             : 
     166         686 :     Handle<Script> script(factory->NewScript(source_));
     167             :     // We should sent compile error event because we compile JSON object in
     168             :     // separated source file.
     169         686 :     isolate()->debug()->OnCompileError(script);
     170         686 :     MessageLocation location(script, position_, position_ + 1);
     171         686 :     Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
     172             :     return isolate()->template Throw<Object>(error, &location);
     173             :   }
     174      480848 :   return result;
     175             : }
     176             : 
     177             : MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
     178             :                                             Handle<String> key);
     179             : 
     180             : template <bool seq_one_byte>
     181           0 : void JsonParser<seq_one_byte>::Advance() {
     182  1216451132 :   position_++;
     183  1216451132 :   if (position_ >= source_length_) {
     184      480968 :     c0_ = kEndOfString;
     185             :   } else if (seq_one_byte) {
     186  1209991316 :     c0_ = seq_source_->SeqOneByteStringGet(position_);
     187             :   } else {
     188     5978848 :     c0_ = source_->Get(position_);
     189             :   }
     190           0 : }
     191             : 
     192             : template <bool seq_one_byte>
     193           0 : void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() {
     194   130254778 :   do {
     195             :     Advance();
     196             :   } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
     197           0 : }
     198             : 
     199             : template <bool seq_one_byte>
     200           0 : void JsonParser<seq_one_byte>::SkipWhitespace() {
     201     6429185 :   while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
     202             :     Advance();
     203             :   }
     204           0 : }
     205             : 
     206             : template <bool seq_one_byte>
     207           0 : uc32 JsonParser<seq_one_byte>::AdvanceGetChar() {
     208             :   Advance();
     209    30743053 :   return c0_;
     210             : }
     211             : 
     212             : template <bool seq_one_byte>
     213           0 : bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) {
     214    36760437 :   if (c0_ == c) {
     215             :     AdvanceSkipWhitespace();
     216             :     return true;
     217             :   }
     218             :   return false;
     219             : }
     220             : 
     221             : template <bool seq_one_byte>
     222    19497701 : bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) {
     223             :   int length = expected->length();
     224    19497701 :   if (source_->length() - position_ - 1 > length) {
     225             :     DisallowHeapAllocation no_gc;
     226    19497514 :     String::FlatContent content = expected->GetFlatContent();
     227    19497514 :     if (content.IsOneByte()) {
     228             :       DCHECK_EQ('"', c0_);
     229    19497514 :       const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
     230    19497514 :       const uint8_t* expected_chars = content.ToOneByteVector().start();
     231   187733758 :       for (int i = 0; i < length; i++) {
     232   168244948 :         uint8_t c0 = input_chars[i];
     233   168244948 :         if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
     234    19497500 :           return false;
     235             :         }
     236             :       }
     237    19488810 :       if (input_chars[length] == '"') {
     238    19488796 :         position_ = position_ + length + 1;
     239             :         AdvanceSkipWhitespace();
     240             :         return true;
     241             :       }
     242             :     }
     243             :   }
     244             :   return false;
     245             : }
     246             : 
     247             : // Parse any JSON value.
     248             : template <bool seq_one_byte>
     249    37290563 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
     250    37290563 :   StackLimitCheck stack_check(isolate_);
     251    37290563 :   if (stack_check.HasOverflowed()) {
     252          29 :     isolate_->StackOverflow();
     253             :     return Handle<Object>::null();
     254             :   }
     255             : 
     256    37290642 :   if (stack_check.InterruptRequested() &&
     257         108 :       isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
     258             :     return Handle<Object>::null();
     259             :   }
     260             : 
     261    52149486 :   if (c0_ == '"') return ParseJsonString();
     262    22431582 :   if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
     263    16982082 :   if (c0_ == '{') return ParseJsonObject();
     264     9994600 :   if (c0_ == '[') return ParseJsonArray();
     265     9561029 :   if (c0_ == 'f') {
     266     8240922 :     if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
     267             :         AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
     268             :       AdvanceSkipWhitespace();
     269     2060228 :       return factory()->false_value();
     270             :     }
     271             :     return ReportUnexpectedCharacter();
     272             :   }
     273     7500791 :   if (c0_ == 't') {
     274    22494294 :     if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
     275             :         AdvanceGetChar() == 'e') {
     276             :       AdvanceSkipWhitespace();
     277     7498098 :       return factory()->true_value();
     278             :     }
     279             :     return ReportUnexpectedCharacter();
     280             :   }
     281        2693 :   if (c0_ == 'n') {
     282        7837 :     if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
     283             :         AdvanceGetChar() == 'l') {
     284             :       AdvanceSkipWhitespace();
     285        2612 :       return factory()->null_value();
     286             :     }
     287             :     return ReportUnexpectedCharacter();
     288             :   }
     289             :   return ReportUnexpectedCharacter();
     290             : }
     291             : 
     292             : template <bool seq_one_byte>
     293      173537 : ParseElementResult JsonParser<seq_one_byte>::ParseElement(
     294             :     Handle<JSObject> json_object) {
     295             :   uint32_t index = 0;
     296             :   // Maybe an array index, try to parse it.
     297      173537 :   if (c0_ == '0') {
     298             :     // With a leading zero, the string has to be "0" only to be an index.
     299             :     Advance();
     300             :   } else {
     301      389370 :     do {
     302      389380 :       int d = c0_ - '0';
     303      389380 :       if (index > 429496729U - ((d + 3) >> 3)) break;
     304      389370 :       index = (index * 10) + d;
     305             :       Advance();
     306      389370 :     } while (IsDecimalDigit(c0_));
     307             :   }
     308             : 
     309      173537 :   if (c0_ == '"') {
     310             :     // Successfully parsed index, parse and store element.
     311             :     AdvanceSkipWhitespace();
     312             : 
     313      173487 :     if (c0_ == ':') {
     314             :       AdvanceSkipWhitespace();
     315      173487 :       Handle<Object> value = ParseJsonValue();
     316      173487 :       if (!value.is_null()) {
     317             :         JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
     318      173477 :             .Assert();
     319      173477 :         return kElementFound;
     320             :       } else {
     321             :         return kNullHandle;
     322             :       }
     323             :     }
     324             :   }
     325             :   return kElementNotFound;
     326             : }
     327             : 
     328             : // Parse a JSON object. Position must be right at '{'.
     329             : template <bool seq_one_byte>
     330     6987482 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
     331             :   HandleScope scope(isolate());
     332             :   Handle<JSObject> json_object =
     333    13974964 :       factory()->NewJSObject(object_constructor(), pretenure_);
     334             :   Handle<Map> map(json_object->map());
     335             :   int descriptor = 0;
     336     6987482 :   ZoneList<Handle<Object> > properties(8, zone());
     337             :   DCHECK_EQ(c0_, '{');
     338             : 
     339             :   bool transitioning = true;
     340             : 
     341             :   AdvanceSkipWhitespace();
     342     6987482 :   if (c0_ != '}') {
     343    59819759 :     do {
     344    29961135 :       if (c0_ != '"') return ReportUnexpectedCharacter();
     345             : 
     346    29960852 :       int start_position = position_;
     347             :       Advance();
     348             : 
     349    59921704 :       if (IsDecimalDigit(c0_)) {
     350      173537 :         ParseElementResult element_result = ParseElement(json_object);
     351      173537 :         if (element_result == kNullHandle) return Handle<Object>::null();
     352    30032537 :         if (element_result == kElementFound) continue;
     353             :       }
     354             :       // Not an index, fallback to the slow path.
     355             : 
     356    29787365 :       position_ = start_position;
     357             : #ifdef DEBUG
     358             :       c0_ = '"';
     359             : #endif
     360             : 
     361             :       Handle<String> key;
     362             :       Handle<Object> value;
     363             : 
     364             :       // Try to follow existing transitions as long as possible. Once we stop
     365             :       // transitioning, no transition can be found anymore.
     366             :       DCHECK(transitioning);
     367             :       // First check whether there is a single expected transition. If so, try
     368             :       // to parse it first.
     369             :       bool follow_expected = false;
     370             :       Handle<Map> target;
     371             :       if (seq_one_byte) {
     372             :         DisallowHeapAllocation no_gc;
     373             :         TransitionsAccessor transitions(*map, &no_gc);
     374    29687315 :         key = transitions.ExpectedTransitionKey();
     375    29687315 :         follow_expected = !key.is_null() && ParseJsonString(key);
     376             :         // If the expected transition hits, follow it.
     377    29687315 :         if (follow_expected) {
     378    19488796 :           target = transitions.ExpectedTransitionTarget();
     379             :         }
     380             :       }
     381    29687315 :       if (!follow_expected) {
     382             :         // If the expected transition failed, parse an internalized string and
     383             :         // try to find a matching transition.
     384    10298569 :         key = ParseJsonInternalizedString();
     385    10298569 :         if (key.is_null()) return ReportUnexpectedCharacter();
     386             : 
     387    10298499 :         target = TransitionsAccessor(map).FindTransitionToField(key);
     388             :         // If a transition was found, follow it and continue.
     389    10298499 :         transitioning = !target.is_null();
     390             :       }
     391    29787295 :       if (c0_ != ':') return ReportUnexpectedCharacter();
     392             : 
     393             :       AdvanceSkipWhitespace();
     394    29787295 :       value = ParseJsonValue();
     395    29787295 :       if (value.is_null()) return ReportUnexpectedCharacter();
     396             : 
     397    29787272 :       if (transitioning) {
     398             :         PropertyDetails details =
     399    29688480 :             target->instance_descriptors()->GetDetails(descriptor);
     400             :         Representation expected_representation = details.representation();
     401             : 
     402    29688480 :         if (value->FitsRepresentation(expected_representation)) {
     403    57626659 :           if (expected_representation.IsHeapObject() &&
     404             :               !target->instance_descriptors()
     405             :                    ->GetFieldType(descriptor)
     406    27941126 :                    ->NowContains(value)) {
     407             :             Handle<FieldType> value_type(
     408       13122 :                 value->OptimalType(isolate(), expected_representation));
     409       13122 :             Map::GeneralizeField(target, descriptor, details.constness(),
     410             :                                  expected_representation, value_type);
     411             :           }
     412             :           DCHECK(target->instance_descriptors()
     413             :                      ->GetFieldType(descriptor)
     414             :                      ->NowContains(value));
     415    29685533 :           properties.Add(value, zone());
     416             :           map = target;
     417    29685533 :           descriptor++;
     418             :           continue;
     419             :         } else {
     420             :           transitioning = false;
     421             :         }
     422             :       }
     423             : 
     424             :       DCHECK(!transitioning);
     425             : 
     426             :       // Commit the intermediate state to the object and stop transitioning.
     427      101739 :       CommitStateToJsonObject(json_object, map, &properties);
     428             : 
     429      101739 :       JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
     430      203478 :           .Check();
     431             :     } while (transitioning && MatchSkipWhiteSpace(','));
     432             : 
     433             :     // If we transitioned until the very end, transition the map now.
     434     6882590 :     if (transitioning) {
     435     6780851 :       CommitStateToJsonObject(json_object, map, &properties);
     436             :     } else {
     437      388730 :       while (MatchSkipWhiteSpace(',')) {
     438             :         HandleScope local_scope(isolate());
     439      286991 :         if (c0_ != '"') return ReportUnexpectedCharacter();
     440             : 
     441      286991 :         int start_position = position_;
     442             :         Advance();
     443             : 
     444      573982 :         if (IsDecimalDigit(c0_)) {
     445           0 :           ParseElementResult element_result = ParseElement(json_object);
     446           0 :           if (element_result == kNullHandle) return Handle<Object>::null();
     447           0 :           if (element_result == kElementFound) continue;
     448             :         }
     449             :         // Not an index, fallback to the slow path.
     450             : 
     451      286991 :         position_ = start_position;
     452             : #ifdef DEBUG
     453             :         c0_ = '"';
     454             : #endif
     455             : 
     456             :         Handle<String> key;
     457             :         Handle<Object> value;
     458             : 
     459      286991 :         key = ParseJsonInternalizedString();
     460      286991 :         if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
     461             : 
     462             :         AdvanceSkipWhitespace();
     463      286991 :         value = ParseJsonValue();
     464      286991 :         if (value.is_null()) return ReportUnexpectedCharacter();
     465             : 
     466             :         JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
     467      286991 :                                                           value)
     468      573982 :             .Check();
     469             :       }
     470             :     }
     471             : 
     472     6882590 :     if (c0_ != '}') {
     473             :       return ReportUnexpectedCharacter();
     474             :     }
     475             :   }
     476             :   AdvanceSkipWhitespace();
     477     6987279 :   return scope.CloseAndEscape(json_object);
     478             : }
     479             : 
     480             : template <bool seq_one_byte>
     481     6882590 : void JsonParser<seq_one_byte>::CommitStateToJsonObject(
     482             :     Handle<JSObject> json_object, Handle<Map> map,
     483    36568109 :     ZoneList<Handle<Object> >* properties) {
     484     6882590 :   JSObject::AllocateStorageForMap(json_object, map);
     485             :   DCHECK(!json_object->map()->is_dictionary_map());
     486             : 
     487             :   DisallowHeapAllocation no_gc;
     488             :   DescriptorArray* descriptors = json_object->map()->instance_descriptors();
     489             :   int length = properties->length();
     490    36568109 :   for (int i = 0; i < length; i++) {
     491    29685519 :     Handle<Object> value = (*properties)[i];
     492             :     // Initializing store.
     493    59371038 :     json_object->WriteToField(i, descriptors->GetDetails(i), *value);
     494             :   }
     495     6882590 : }
     496             : 
     497             : class ElementKindLattice {
     498             :  private:
     499             :   enum {
     500             :     SMI_ELEMENTS,
     501             :     NUMBER_ELEMENTS,
     502             :     OBJECT_ELEMENTS,
     503             :   };
     504             : 
     505             :  public:
     506      433571 :   ElementKindLattice() : value_(SMI_ELEMENTS) {}
     507             : 
     508     6512697 :   void Update(Handle<Object> o) {
     509     6512697 :     if (o->IsSmi()) {
     510     6512697 :       return;
     511     2995072 :     } else if (o->IsHeapNumber()) {
     512          44 :       if (value_ < NUMBER_ELEMENTS) value_ = NUMBER_ELEMENTS;
     513             :     } else {
     514             :       DCHECK(!o->IsNumber());
     515     2995028 :       value_ = OBJECT_ELEMENTS;
     516             :     }
     517             :   }
     518             : 
     519      385031 :   ElementsKind GetElementsKind() const {
     520      385031 :     switch (value_) {
     521             :       case SMI_ELEMENTS:
     522             :         return PACKED_SMI_ELEMENTS;
     523             :       case NUMBER_ELEMENTS:
     524          22 :         return PACKED_DOUBLE_ELEMENTS;
     525             :       case OBJECT_ELEMENTS:
     526      331199 :         return PACKED_ELEMENTS;
     527             :       default:
     528           0 :         UNREACHABLE();
     529             :         return PACKED_ELEMENTS;
     530             :     }
     531             :   }
     532             : 
     533             :  private:
     534             :   int value_;
     535             : };
     536             : 
     537             : // Parse a JSON array. Position must be right at '['.
     538             : template <bool seq_one_byte>
     539      433571 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
     540             :   HandleScope scope(isolate());
     541      433571 :   ZoneList<Handle<Object> > elements(4, zone());
     542             :   DCHECK_EQ(c0_, '[');
     543             : 
     544             :   ElementKindLattice lattice;
     545             : 
     546             :   AdvanceSkipWhitespace();
     547      433571 :   if (c0_ != ']') {
     548     6512697 :     do {
     549     6561227 :       Handle<Object> element = ParseJsonValue();
     550     6561227 :       if (element.is_null()) return ReportUnexpectedCharacter();
     551     6512697 :       elements.Add(element, zone());
     552     6512697 :       lattice.Update(element);
     553             :     } while (MatchSkipWhiteSpace(','));
     554      332540 :     if (c0_ != ']') {
     555             :       return ReportUnexpectedCharacter();
     556             :     }
     557             :   }
     558             :   AdvanceSkipWhitespace();
     559             : 
     560             :   // Allocate a fixed array with all the elements.
     561             : 
     562             :   Handle<Object> json_array;
     563      385031 :   const ElementsKind kind = lattice.GetElementsKind();
     564             : 
     565      385031 :   switch (kind) {
     566             :     case PACKED_ELEMENTS:
     567             :     case PACKED_SMI_ELEMENTS: {
     568             :       Handle<FixedArray> elems =
     569      770018 :           factory()->NewFixedArray(elements.length(), pretenure_);
     570     6849180 :       for (int i = 0; i < elements.length(); i++) elems->set(i, *elements[i]);
     571      770018 :       json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
     572             :       break;
     573             :     }
     574             :     case PACKED_DOUBLE_ELEMENTS: {
     575             :       Handle<FixedDoubleArray> elems = Handle<FixedDoubleArray>::cast(
     576          44 :           factory()->NewFixedDoubleArray(elements.length(), pretenure_));
     577          68 :       for (int i = 0; i < elements.length(); i++) {
     578          46 :         elems->set(i, elements[i]->Number());
     579             :       }
     580          44 :       json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
     581             :       break;
     582             :     }
     583             :     default:
     584           0 :       UNREACHABLE();
     585             :   }
     586             : 
     587      385031 :   return scope.CloseAndEscape(json_array);
     588             : }
     589             : 
     590             : template <bool seq_one_byte>
     591     5449500 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
     592             :   bool negative = false;
     593     5449500 :   int beg_pos = position_;
     594     5449500 :   if (c0_ == '-') {
     595             :     Advance();
     596             :     negative = true;
     597             :   }
     598     5449500 :   if (c0_ == '0') {
     599             :     Advance();
     600             :     // Prefix zero is only allowed if it's the only digit before
     601             :     // a decimal point or exponent.
     602     1505008 :     if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     603             :   } else {
     604             :     int i = 0;
     605             :     int digits = 0;
     606     4696996 :     if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
     607    11701357 :     do {
     608    11701357 :       i = i * 10 + c0_ - '0';
     609    11701357 :       digits++;
     610             :       Advance();
     611    11701357 :     } while (IsDecimalDigit(c0_));
     612     4696966 :     if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
     613             :       SkipWhitespace();
     614     9345534 :       return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
     615             :     }
     616             :   }
     617      776693 :   if (c0_ == '.') {
     618             :     Advance();
     619      248574 :     if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     620      156820 :     do {
     621             :       Advance();
     622      156820 :     } while (IsDecimalDigit(c0_));
     623             :   }
     624     1553326 :   if (AsciiAlphaToLower(c0_) == 'e') {
     625             :     Advance();
     626         120 :     if (c0_ == '-' || c0_ == '+') Advance();
     627         240 :     if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     628          80 :     do {
     629             :       Advance();
     630          80 :     } while (IsDecimalDigit(c0_));
     631             :   }
     632      776613 :   int length = position_ - beg_pos;
     633             :   double number;
     634             :   if (seq_one_byte) {
     635     1448554 :     Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
     636      724277 :     number = StringToDouble(isolate()->unicode_cache(), chars,
     637             :                             NO_FLAGS,  // Hex, octal or trailing junk.
     638      724277 :                             std::numeric_limits<double>::quiet_NaN());
     639             :   } else {
     640             :     Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
     641      104672 :     String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
     642             :     Vector<const uint8_t> result =
     643             :         Vector<const uint8_t>(buffer.start(), length);
     644       52336 :     number = StringToDouble(isolate()->unicode_cache(), result,
     645             :                             NO_FLAGS,  // Hex, octal or trailing junk.
     646       52336 :                             0.0);
     647             :     buffer.Dispose();
     648             :   }
     649             :   SkipWhitespace();
     650     1553226 :   return factory()->NewNumber(number, pretenure_);
     651             : }
     652             : 
     653             : template <typename StringType>
     654             : inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
     655             : 
     656             : template <>
     657             : inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
     658      572721 :   seq_str->SeqTwoByteStringSet(i, c);
     659             : }
     660             : 
     661             : template <>
     662             : inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
     663   750893747 :   seq_str->SeqOneByteStringSet(i, c);
     664             : }
     665             : 
     666             : template <typename StringType>
     667             : inline Handle<StringType> NewRawString(Factory* factory, int length,
     668             :                                        PretenureFlag pretenure);
     669             : 
     670             : template <>
     671       50121 : inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length,
     672             :                                              PretenureFlag pretenure) {
     673      100242 :   return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
     674             : }
     675             : 
     676             : template <>
     677     6416746 : inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length,
     678             :                                              PretenureFlag pretenure) {
     679    12833492 :   return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
     680             : }
     681             : 
     682             : // Scans the rest of a JSON string starting from position_ and writes
     683             : // prefix[start..end] along with the scanned characters into a
     684             : // sequential string of type StringType.
     685             : template <bool seq_one_byte>
     686             : template <typename StringType, typename SinkChar>
     687     6466867 : Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
     688             :     Handle<String> prefix, int start, int end) {
     689     6466867 :   int count = end - start;
     690     6466867 :   int max_length = count + source_length_ - position_;
     691     6466867 :   int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
     692             :   Handle<StringType> seq_string =
     693    12933734 :       NewRawString<StringType>(factory(), length, pretenure_);
     694             :   // Copy prefix into seq_str.
     695     6466867 :   SinkChar* dest = seq_string->GetChars();
     696     6466867 :   String::WriteToFlat(*prefix, dest, start, end);
     697             : 
     698   786581230 :   while (c0_ != '"') {
     699             :     // Check for control character (0x00-0x1f) or unterminated string (<0).
     700   776682319 :     if (c0_ < 0x20) return Handle<String>::null();
     701   776682269 :     if (count >= length) {
     702             :       // We need to create a longer sequential string for the result.
     703     3034608 :       return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
     704             :     }
     705   773647661 :     if (c0_ != '\\') {
     706             :       // If the sink can contain UC16 characters, or source_ contains only
     707             :       // Latin1 characters, there's no need to test whether we can store the
     708             :       // character. Otherwise check whether the UC16 source character can fit
     709             :       // in the Latin1 sink.
     710       38670 :       if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
     711             :           c0_ <= String::kMaxOneByteCharCode) {
     712   736103983 :         SeqStringSet(seq_string, count++, c0_);
     713             :         Advance();
     714             :       } else {
     715             :         // StringType is SeqOneByteString and we just read a non-Latin1 char.
     716          10 :         return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
     717             :       }
     718             :     } else {
     719             :       Advance();  // Advance past the \.
     720    37543668 :       switch (c0_) {
     721             :         case '"':
     722             :         case '\\':
     723             :         case '/':
     724    15362325 :           SeqStringSet(seq_string, count++, c0_);
     725             :           break;
     726             :         case 'b':
     727          15 :           SeqStringSet(seq_string, count++, '\x08');
     728             :           break;
     729             :         case 'f':
     730          10 :           SeqStringSet(seq_string, count++, '\x0c');
     731             :           break;
     732             :         case 'n':
     733    22180978 :           SeqStringSet(seq_string, count++, '\x0a');
     734             :           break;
     735             :         case 'r':
     736          15 :           SeqStringSet(seq_string, count++, '\x0d');
     737             :           break;
     738             :         case 't':
     739          10 :           SeqStringSet(seq_string, count++, '\x09');
     740             :           break;
     741             :         case 'u': {
     742             :           uc32 value = 0;
     743        1050 :           for (int i = 0; i < 4; i++) {
     744             :             Advance();
     745        1060 :             int digit = HexValue(c0_);
     746        1060 :             if (digit < 0) {
     747             :               return Handle<String>::null();
     748             :             }
     749        1050 :             value = value * 16 + digit;
     750             :           }
     751         110 :           if (sizeof(SinkChar) == kUC16Size ||
     752             :               value <= String::kMaxOneByteCharCode) {
     753         160 :             SeqStringSet(seq_string, count++, value);
     754             :             break;
     755             :           } else {
     756             :             // StringType is SeqOneByteString and we just read a non-Latin1
     757             :             // char.
     758          95 :             position_ -= 6;  // Rewind position_ to \ in \uxxxx.
     759             :             Advance();
     760          95 :             return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0,
     761          95 :                                                               count);
     762             :           }
     763             :         }
     764             :         default:
     765             :           return Handle<String>::null();
     766             :       }
     767             :       Advance();
     768             :     }
     769             :   }
     770             : 
     771             :   DCHECK_EQ('"', c0_);
     772             :   // Advance past the last '"'.
     773             :   AdvanceSkipWhitespace();
     774             : 
     775             :   // Shrink seq_string length to count and return.
     776     3432044 :   return SeqString::Truncate(seq_string, count);
     777             : }
     778             : 
     779             : template <bool seq_one_byte>
     780             : template <bool is_internalized>
     781    25444512 : Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
     782             :   DCHECK_EQ('"', c0_);
     783             :   Advance();
     784    25444512 :   if (c0_ == '"') {
     785             :     AdvanceSkipWhitespace();
     786             :     return factory()->empty_string();
     787             :   }
     788             : 
     789             :   if (seq_one_byte && is_internalized) {
     790             :     // Fast path for existing internalized strings.  If the the string being
     791             :     // parsed is not a known internalized string, contains backslashes or
     792             :     // unexpectedly reaches the end of string, return with an empty handle.
     793             : 
     794             :     // We intentionally use local variables instead of fields, compute hash
     795             :     // while we are iterating a string and manually inline StringTable lookup
     796             :     // here.
     797             :     uint32_t running_hash = isolate()->heap()->HashSeed();
     798    10435434 :     int position = position_;
     799             :     uc32 c0 = c0_;
     800    62497943 :     do {
     801    62498003 :       if (c0 == '\\') {
     802          30 :         c0_ = c0;
     803             :         int beg_pos = position_;
     804          30 :         position_ = position;
     805             :         return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
     806          30 :                                                              position_);
     807             :       }
     808    62497973 :       if (c0 < 0x20) {
     809          20 :         c0_ = c0;
     810          20 :         position_ = position;
     811             :         return Handle<String>::null();
     812             :       }
     813             :       running_hash = StringHasher::AddCharacterCore(running_hash,
     814    62497953 :                                                     static_cast<uint16_t>(c0));
     815    62497953 :       position++;
     816    62497953 :       if (position >= source_length_) {
     817          10 :         c0_ = kEndOfString;
     818          10 :         position_ = position;
     819             :         return Handle<String>::null();
     820             :       }
     821    62497943 :       c0 = seq_source_->SeqOneByteStringGet(position);
     822             :     } while (c0 != '"');
     823    10435374 :     int length = position - position_;
     824             :     uint32_t hash = (length <= String::kMaxHashCalcLength)
     825             :                         ? StringHasher::GetHashCore(running_hash)
     826    10435374 :                         : static_cast<uint32_t>(length);
     827    10435374 :     Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
     828    20870748 :                                         length);
     829    10435374 :     StringTable* string_table = isolate()->heap()->string_table();
     830    10435374 :     uint32_t capacity = string_table->Capacity();
     831             :     uint32_t entry = StringTable::FirstProbe(hash, capacity);
     832             :     uint32_t count = 1;
     833             :     Handle<String> result;
     834             :     while (true) {
     835    12623873 :       Object* element = string_table->KeyAt(entry);
     836    12623873 :       if (element->IsUndefined(isolate())) {
     837             :         // Lookup failure.
     838      224008 :         result =
     839             :             factory()->InternalizeOneByteString(seq_source_, position_, length);
     840      112004 :         break;
     841             :       }
     842    24839538 :       if (!element->IsTheHole(isolate()) &&
     843    12327669 :           String::cast(element)->IsOneByteEqualTo(string_vector)) {
     844             :         result = Handle<String>(String::cast(element), isolate());
     845             : #ifdef DEBUG
     846             :         uint32_t hash_field =
     847             :             (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
     848             :         DCHECK_EQ(static_cast<int>(result->Hash()),
     849             :                   static_cast<int>(hash_field >> String::kHashShift));
     850             : #endif
     851    10323370 :         break;
     852             :       }
     853     2188499 :       entry = StringTable::NextProbe(entry, count++, capacity);
     854             :     }
     855    10435374 :     position_ = position;
     856             :     // Advance past the last '"'.
     857             :     AdvanceSkipWhitespace();
     858    12623873 :     return result;
     859             :   }
     860             : 
     861    14874594 :   int beg_pos = position_;
     862             :   // Fast case for Latin1 only without escape characters.
     863   174389816 :   do {
     864             :     // Check for control character (0x00-0x1f) or unterminated string (<0).
     865   177821970 :     if (c0_ < 0x20) return Handle<String>::null();
     866   177821940 :     if (c0_ != '\\') {
     867      890015 :       if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
     868             :         Advance();
     869             :       } else {
     870       50016 :         return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos,
     871       50016 :                                                           position_);
     872             :       }
     873             :     } else {
     874     3382108 :       return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
     875     3382108 :                                                            position_);
     876             :     }
     877             :   } while (c0_ != '"');
     878    11442440 :   int length = position_ - beg_pos;
     879             :   Handle<String> result =
     880    34327320 :       factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
     881    11442440 :   uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
     882    22884880 :   String::WriteToFlat(*source_, dest, beg_pos, position_);
     883             : 
     884             :   DCHECK_EQ('"', c0_);
     885             :   // Advance past the last '"'.
     886             :   AdvanceSkipWhitespace();
     887    11442440 :   return result;
     888             : }
     889             : 
     890             : // Explicit instantiation.
     891             : template class JsonParser<true>;
     892             : template class JsonParser<false>;
     893             : 
     894             : }  // namespace internal
     895             : }  // namespace v8

Generated by: LCOV version 1.10