LCOV - code coverage report
Current view: top level - src - json-parser.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 333 350 95.1 %
Date: 2019-02-19 Functions: 32 44 72.7 %

          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/field-type.h"
      11             : #include "src/hash-seed-inl.h"
      12             : #include "src/heap/heap-inl.h"  // For string_table().
      13             : #include "src/message-template.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/hash-table-inl.h"
      16             : #include "src/property-descriptor.h"
      17             : #include "src/string-hasher.h"
      18             : #include "src/transitions.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : 
      23             : namespace {
      24             : 
      25             : // A vector-like data structure that uses a larger vector for allocation, and
      26             : // provides limited utility access. The original vector must not be used for the
      27             : // duration, and it may even be reallocated. This allows vector storage to be
      28             : // reused for the properties of sibling objects.
      29             : template <typename Container>
      30             : class VectorSegment {
      31             :  public:
      32             :   using value_type = typename Container::value_type;
      33             : 
      34             :   explicit VectorSegment(Container* container)
      35     7822550 :       : container_(*container), begin_(container->size()) {}
      36     7822550 :   ~VectorSegment() { container_.resize(begin_); }
      37             : 
      38             :   Vector<const value_type> GetVector() const {
      39             :     return VectorOf(container_) + begin_;
      40             :   }
      41             : 
      42             :   template <typename T>
      43             :   void push_back(T&& value) {
      44    33279643 :     container_.push_back(std::forward<T>(value));
      45             :   }
      46             : 
      47             :  private:
      48             :   Container& container_;
      49             :   const typename Container::size_type begin_;
      50             : };
      51             : 
      52             : }  // namespace
      53             : 
      54         144 : MaybeHandle<Object> JsonParseInternalizer::Internalize(Isolate* isolate,
      55             :                                                        Handle<Object> object,
      56             :                                                        Handle<Object> reviver) {
      57             :   DCHECK(reviver->IsCallable());
      58             :   JsonParseInternalizer internalizer(isolate,
      59         144 :                                      Handle<JSReceiver>::cast(reviver));
      60             :   Handle<JSObject> holder =
      61         144 :       isolate->factory()->NewJSObject(isolate->object_function());
      62             :   Handle<String> name = isolate->factory()->empty_string();
      63         144 :   JSObject::AddProperty(isolate, holder, name, object, NONE);
      64         144 :   return internalizer.InternalizeJsonProperty(holder, name);
      65             : }
      66             : 
      67       63417 : MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
      68             :     Handle<JSReceiver> holder, Handle<String> name) {
      69       63417 :   HandleScope outer_scope(isolate_);
      70             :   Handle<Object> value;
      71      126834 :   ASSIGN_RETURN_ON_EXCEPTION(
      72             :       isolate_, value, Object::GetPropertyOrElement(isolate_, holder, name),
      73             :       Object);
      74      126834 :   if (value->IsJSReceiver()) {
      75       42113 :     Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
      76             :     Maybe<bool> is_array = Object::IsArray(object);
      77       42113 :     if (is_array.IsNothing()) return MaybeHandle<Object>();
      78       42113 :     if (is_array.FromJust()) {
      79             :       Handle<Object> length_object;
      80       42050 :       ASSIGN_RETURN_ON_EXCEPTION(
      81             :           isolate_, length_object,
      82             :           Object::GetLengthFromArrayLike(isolate_, object), Object);
      83       21025 :       double length = length_object->Number();
      84       42140 :       for (double i = 0; i < length; i++) {
      85       42077 :         HandleScope inner_scope(isolate_);
      86       42077 :         Handle<Object> index = isolate_->factory()->NewNumber(i);
      87       42077 :         Handle<String> name = isolate_->factory()->NumberToString(index);
      88       42077 :         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
      89             :       }
      90             :     } else {
      91             :       Handle<FixedArray> contents;
      92       42176 :       ASSIGN_RETURN_ON_EXCEPTION(
      93             :           isolate_, contents,
      94             :           KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
      95             :                                   ENUMERABLE_STRINGS,
      96             :                                   GetKeysConversion::kConvertToString),
      97             :           Object);
      98       21574 :       for (int i = 0; i < contents->length(); i++) {
      99       21205 :         HandleScope inner_scope(isolate_);
     100       21205 :         Handle<String> name(String::cast(contents->get(i)), isolate_);
     101       21205 :         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
     102             :       }
     103             :     }
     104             :   }
     105       21493 :   Handle<Object> argv[] = {name, value};
     106             :   Handle<Object> result;
     107       42986 :   ASSIGN_RETURN_ON_EXCEPTION(
     108             :       isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
     109             :       Object);
     110       21484 :   return outer_scope.CloseAndEscape(result);
     111             : }
     112             : 
     113       63282 : bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
     114             :                                             Handle<String> name) {
     115      126564 :   STACK_CHECK(isolate_, false);
     116             : 
     117             :   Handle<Object> result;
     118      126546 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     119             :       isolate_, result, InternalizeJsonProperty(holder, name), false);
     120             :   Maybe<bool> change_result = Nothing<bool>();
     121       64074 :   if (result->IsUndefined(isolate_)) {
     122             :     change_result = JSReceiver::DeletePropertyOrElement(holder, name,
     123         108 :                                                         LanguageMode::kSloppy);
     124             :   } else {
     125             :     PropertyDescriptor desc;
     126             :     desc.set_value(result);
     127             :     desc.set_configurable(true);
     128             :     desc.set_enumerable(true);
     129             :     desc.set_writable(true);
     130             :     change_result = JSReceiver::DefineOwnProperty(isolate_, holder, name, &desc,
     131       21250 :                                                   Just(kDontThrow));
     132             :   }
     133       21358 :   MAYBE_RETURN(change_result, false);
     134       21358 :   return true;
     135             : }
     136             : 
     137             : template <bool seq_one_byte>
     138      558458 : JsonParser<seq_one_byte>::JsonParser(Isolate* isolate, Handle<String> source)
     139             :     : source_(source),
     140             :       source_length_(source->length()),
     141             :       isolate_(isolate),
     142             :       zone_(isolate_->allocator(), ZONE_NAME),
     143     1675375 :       object_constructor_(isolate_->native_context()->object_function(),
     144             :                           isolate_),
     145             :       position_(-1),
     146     2792291 :       properties_(&zone_) {
     147      558459 :   source_ = String::Flatten(isolate, source_);
     148      558458 :   pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
     149             : 
     150             :   // Optimized fast case where we only have Latin1 characters.
     151             :   if (seq_one_byte) {
     152      558409 :     seq_source_ = Handle<SeqOneByteString>::cast(source_);
     153             :   }
     154      558457 : }
     155             : 
     156             : template <bool seq_one_byte>
     157      558458 : MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
     158             :   // Advance to the first character (possibly EOS)
     159             :   AdvanceSkipWhitespace();
     160      558458 :   Handle<Object> result = ParseJsonValue();
     161      558460 :   if (result.is_null() || c0_ != kEndOfString) {
     162             :     // Some exception (for example stack overflow) is already pending.
     163        5659 :     if (isolate_->has_pending_exception()) return Handle<Object>::null();
     164             : 
     165             :     // Parse failed. Current character is the unexpected token.
     166             :     Factory* factory = this->factory();
     167             :     MessageTemplate message;
     168        5624 :     Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
     169             :     Handle<Object> arg2;
     170             : 
     171        5624 :     switch (c0_) {
     172             :       case kEndOfString:
     173             :         message = MessageTemplate::kJsonParseUnexpectedEOS;
     174             :         break;
     175             :       case '-':
     176             :       case '0':
     177             :       case '1':
     178             :       case '2':
     179             :       case '3':
     180             :       case '4':
     181             :       case '5':
     182             :       case '6':
     183             :       case '7':
     184             :       case '8':
     185             :       case '9':
     186             :         message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
     187          90 :         break;
     188             :       case '"':
     189             :         message = MessageTemplate::kJsonParseUnexpectedTokenString;
     190         117 :         break;
     191             :       default:
     192             :         message = MessageTemplate::kJsonParseUnexpectedToken;
     193        5300 :         arg2 = arg1;
     194        5300 :         arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
     195        5300 :         break;
     196             :     }
     197             : 
     198        5624 :     Handle<Script> script(factory->NewScript(source_));
     199        5624 :     if (isolate()->NeedsSourcePositionsForProfiling()) {
     200        5020 :       Script::InitLineEnds(script);
     201             :     }
     202             :     // We should sent compile error event because we compile JSON object in
     203             :     // separated source file.
     204        5624 :     isolate()->debug()->OnCompileError(script);
     205        5624 :     MessageLocation location(script, position_, position_ + 1);
     206        5624 :     Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
     207        5624 :     return isolate()->template Throw<Object>(error, &location);
     208             :   }
     209      552801 :   return result;
     210             : }
     211             : 
     212             : MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
     213             :                                             Handle<String> key);
     214             : 
     215             : template <bool seq_one_byte>
     216           0 : void JsonParser<seq_one_byte>::Advance() {
     217  1077427163 :   position_++;
     218  1077427163 :   if (position_ >= source_length_) {
     219      552891 :     c0_ = kEndOfString;
     220             :   } else if (seq_one_byte) {
     221  1071125585 :     c0_ = seq_source_->SeqOneByteStringGet(position_);
     222             :   } else {
     223    11497374 :     c0_ = source_->Get(position_);
     224             :   }
     225           0 : }
     226             : 
     227             : template <bool seq_one_byte>
     228           0 : void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() {
     229   143761523 :   do {
     230             :     Advance();
     231             :   } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
     232           0 : }
     233             : 
     234             : template <bool seq_one_byte>
     235           0 : void JsonParser<seq_one_byte>::SkipWhitespace() {
     236     5552611 :   while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
     237             :     Advance();
     238             :   }
     239           0 : }
     240             : 
     241             : template <bool seq_one_byte>
     242           0 : uc32 JsonParser<seq_one_byte>::AdvanceGetChar() {
     243             :   Advance();
     244    33099122 :   return c0_;
     245             : }
     246             : 
     247             : template <bool seq_one_byte>
     248           0 : bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) {
     249    39538284 :   if (c0_ == c) {
     250             :     AdvanceSkipWhitespace();
     251             :     return true;
     252             :   }
     253             :   return false;
     254             : }
     255             : 
     256             : template <bool seq_one_byte>
     257    21832427 : bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) {
     258             :   int length = expected->length();
     259    21832427 :   if (source_->length() - position_ - 1 > length) {
     260             :     DisallowHeapAllocation no_gc;
     261    21832395 :     String::FlatContent content = expected->GetFlatContent(no_gc);
     262    21832395 :     if (content.IsOneByte()) {
     263             :       DCHECK_EQ('"', c0_);
     264    21832395 :       const uint8_t* input_chars = seq_source_->GetChars(no_gc) + position_ + 1;
     265    21832395 :       const uint8_t* expected_chars = content.ToOneByteVector().start();
     266   211045534 :       for (int i = 0; i < length; i++) {
     267   189223420 :         uint8_t c0 = input_chars[i];
     268   189223420 :         if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
     269    21832371 :           return false;
     270             :         }
     271             :       }
     272    21822114 :       if (input_chars[length] == '"') {
     273    21822090 :         position_ = position_ + length + 1;
     274             :         AdvanceSkipWhitespace();
     275             :         return true;
     276             :       }
     277             :     }
     278             :   }
     279             :   return false;
     280             : }
     281             : 
     282             : // Parse any JSON value.
     283             : template <bool seq_one_byte>
     284    40130182 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
     285    40130182 :   StackLimitCheck stack_check(isolate_);
     286    40130180 :   if (stack_check.HasOverflowed()) {
     287          35 :     isolate_->StackOverflow();
     288             :     return Handle<Object>::null();
     289             :   }
     290             : 
     291   120390481 :   if (stack_check.InterruptRequested() &&
     292    40130342 :       isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
     293             :     return Handle<Object>::null();
     294             :   }
     295             : 
     296    40130168 :   if (c0_ == '"') return ParseJsonString();
     297    23494705 :   if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
     298    18574509 :   if (c0_ == '{') return ParseJsonObject();
     299    10751959 :   if (c0_ == '[') return ParseJsonArray();
     300    10260182 :   if (c0_ == 'f') {
     301     9335329 :     if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
     302             :         AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
     303             :       AdvanceSkipWhitespace();
     304     2333830 :       return factory()->false_value();
     305             :     }
     306             :     return ReportUnexpectedCharacter();
     307             :   }
     308     7926343 :   if (c0_ == 't') {
     309    23755518 :     if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
     310             :         AdvanceGetChar() == 'e') {
     311             :       AdvanceSkipWhitespace();
     312     7918506 :       return factory()->true_value();
     313             :     }
     314             :     return ReportUnexpectedCharacter();
     315             :   }
     316        7837 :   if (c0_ == 'n') {
     317        8275 :     if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
     318             :         AdvanceGetChar() == 'l') {
     319             :       AdvanceSkipWhitespace();
     320        2758 :       return factory()->null_value();
     321             :     }
     322             :     return ReportUnexpectedCharacter();
     323             :   }
     324             :   return ReportUnexpectedCharacter();
     325             : }
     326             : 
     327             : template <bool seq_one_byte>
     328      152207 : ParseElementResult JsonParser<seq_one_byte>::ParseElement(
     329             :     Handle<JSObject> json_object) {
     330             :   uint32_t index = 0;
     331             :   // Maybe an array index, try to parse it.
     332      152207 :   if (c0_ == '0') {
     333             :     // With a leading zero, the string has to be "0" only to be an index.
     334             :     Advance();
     335             :   } else {
     336      350437 :     do {
     337      350446 :       int d = c0_ - '0';
     338      350446 :       if (index > 429496729U - ((d + 3) >> 3)) break;
     339      350437 :       index = (index * 10) + d;
     340             :       Advance();
     341      350437 :     } while (IsDecimalDigit(c0_));
     342             :   }
     343             : 
     344      152207 :   if (c0_ == '"') {
     345             :     // Successfully parsed index, parse and store element.
     346             :     AdvanceSkipWhitespace();
     347             : 
     348      152162 :     if (c0_ == ':') {
     349             :       AdvanceSkipWhitespace();
     350      152162 :       Handle<Object> value = ParseJsonValue();
     351      152162 :       if (!value.is_null()) {
     352             :         JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
     353      152153 :             .Assert();
     354      152153 :         return kElementFound;
     355             :       } else {
     356             :         return kNullHandle;
     357             :       }
     358             :     }
     359             :   }
     360             :   return kElementNotFound;
     361             : }
     362             : 
     363             : // Parse a JSON object. Position must be right at '{'.
     364             : template <bool seq_one_byte>
     365     7822550 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
     366             :   HandleScope scope(isolate());
     367             :   Handle<JSObject> json_object =
     368    15645100 :       factory()->NewJSObject(object_constructor(), pretenure_);
     369             :   Handle<Map> map(json_object->map(), isolate());
     370             :   int descriptor = 0;
     371     7822550 :   VectorSegment<ZoneVector<Handle<Object>>> properties(&properties_);
     372             :   DCHECK_EQ(c0_, '{');
     373             : 
     374             :   bool transitioning = true;
     375             : 
     376             :   AdvanceSkipWhitespace();
     377     7822550 :   if (c0_ != '}') {
     378    66979031 :     do {
     379    33547645 :       if (c0_ != '"') return ReportUnexpectedCharacter();
     380             : 
     381    33547359 :       int start_position = position_;
     382             :       Advance();
     383             : 
     384    67094718 :       if (IsDecimalDigit(c0_)) {
     385      152207 :         ParseElementResult element_result = ParseElement(json_object);
     386      152207 :         if (element_result == kNullHandle) return Handle<Object>::null();
     387    33583994 :         if (element_result == kElementFound) continue;
     388             :       }
     389             :       // Not an index, fallback to the slow path.
     390             : 
     391    33395197 :       position_ = start_position;
     392             : #ifdef DEBUG
     393             :       c0_ = '"';
     394             : #endif
     395             : 
     396             :       Handle<String> key;
     397             :       Handle<Object> value;
     398             : 
     399             :       // Try to follow existing transitions as long as possible. Once we stop
     400             :       // transitioning, no transition can be found anymore.
     401             :       DCHECK(transitioning);
     402             :       // First check whether there is a single expected transition. If so, try
     403             :       // to parse it first.
     404             :       bool follow_expected = false;
     405             :       Handle<Map> target;
     406             :       if (seq_one_byte) {
     407             :         DisallowHeapAllocation no_gc;
     408             :         TransitionsAccessor transitions(isolate(), *map, &no_gc);
     409    33294915 :         key = transitions.ExpectedTransitionKey();
     410    33294915 :         follow_expected = !key.is_null() && ParseJsonString(key);
     411             :         // If the expected transition hits, follow it.
     412    33294915 :         if (follow_expected) {
     413    21822090 :           target = transitions.ExpectedTransitionTarget();
     414             :         }
     415             :       }
     416    33294915 :       if (!follow_expected) {
     417             :         // If the expected transition failed, parse an internalized string and
     418             :         // try to find a matching transition.
     419    11573107 :         key = ParseJsonString();
     420    11573107 :         if (key.is_null()) return ReportUnexpectedCharacter();
     421             : 
     422             :         // If a transition was found, follow it and continue.
     423             :         transitioning = TransitionsAccessor(isolate(), map)
     424    23146088 :                             .FindTransitionToField(key)
     425             :                             .ToHandle(&target);
     426             :       }
     427    33395134 :       if (c0_ != ':') return ReportUnexpectedCharacter();
     428             : 
     429             :       AdvanceSkipWhitespace();
     430    33395134 :       value = ParseJsonValue();
     431    33395134 :       if (value.is_null()) return ReportUnexpectedCharacter();
     432             : 
     433    33395082 :       if (transitioning) {
     434             :         PropertyDetails details =
     435    33282960 :             target->instance_descriptors()->GetDetails(descriptor);
     436             :         Representation expected_representation = details.representation();
     437             : 
     438    33282960 :         if (value->FitsRepresentation(expected_representation)) {
     439    99838929 :           if (expected_representation.IsHeapObject() &&
     440    95039963 :               !target->instance_descriptors()
     441    64159803 :                    ->GetFieldType(descriptor)
     442    64159803 :                    ->NowContains(value)) {
     443             :             Handle<FieldType> value_type(
     444       15859 :                 value->OptimalType(isolate(), expected_representation));
     445       15859 :             Map::GeneralizeField(isolate(), target, descriptor,
     446             :                                  details.constness(), expected_representation,
     447             :                                  value_type);
     448             :           }
     449             :           DCHECK(target->instance_descriptors()
     450             :                      ->GetFieldType(descriptor)
     451             :                      ->NowContains(value));
     452             :           properties.push_back(value);
     453      100235 :           map = target;
     454    33279643 :           descriptor++;
     455             :           continue;
     456             :         } else {
     457             :           transitioning = false;
     458             :         }
     459             :       }
     460             : 
     461             :       DCHECK(!transitioning);
     462             : 
     463             :       // Commit the intermediate state to the object and stop transitioning.
     464      115439 :       CommitStateToJsonObject(json_object, map, properties.GetVector());
     465             : 
     466      115439 :       JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
     467      230878 :           .Check();
     468             :     } while (transitioning && MatchSkipWhiteSpace(','));
     469             : 
     470             :     // If we transitioned until the very end, transition the map now.
     471     7708720 :     if (transitioning) {
     472     7593281 :       CommitStateToJsonObject(json_object, map, properties.GetVector());
     473             :     } else {
     474      424258 :       while (MatchSkipWhiteSpace(',')) {
     475             :         HandleScope local_scope(isolate());
     476      308819 :         if (c0_ != '"') return ReportUnexpectedCharacter();
     477             : 
     478      308819 :         int start_position = position_;
     479             :         Advance();
     480             : 
     481      617638 :         if (IsDecimalDigit(c0_)) {
     482           0 :           ParseElementResult element_result = ParseElement(json_object);
     483           0 :           if (element_result == kNullHandle) return Handle<Object>::null();
     484           0 :           if (element_result == kElementFound) continue;
     485             :         }
     486             :         // Not an index, fallback to the slow path.
     487             : 
     488      308819 :         position_ = start_position;
     489             : #ifdef DEBUG
     490             :         c0_ = '"';
     491             : #endif
     492             : 
     493             :         Handle<String> key;
     494             :         Handle<Object> value;
     495             : 
     496      308819 :         key = ParseJsonString();
     497      308819 :         if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
     498             : 
     499             :         AdvanceSkipWhitespace();
     500      308819 :         value = ParseJsonValue();
     501      308819 :         if (value.is_null()) return ReportUnexpectedCharacter();
     502             : 
     503             :         JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
     504      308819 :                                                           value)
     505      617638 :             .Check();
     506             :       }
     507             :     }
     508             : 
     509     7708720 :     if (c0_ != '}') {
     510             :       return ReportUnexpectedCharacter();
     511             :     }
     512             :   }
     513             :   AdvanceSkipWhitespace();
     514     7822336 :   return scope.CloseAndEscape(json_object);
     515             : }
     516             : 
     517             : template <bool seq_one_byte>
     518     7708720 : void JsonParser<seq_one_byte>::CommitStateToJsonObject(
     519             :     Handle<JSObject> json_object, Handle<Map> map,
     520             :     Vector<const Handle<Object>> properties) {
     521     7708720 :   JSObject::AllocateStorageForMap(json_object, map);
     522             :   DCHECK(!json_object->map()->is_dictionary_map());
     523             : 
     524             :   DisallowHeapAllocation no_gc;
     525     7708720 :   DescriptorArray descriptors = json_object->map()->instance_descriptors();
     526    81976452 :   for (int i = 0; i < properties.length(); i++) {
     527    66559012 :     Handle<Object> value = properties[i];
     528             :     // Initializing store.
     529    66559012 :     json_object->WriteToField(i, descriptors->GetDetails(i), *value);
     530             :   }
     531     7708720 : }
     532             : 
     533             : class ElementKindLattice {
     534             :  private:
     535             :   enum {
     536             :     SMI_ELEMENTS,
     537             :     NUMBER_ELEMENTS,
     538             :     OBJECT_ELEMENTS,
     539             :   };
     540             : 
     541             :  public:
     542      491777 :   ElementKindLattice() : value_(SMI_ELEMENTS) {}
     543             : 
     544     5682230 :   void Update(Handle<Object> o) {
     545    11364460 :     if (o->IsSmi()) {
     546     5682230 :       return;
     547     6667002 :     } else if (o->IsHeapNumber()) {
     548          42 :       if (value_ < NUMBER_ELEMENTS) value_ = NUMBER_ELEMENTS;
     549             :     } else {
     550             :       DCHECK(!o->IsNumber());
     551     3333459 :       value_ = OBJECT_ELEMENTS;
     552             :     }
     553             :   }
     554             : 
     555      458370 :   ElementsKind GetElementsKind() const {
     556      458370 :     switch (value_) {
     557             :       case SMI_ELEMENTS:
     558             :         return PACKED_SMI_ELEMENTS;
     559             :       case NUMBER_ELEMENTS:
     560          21 :         return PACKED_DOUBLE_ELEMENTS;
     561             :       case OBJECT_ELEMENTS:
     562      398551 :         return PACKED_ELEMENTS;
     563             :       default:
     564           0 :         UNREACHABLE();
     565             :         return PACKED_ELEMENTS;
     566             :     }
     567             :   }
     568             : 
     569             :  private:
     570             :   int value_;
     571             : };
     572             : 
     573             : // Parse a JSON array. Position must be right at '['.
     574             : template <bool seq_one_byte>
     575      491777 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
     576             :   HandleScope scope(isolate());
     577      491777 :   ZoneVector<Handle<Object>> elements(zone());
     578             :   DCHECK_EQ(c0_, '[');
     579             : 
     580             :   ElementKindLattice lattice;
     581             : 
     582             :   AdvanceSkipWhitespace();
     583      491777 :   if (c0_ != ']') {
     584     5682230 :     do {
     585     5715628 :       Handle<Object> element = ParseJsonValue();
     586     5715628 :       if (element.is_null()) return ReportUnexpectedCharacter();
     587     5682230 :       elements.push_back(element);
     588     5682230 :       lattice.Update(element);
     589             :     } while (MatchSkipWhiteSpace(','));
     590      399892 :     if (c0_ != ']') {
     591             :       return ReportUnexpectedCharacter();
     592             :     }
     593             :   }
     594             :   AdvanceSkipWhitespace();
     595             : 
     596             :   // Allocate a fixed array with all the elements.
     597             : 
     598             :   Handle<Object> json_array;
     599      458370 :   const ElementsKind kind = lattice.GetElementsKind();
     600      916740 :   int elements_size = static_cast<int>(elements.size());
     601             : 
     602      458370 :   switch (kind) {
     603             :     case PACKED_ELEMENTS:
     604             :     case PACKED_SMI_ELEMENTS: {
     605             :       Handle<FixedArray> elems =
     606      916698 :           factory()->NewFixedArray(elements_size, pretenure_);
     607     6107187 :       for (int i = 0; i < elements_size; i++) elems->set(i, *elements[i]);
     608      916698 :       json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
     609             :       break;
     610             :     }
     611             :     case PACKED_DOUBLE_ELEMENTS: {
     612             :       Handle<FixedDoubleArray> elems = Handle<FixedDoubleArray>::cast(
     613          42 :           factory()->NewFixedDoubleArray(elements_size, pretenure_));
     614          66 :       for (int i = 0; i < elements_size; i++) {
     615         135 :         elems->set(i, elements[i]->Number());
     616             :       }
     617          42 :       json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
     618             :       break;
     619             :     }
     620             :     default:
     621           0 :       UNREACHABLE();
     622             :   }
     623             : 
     624      458370 :   return scope.CloseAndEscape(json_array);
     625             : }
     626             : 
     627             : template <bool seq_one_byte>
     628     4920196 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
     629             :   bool negative = false;
     630     4920196 :   int beg_pos = position_;
     631     4920196 :   if (c0_ == '-') {
     632             :     Advance();
     633             :     negative = true;
     634             :   }
     635     4920196 :   if (c0_ == '0') {
     636             :     Advance();
     637             :     // Prefix zero is only allowed if it's the only digit before
     638             :     // a decimal point or exponent.
     639     2065346 :     if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     640             :   } else {
     641             :     uint32_t i = 0;
     642             :     int digits = 0;
     643     3887523 :     if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
     644     9314569 :     do {
     645             :       // This can overflow. That's OK, the "digits < 10" check below
     646             :       // will discard overflown results.
     647     9314569 :       i = i * 10 + c0_ - '0';
     648     9314569 :       digits++;
     649             :       Advance();
     650     9314569 :     } while (IsDecimalDigit(c0_));
     651     3887496 :     if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
     652             :       SkipWhitespace();
     653             :       return Handle<Smi>(Smi::FromInt((negative ? -static_cast<int>(i) : i)),
     654     7726640 :                          isolate());
     655             :     }
     656             :   }
     657     1056840 :   if (c0_ == '.') {
     658             :     Advance();
     659      228268 :     if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     660      146300 :     do {
     661             :       Advance();
     662      146300 :     } while (IsDecimalDigit(c0_));
     663             :   }
     664     2113626 :   if (AsciiAlphaToLower(c0_) == 'e') {
     665             :     Advance();
     666         109 :     if (c0_ == '-' || c0_ == '+') Advance();
     667         218 :     if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     668          74 :     do {
     669             :       Advance();
     670          74 :     } while (IsDecimalDigit(c0_));
     671             :   }
     672     1056768 :   int length = position_ - beg_pos;
     673             :   double number;
     674             :   if (seq_one_byte) {
     675             :     DisallowHeapAllocation no_gc;
     676     1997330 :     Vector<const uint8_t> chars(seq_source_->GetChars(no_gc) + beg_pos, length);
     677      998665 :     number = StringToDouble(chars,
     678             :                             NO_FLAGS,  // Hex, octal or trailing junk.
     679             :                             std::numeric_limits<double>::quiet_NaN());
     680             :   } else {
     681             :     Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
     682      116206 :     String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
     683             :     Vector<const uint8_t> result =
     684             :         Vector<const uint8_t>(buffer.start(), length);
     685       58103 :     number = StringToDouble(result,
     686             :                             NO_FLAGS,  // Hex, octal or trailing junk.
     687             :                             0.0);
     688             :     buffer.Dispose();
     689             :   }
     690             :   SkipWhitespace();
     691     2113536 :   return factory()->NewNumber(number, pretenure_);
     692             : }
     693             : 
     694             : template <typename StringType>
     695             : inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
     696             : 
     697             : template <>
     698      574284 : inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
     699      574284 :   seq_str->SeqTwoByteStringSet(i, c);
     700      574284 : }
     701             : 
     702             : template <>
     703             : inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
     704   762603564 :   seq_str->SeqOneByteStringSet(i, c);
     705             : }
     706             : 
     707             : template <typename StringType>
     708             : inline Handle<StringType> NewRawString(Factory* factory, int length,
     709             :                                        PretenureFlag pretenure);
     710             : 
     711             : template <>
     712       50183 : inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length,
     713             :                                              PretenureFlag pretenure) {
     714      100366 :   return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
     715             : }
     716             : 
     717             : template <>
     718     7138656 : inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length,
     719             :                                              PretenureFlag pretenure) {
     720    14277312 :   return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
     721             : }
     722             : 
     723             : // Scans the rest of a JSON string starting from position_ and writes
     724             : // prefix[start..end] along with the scanned characters into a
     725             : // sequential string of type StringType.
     726             : template <bool seq_one_byte>
     727             : template <typename StringType, typename SinkChar>
     728     7188839 : Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
     729             :     Handle<String> prefix, int start, int end) {
     730     7188839 :   int count = end - start;
     731     7188839 :   int max_length = count + source_length_ - position_;
     732     7188839 :   int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
     733             :   Handle<StringType> seq_string =
     734    14377678 :       NewRawString<StringType>(factory(), length, pretenure_);
     735             : 
     736             :   {
     737             :     DisallowHeapAllocation no_gc;
     738             :     // Copy prefix into seq_str.
     739             :     SinkChar* dest = seq_string->GetChars(no_gc);
     740     7188839 :     String::WriteToFlat(*prefix, dest, start, end);
     741             :   }
     742             : 
     743   799359671 :   while (c0_ != '"') {
     744             :     // Check for control character (0x00-0x1F) or unterminated string (<0).
     745   788450365 :     if (c0_ < 0x20) return Handle<String>::null();
     746   788450320 :     if (count >= length) {
     747             :       // We need to create a longer sequential string for the result.
     748     3468125 :       return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
     749             :     }
     750   784982195 :     if (c0_ != '\\') {
     751             :       // If the sink can contain UC16 characters, or source_ contains only
     752             :       // Latin1 characters, there's no need to test whether we can store the
     753             :       // character. Otherwise check whether the UC16 source character can fit
     754             :       // in the Latin1 sink.
     755        5414 :       if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
     756             :           c0_ <= String::kMaxOneByteCharCode) {
     757   744700774 :         SeqStringSet(seq_string, count++, c0_);
     758             :         Advance();
     759             :       } else {
     760             :         // StringType is SeqOneByteString and we just read a non-Latin1 char.
     761           9 :         return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
     762             :       }
     763             :     } else {
     764             :       Advance();  // Advance past the \.
     765    40281412 :       switch (c0_) {
     766             :         case '"':
     767             :         case '\\':
     768             :         case '/':
     769    18476861 :           SeqStringSet(seq_string, count++, c0_);
     770          18 :           break;
     771             :         case 'b':
     772          14 :           SeqStringSet(seq_string, count++, '\x08');
     773           0 :           break;
     774             :         case 'f':
     775           9 :           SeqStringSet(seq_string, count++, '\x0C');
     776           0 :           break;
     777             :         case 'n':
     778    21804109 :           SeqStringSet(seq_string, count++, '\x0A');
     779          10 :           break;
     780             :         case 'r':
     781          14 :           SeqStringSet(seq_string, count++, '\x0D');
     782           0 :           break;
     783             :         case 't':
     784           9 :           SeqStringSet(seq_string, count++, '\x09');
     785           0 :           break;
     786             :         case 'u': {
     787             :           uc32 value = 0;
     788        1395 :           for (int i = 0; i < 4; i++) {
     789             :             Advance();
     790        1404 :             int digit = HexValue(c0_);
     791        1404 :             if (digit < 0) {
     792             :               return Handle<String>::null();
     793             :             }
     794        1395 :             value = value * 16 + digit;
     795             :           }
     796         153 :           if (sizeof(SinkChar) == kUC16Size ||
     797             :               value <= String::kMaxOneByteCharCode) {
     798         203 :             SeqStringSet(seq_string, count++, value);
     799         189 :             break;
     800             :           } else {
     801             :             // StringType is SeqOneByteString and we just read a non-Latin1
     802             :             // char.
     803         139 :             position_ -= 6;  // Rewind position_ to \ in \uxxxx.
     804             :             Advance();
     805         139 :             return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0,
     806         139 :                                                               count);
     807             :           }
     808             :         }
     809             :         default:
     810             :           return Handle<String>::null();
     811             :       }
     812             :       Advance();
     813             :     }
     814             :   }
     815             : 
     816             :   DCHECK_EQ('"', c0_);
     817             :   // Advance past the last '"'.
     818             :   AdvanceSkipWhitespace();
     819             : 
     820             :   // Shrink seq_string length to count and return.
     821     3720467 :   return SeqString::Truncate(seq_string, count);
     822             : }
     823             : 
     824             : template <bool seq_one_byte>
     825    28517389 : Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
     826             :   DCHECK_EQ('"', c0_);
     827             :   Advance();
     828    28517389 :   if (c0_ == '"') {
     829             :     AdvanceSkipWhitespace();
     830             :     return factory()->empty_string();
     831             :   }
     832             : 
     833             :   if (seq_one_byte) {
     834             :     // Fast path for existing internalized strings.  If the the string being
     835             :     // parsed is not a known internalized string, contains backslashes or
     836             :     // unexpectedly reaches the end of string, return with an empty handle.
     837             : 
     838             :     // We intentionally use local variables instead of fields, compute hash
     839             :     // while we are iterating a string and manually inline StringTable lookup
     840             :     // here.
     841             : 
     842    28114988 :     int position = position_;
     843             :     uc32 c0 = c0_;
     844    28114988 :     uint32_t running_hash = static_cast<uint32_t>(HashSeed(isolate()));
     845             :     uint32_t index = 0;
     846             :     bool is_array_index = true;
     847             : 
     848   273793177 :     do {
     849   277463704 :       if (c0 == '\\') {
     850     3670482 :         c0_ = c0;
     851     3670482 :         int beg_pos = position_;
     852     3670482 :         position_ = position;
     853             :         return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
     854     3670482 :                                                              position_);
     855             :       }
     856   273793222 :       if (c0 < 0x20) {
     857          18 :         c0_ = c0;
     858          18 :         position_ = position;
     859             :         return Handle<String>::null();
     860             :       }
     861   273793204 :       if (is_array_index) {
     862             :         // With leading zero, the string has to be "0" to be a valid index.
     863    28801023 :         if (!IsDecimalDigit(c0) || (position > position_ && index == 0)) {
     864             :           is_array_index = false;
     865             :         } else {
     866     1605352 :           int d = c0 - '0';
     867     1605352 :           is_array_index = index <= 429496729U - ((d + 3) >> 3);
     868     1605352 :           index = (index * 10) + d;
     869             :         }
     870             :       }
     871             :       running_hash = StringHasher::AddCharacterCore(running_hash,
     872   273793204 :                                                     static_cast<uint16_t>(c0));
     873   273793204 :       position++;
     874   273793204 :       if (position >= source_length_) {
     875          27 :         c0_ = kEndOfString;
     876          27 :         position_ = position;
     877             :         return Handle<String>::null();
     878             :       }
     879   273793177 :       c0 = seq_source_->SeqOneByteStringGet(position);
     880             :     } while (c0 != '"');
     881    24444461 :     int length = position - position_;
     882             :     uint32_t hash;
     883    24444461 :     if (is_array_index) {
     884      918517 :       hash =
     885      918517 :           StringHasher::MakeArrayIndexHash(index, length) >> String::kHashShift;
     886    23525944 :     } else if (length <= String::kMaxHashCalcLength) {
     887             :       hash = StringHasher::GetHashCore(running_hash);
     888             :     } else {
     889          25 :       hash = static_cast<uint32_t>(length);
     890             :     }
     891    24444461 :     StringTable string_table = isolate()->heap()->string_table();
     892    24444461 :     uint32_t capacity = string_table->Capacity();
     893             :     uint32_t entry = StringTable::FirstProbe(hash, capacity);
     894             :     uint32_t count = 1;
     895             :     Handle<String> result;
     896             :     while (true) {
     897    33819266 :       Object element = string_table->KeyAt(entry);
     898    33819266 :       if (element->IsUndefined(isolate())) {
     899             :         // Lookup failure.
     900      941422 :         result =
     901             :             factory()->InternalizeOneByteString(seq_source_, position_, length);
     902    24915172 :         break;
     903             :       }
     904    33348555 :       if (!element->IsTheHole(isolate())) {
     905             :         DisallowHeapAllocation no_gc;
     906             :         Vector<const uint8_t> string_vector(
     907    65844590 :             seq_source_->GetChars(no_gc) + position_, length);
     908    32922295 :         if (String::cast(element)->IsOneByteEqualTo(string_vector)) {
     909             :           result = Handle<String>(String::cast(element), isolate());
     910             :           DCHECK_EQ(result->Hash(),
     911             :                     (hash << String::kHashShift) >> String::kHashShift);
     912    23973750 :           break;
     913             :         }
     914             :       }
     915     9374805 :       entry = StringTable::NextProbe(entry, count++, capacity);
     916             :     }
     917    24444461 :     position_ = position;
     918             :     // Advance past the last '"'.
     919             :     AdvanceSkipWhitespace();
     920    33819266 :     return result;
     921             :   }
     922             : 
     923      183864 :   int beg_pos = position_;
     924             :   // Fast case for Latin1 only without escape characters.
     925     1262496 :   do {
     926             :     // Check for control character (0x00-0x1F) or unterminated string (<0).
     927     1312589 :     if (c0_ < 0x20) return Handle<String>::null();
     928     1312580 :     if (c0_ != '\\') {
     929     1312531 :       if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
     930             :         Advance();
     931             :       } else {
     932       50035 :         return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos,
     933       50035 :                                                           position_);
     934             :       }
     935             :     } else {
     936          49 :       return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
     937          49 :                                                            position_);
     938             :     }
     939             :   } while (c0_ != '"');
     940      133771 :   int length = position_ - beg_pos;
     941             :   Handle<String> result =
     942      401313 :       factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
     943             :   DisallowHeapAllocation no_gc;
     944             :   uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(no_gc);
     945      267542 :   String::WriteToFlat(*source_, dest, beg_pos, position_);
     946             : 
     947             :   DCHECK_EQ('"', c0_);
     948             :   // Advance past the last '"'.
     949             :   AdvanceSkipWhitespace();
     950      133771 :   return result;
     951             : }
     952             : 
     953             : // Explicit instantiation.
     954             : template class JsonParser<true>;
     955             : template class JsonParser<false>;
     956             : 
     957             : }  // namespace internal
     958      178779 : }  // namespace v8

Generated by: LCOV version 1.10