LCOV - code coverage report
Current view: top level - src - json-parser.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 315 328 96.0 %
Date: 2019-04-18 Functions: 30 42 71.4 %

          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             :       : container_(*container), begin_(container->size()) {}
      36     7798693 :   ~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    33217815 :     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             :                                      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       61227 : MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
      68             :     Handle<JSReceiver> holder, Handle<String> name) {
      69       61227 :   HandleScope outer_scope(isolate_);
      70             :   Handle<Object> value;
      71      122454 :   ASSIGN_RETURN_ON_EXCEPTION(
      72             :       isolate_, value, Object::GetPropertyOrElement(isolate_, holder, name),
      73             :       Object);
      74       61227 :   if (value->IsJSReceiver()) {
      75             :     Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
      76             :     Maybe<bool> is_array = Object::IsArray(object);
      77       40653 :     if (is_array.IsNothing()) return MaybeHandle<Object>();
      78       40653 :     if (is_array.FromJust()) {
      79             :       Handle<Object> length_object;
      80       40590 :       ASSIGN_RETURN_ON_EXCEPTION(
      81             :           isolate_, length_object,
      82             :           Object::GetLengthFromArrayLike(isolate_, object), Object);
      83             :       double length = length_object->Number();
      84       61065 :       for (double i = 0; i < length; i++) {
      85       40617 :         HandleScope inner_scope(isolate_);
      86       40617 :         Handle<Object> index = isolate_->factory()->NewNumber(i);
      87       40617 :         Handle<String> name = isolate_->factory()->NumberToString(index);
      88       40617 :         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
      89             :       }
      90             :     } else {
      91             :       Handle<FixedArray> contents;
      92       40716 :       ASSIGN_RETURN_ON_EXCEPTION(
      93             :           isolate_, contents,
      94             :           KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
      95             :                                   ENUMERABLE_STRINGS,
      96             :                                   GetKeysConversion::kConvertToString),
      97             :           Object);
      98       20844 :       for (int i = 0; i < contents->length(); i++) {
      99       20475 :         HandleScope inner_scope(isolate_);
     100       20475 :         Handle<String> name(String::cast(contents->get(i)), isolate_);
     101       20475 :         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
     102             :       }
     103             :     }
     104             :   }
     105       20763 :   Handle<Object> argv[] = {name, value};
     106             :   Handle<Object> result;
     107       41526 :   ASSIGN_RETURN_ON_EXCEPTION(
     108             :       isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
     109             :       Object);
     110       20754 :   return outer_scope.CloseAndEscape(result);
     111             : }
     112             : 
     113       61092 : bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
     114             :                                             Handle<String> name) {
     115      122184 :   STACK_CHECK(isolate_, false);
     116             : 
     117             :   Handle<Object> result;
     118      122166 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     119             :       isolate_, result, InternalizeJsonProperty(holder, name), false);
     120             :   Maybe<bool> change_result = Nothing<bool>();
     121       41256 :   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       20520 :                                                   Just(kDontThrow));
     132             :   }
     133       20628 :   MAYBE_RETURN(change_result, false);
     134       20628 :   return true;
     135             : }
     136             : 
     137             : template <bool seq_one_byte>
     138      537027 : 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     1611081 :       object_constructor_(isolate_->native_context()->object_function(),
     144             :                           isolate_),
     145             :       position_(-1),
     146     2685135 :       properties_(&zone_) {
     147      537027 :   source_ = String::Flatten(isolate, source_);
     148      537027 :   allocation_ = (source_length_ >= kPretenureTreshold) ? AllocationType::kOld
     149             :                                                        : AllocationType::kYoung;
     150             : 
     151             :   // Optimized fast case where we only have Latin1 characters.
     152             :   if (seq_one_byte) {
     153      536978 :     seq_source_ = Handle<SeqOneByteString>::cast(source_);
     154             :   }
     155      537027 : }
     156             : 
     157             : template <bool seq_one_byte>
     158      537027 : MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
     159             :   // Advance to the first character (possibly EOS)
     160             :   AdvanceSkipWhitespace();
     161      537027 :   Handle<Object> result = ParseJsonValue();
     162      537027 :   if (result.is_null() || c0_ != kEndOfString) {
     163             :     // Some exception (for example stack overflow) is already pending.
     164        1314 :     if (isolate_->has_pending_exception()) return Handle<Object>::null();
     165             : 
     166             :     // Parse failed. Current character is the unexpected token.
     167             :     Factory* factory = this->factory();
     168             :     MessageTemplate message;
     169         619 :     Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
     170             :     Handle<Object> arg2;
     171             : 
     172         619 :     switch (c0_) {
     173             :       case kEndOfString:
     174             :         message = MessageTemplate::kJsonParseUnexpectedEOS;
     175             :         break;
     176             :       case '-':
     177             :       case '0':
     178             :       case '1':
     179             :       case '2':
     180             :       case '3':
     181             :       case '4':
     182             :       case '5':
     183             :       case '6':
     184             :       case '7':
     185             :       case '8':
     186             :       case '9':
     187             :         message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
     188          90 :         break;
     189             :       case '"':
     190             :         message = MessageTemplate::kJsonParseUnexpectedTokenString;
     191         117 :         break;
     192             :       default:
     193             :         message = MessageTemplate::kJsonParseUnexpectedToken;
     194         295 :         arg2 = arg1;
     195         295 :         arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
     196         295 :         break;
     197             :     }
     198             : 
     199         619 :     Handle<Script> script(factory->NewScript(source_));
     200         619 :     if (isolate()->NeedsSourcePositionsForProfiling()) {
     201          15 :       Script::InitLineEnds(script);
     202             :     }
     203             :     // We should sent compile error event because we compile JSON object in
     204             :     // separated source file.
     205         619 :     isolate()->debug()->OnCompileError(script);
     206         619 :     MessageLocation location(script, position_, position_ + 1);
     207         619 :     Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
     208             :     return isolate()->template Throw<Object>(error, &location);
     209             :   }
     210      536370 :   return result;
     211             : }
     212             : 
     213             : MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
     214             :                                             Handle<String> key);
     215             : 
     216             : template <bool seq_one_byte>
     217           0 : void JsonParser<seq_one_byte>::Advance() {
     218  1091192370 :   position_++;
     219  1091192370 :   if (position_ >= source_length_) {
     220      536460 :     c0_ = kEndOfString;
     221             :   } else if (seq_one_byte) {
     222  1084871817 :     c0_ = seq_source_->SeqOneByteStringGet(position_);
     223             :   } else {
     224     5784093 :     c0_ = source_->Get(position_);
     225             :   }
     226           0 : }
     227             : 
     228             : template <bool seq_one_byte>
     229           0 : void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() {
     230   143576638 :   do {
     231             :     Advance();
     232   143576638 :   } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
     233           0 : }
     234             : 
     235             : template <bool seq_one_byte>
     236           0 : void JsonParser<seq_one_byte>::SkipWhitespace() {
     237     5566715 :   while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
     238             :     Advance();
     239             :   }
     240           0 : }
     241             : 
     242             : template <bool seq_one_byte>
     243           0 : uc32 JsonParser<seq_one_byte>::AdvanceGetChar() {
     244             :   Advance();
     245    33071989 :   return c0_;
     246             : }
     247             : 
     248             : template <bool seq_one_byte>
     249           0 : bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) {
     250    39521662 :   if (c0_ == c) {
     251             :     AdvanceSkipWhitespace();
     252             :     return true;
     253             :   }
     254             :   return false;
     255             : }
     256             : 
     257             : template <bool seq_one_byte>
     258    21780278 : bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) {
     259             :   int length = expected->length();
     260    21780278 :   if (source_->length() - position_ - 1 > length) {
     261             :     DisallowHeapAllocation no_gc;
     262    21780242 :     String::FlatContent content = expected->GetFlatContent(no_gc);
     263    21780242 :     if (content.IsOneByte()) {
     264             :       DCHECK_EQ('"', c0_);
     265    21780242 :       const uint8_t* input_chars = seq_source_->GetChars(no_gc) + position_ + 1;
     266             :       const uint8_t* expected_chars = content.ToOneByteVector().start();
     267   399494694 :       for (int i = 0; i < length; i++) {
     268   188867547 :         uint8_t c0 = input_chars[i];
     269   188867547 :         if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
     270    21780208 :           return false;
     271             :         }
     272             :       }
     273    21769921 :       if (input_chars[length] == '"') {
     274    21769887 :         position_ = position_ + length + 1;
     275             :         AdvanceSkipWhitespace();
     276             :         return true;
     277             :       }
     278             :     }
     279             :   }
     280             :   return false;
     281             : }
     282             : 
     283             : // Parse any JSON value.
     284             : template <bool seq_one_byte>
     285    40102405 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
     286    40102405 :   StackLimitCheck stack_check(isolate_);
     287    40102404 :   if (stack_check.HasOverflowed()) {
     288          38 :     isolate_->StackOverflow();
     289             :     return Handle<Object>::null();
     290             :   }
     291             : 
     292    40102443 :   if (stack_check.InterruptRequested() &&
     293         154 :       isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
     294             :     return Handle<Object>::null();
     295             :   }
     296             : 
     297    40102367 :   if (c0_ == '"') return ParseJsonString();
     298    23473547 :   if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
     299    18547364 :   if (c0_ == '{') return ParseJsonObject();
     300    10748671 :   if (c0_ == '[') return ParseJsonArray();
     301    10248715 :   if (c0_ == 'f') {
     302     9304341 :     if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
     303             :         AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
     304             :       AdvanceSkipWhitespace();
     305     2326083 :       return factory()->false_value();
     306             :     }
     307             :     return ReportUnexpectedCharacter();
     308             :   }
     309     7922623 :   if (c0_ == 't') {
     310    23759373 :     if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
     311             :         AdvanceGetChar() == 'e') {
     312             :       AdvanceSkipWhitespace();
     313     7919791 :       return factory()->true_value();
     314             :     }
     315             :     return ReportUnexpectedCharacter();
     316             :   }
     317        2832 :   if (c0_ == 'n') {
     318        8275 :     if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
     319             :         AdvanceGetChar() == 'l') {
     320             :       AdvanceSkipWhitespace();
     321        2758 :       return factory()->null_value();
     322             :     }
     323             :     return ReportUnexpectedCharacter();
     324             :   }
     325             :   return ReportUnexpectedCharacter();
     326             : }
     327             : 
     328             : template <bool seq_one_byte>
     329      153044 : ParseElementResult JsonParser<seq_one_byte>::ParseElement(
     330             :     Handle<JSObject> json_object) {
     331             :   uint32_t index = 0;
     332             :   // Maybe an array index, try to parse it.
     333      153044 :   if (c0_ == '0') {
     334             :     // With a leading zero, the string has to be "0" only to be an index.
     335             :     Advance();
     336             :   } else {
     337      350437 :     do {
     338      350446 :       int d = c0_ - '0';
     339      350446 :       if (index > 429496729U - ((d + 3) >> 3)) break;
     340      350437 :       index = (index * 10) + d;
     341             :       Advance();
     342      350437 :     } while (IsDecimalDigit(c0_));
     343             :   }
     344             : 
     345      153044 :   if (c0_ == '"') {
     346             :     // Successfully parsed index, parse and store element.
     347             :     AdvanceSkipWhitespace();
     348             : 
     349      152999 :     if (c0_ == ':') {
     350             :       AdvanceSkipWhitespace();
     351      152999 :       Handle<Object> value = ParseJsonValue();
     352      152999 :       if (!value.is_null()) {
     353             :         JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
     354      152990 :             .Assert();
     355      152990 :         return kElementFound;
     356             :       } else {
     357             :         return kNullHandle;
     358             :       }
     359             :     }
     360             :   }
     361             :   return kElementNotFound;
     362             : }
     363             : 
     364             : // Parse a JSON object. Position must be right at '{'.
     365             : template <bool seq_one_byte>
     366     7798693 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
     367             :   HandleScope scope(isolate());
     368             :   Handle<JSObject> json_object =
     369    15597386 :       factory()->NewJSObject(object_constructor(), allocation_);
     370             :   Handle<Map> map(json_object->map(), isolate());
     371             :   int descriptor = 0;
     372     7798693 :   VectorSegment<ZoneVector<Handle<Object>>> properties(&properties_);
     373             :   DCHECK_EQ(c0_, '{');
     374             : 
     375             :   bool transitioning = true;
     376             : 
     377             :   AdvanceSkipWhitespace();
     378     7798693 :   if (c0_ != '}') {
     379    66857006 :     do {
     380    33486579 :       if (c0_ != '"') return ReportUnexpectedCharacter();
     381             : 
     382    33486309 :       int start_position = position_;
     383             :       Advance();
     384             : 
     385    66972618 :       if (IsDecimalDigit(c0_)) {
     386      153044 :         ParseElementResult element_result = ParseElement(json_object);
     387      153044 :         if (element_result == kNullHandle) return Handle<Object>::null();
     388    33523840 :         if (element_result == kElementFound) continue;
     389             :       }
     390             :       // Not an index, fallback to the slow path.
     391             : 
     392    33333310 :       position_ = start_position;
     393             : #ifdef DEBUG
     394             :       c0_ = '"';
     395             : #endif
     396             : 
     397             :       Handle<String> key;
     398             :       Handle<Object> value;
     399             : 
     400             :       // Try to follow existing transitions as long as possible. Once we stop
     401             :       // transitioning, no transition can be found anymore.
     402             :       DCHECK(transitioning);
     403             :       // First check whether there is a single expected transition. If so, try
     404             :       // to parse it first.
     405             :       bool follow_expected = false;
     406             :       Handle<Map> target;
     407             :       if (seq_one_byte) {
     408             :         DisallowHeapAllocation no_gc;
     409             :         TransitionsAccessor transitions(isolate(), *map, &no_gc);
     410    33233028 :         key = transitions.ExpectedTransitionKey();
     411    33233028 :         follow_expected = !key.is_null() && ParseJsonString(key);
     412             :         // If the expected transition hits, follow it.
     413    33233028 :         if (follow_expected) {
     414    21769887 :           target = transitions.ExpectedTransitionTarget();
     415             :         }
     416             :       }
     417    33233028 :       if (!follow_expected) {
     418             :         // If the expected transition failed, parse an internalized string and
     419             :         // try to find a matching transition.
     420    11563423 :         key = ParseJsonString();
     421    11563423 :         if (key.is_null()) return ReportUnexpectedCharacter();
     422             : 
     423             :         // If a transition was found, follow it and continue.
     424             :         transitioning = TransitionsAccessor(isolate(), map)
     425    11563360 :                             .FindTransitionToField(key)
     426             :                             .ToHandle(&target);
     427             :       }
     428    33333247 :       if (c0_ != ':') return ReportUnexpectedCharacter();
     429             : 
     430             :       AdvanceSkipWhitespace();
     431    33333247 :       value = ParseJsonValue();
     432    33333247 :       if (value.is_null()) return ReportUnexpectedCharacter();
     433             : 
     434    33333211 :       if (transitioning) {
     435             :         PropertyDetails details =
     436    33220929 :             target->instance_descriptors()->GetDetails(descriptor);
     437             :         Representation expected_representation = details.representation();
     438             : 
     439    33220929 :         if (value->FitsRepresentation(expected_representation)) {
     440    93601300 :           if (expected_representation.IsHeapObject() &&
     441             :               !target->instance_descriptors()
     442    60383485 :                    ->GetFieldType(descriptor)
     443    60383485 :                    ->NowContains(value)) {
     444             :             Handle<FieldType> value_type(
     445       13936 :                 value->OptimalType(isolate(), expected_representation));
     446       13936 :             Map::GeneralizeField(isolate(), target, descriptor,
     447             :                                  details.constness(), expected_representation,
     448             :                                  value_type);
     449             :           }
     450             :           DCHECK(target->instance_descriptors()
     451             :                      ->GetFieldType(descriptor)
     452             :                      ->NowContains(value));
     453             :           properties.push_back(value);
     454             :           map = target;
     455    33217815 :           descriptor++;
     456             :           continue;
     457             :         } else {
     458             :           transitioning = false;
     459             :         }
     460             :       }
     461             : 
     462             :       DCHECK(!transitioning);
     463             : 
     464             :       // Commit the intermediate state to the object and stop transitioning.
     465      115396 :       CommitStateToJsonObject(json_object, map, properties.GetVector());
     466             : 
     467      115396 :       JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
     468      230792 :           .Check();
     469             :     } while (transitioning && MatchSkipWhiteSpace(','));
     470             : 
     471             :     // If we transitioned until the very end, transition the map now.
     472     7684646 :     if (transitioning) {
     473     7569250 :       CommitStateToJsonObject(json_object, map, properties.GetVector());
     474             :     } else {
     475      425473 :       while (MatchSkipWhiteSpace(',')) {
     476             :         HandleScope local_scope(isolate());
     477      310077 :         if (c0_ != '"') return ReportUnexpectedCharacter();
     478             : 
     479      310077 :         int start_position = position_;
     480             :         Advance();
     481             : 
     482      620154 :         if (IsDecimalDigit(c0_)) {
     483           0 :           ParseElementResult element_result = ParseElement(json_object);
     484           0 :           if (element_result == kNullHandle) return Handle<Object>::null();
     485           0 :           if (element_result == kElementFound) continue;
     486             :         }
     487             :         // Not an index, fallback to the slow path.
     488             : 
     489      310077 :         position_ = start_position;
     490             : #ifdef DEBUG
     491             :         c0_ = '"';
     492             : #endif
     493             : 
     494             :         Handle<String> key;
     495             :         Handle<Object> value;
     496             : 
     497      310077 :         key = ParseJsonString();
     498      310077 :         if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
     499             : 
     500             :         AdvanceSkipWhitespace();
     501      310077 :         value = ParseJsonValue();
     502      310077 :         if (value.is_null()) return ReportUnexpectedCharacter();
     503             : 
     504      310077 :         JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
     505             :                                                           value)
     506      620154 :             .Check();
     507             :       }
     508             :     }
     509             : 
     510     7684646 :     if (c0_ != '}') {
     511             :       return ReportUnexpectedCharacter();
     512             :     }
     513             :   }
     514             :   AdvanceSkipWhitespace();
     515     7798495 :   return scope.CloseAndEscape(json_object);
     516             : }
     517             : 
     518             : template <bool seq_one_byte>
     519     7684646 : void JsonParser<seq_one_byte>::CommitStateToJsonObject(
     520             :     Handle<JSObject> json_object, Handle<Map> map,
     521             :     Vector<const Handle<Object>> properties) {
     522     7684646 :   JSObject::AllocateStorageForMap(json_object, map);
     523             :   DCHECK(!json_object->map()->is_dictionary_map());
     524             : 
     525             :   DisallowHeapAllocation no_gc;
     526     7684646 :   DescriptorArray descriptors = json_object->map()->instance_descriptors();
     527    74120134 :   for (int i = 0; i < properties.length(); i++) {
     528    66435488 :     Handle<Object> value = properties[i];
     529             :     // Initializing store.
     530    66435488 :     json_object->WriteToField(i, descriptors->GetDetails(i), *value);
     531             :   }
     532     7684646 : }
     533             : 
     534             : class ElementKindLattice {
     535             :  private:
     536             :   enum {
     537             :     SMI_ELEMENTS,
     538             :     NUMBER_ELEMENTS,
     539             :     OBJECT_ELEMENTS,
     540             :   };
     541             : 
     542             :  public:
     543      499956 :   ElementKindLattice() : value_(SMI_ELEMENTS) {}
     544             : 
     545     5725384 :   void Update(Handle<Object> o) {
     546     5725384 :     if (o->IsSmi()) {
     547             :       return;
     548     3336306 :     } else if (o->IsHeapNumber()) {
     549          42 :       if (value_ < NUMBER_ELEMENTS) value_ = NUMBER_ELEMENTS;
     550             :     } else {
     551             :       DCHECK(!o->IsNumber());
     552     3336264 :       value_ = OBJECT_ELEMENTS;
     553             :     }
     554             :   }
     555             : 
     556      456275 :   ElementsKind GetElementsKind() const {
     557      456275 :     switch (value_) {
     558             :       case SMI_ELEMENTS:
     559             :         return PACKED_SMI_ELEMENTS;
     560             :       case NUMBER_ELEMENTS:
     561          21 :         return PACKED_DOUBLE_ELEMENTS;
     562             :       case OBJECT_ELEMENTS:
     563      395854 :         return PACKED_ELEMENTS;
     564             :       default:
     565           0 :         UNREACHABLE();
     566             :         return PACKED_ELEMENTS;
     567             :     }
     568             :   }
     569             : 
     570             :  private:
     571             :   int value_;
     572             : };
     573             : 
     574             : // Parse a JSON array. Position must be right at '['.
     575             : template <bool seq_one_byte>
     576      499956 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
     577             :   HandleScope scope(isolate());
     578             :   ZoneVector<Handle<Object>> elements(zone());
     579             :   DCHECK_EQ(c0_, '[');
     580             : 
     581             :   ElementKindLattice lattice;
     582             : 
     583             :   AdvanceSkipWhitespace();
     584      499956 :   if (c0_ != ']') {
     585     5725384 :     do {
     586     5769056 :       Handle<Object> element = ParseJsonValue();
     587     5769056 :       if (element.is_null()) return ReportUnexpectedCharacter();
     588     5725384 :       elements.push_back(element);
     589     5725384 :       lattice.Update(element);
     590             :     } while (MatchSkipWhiteSpace(','));
     591      397461 :     if (c0_ != ']') {
     592             :       return ReportUnexpectedCharacter();
     593             :     }
     594             :   }
     595             :   AdvanceSkipWhitespace();
     596             : 
     597             :   // Allocate a fixed array with all the elements.
     598             : 
     599             :   Handle<Object> json_array;
     600      456275 :   const ElementsKind kind = lattice.GetElementsKind();
     601      456275 :   int elements_size = static_cast<int>(elements.size());
     602             : 
     603      456275 :   switch (kind) {
     604             :     case PACKED_ELEMENTS:
     605             :     case PACKED_SMI_ELEMENTS: {
     606             :       Handle<FixedArray> elems =
     607      912508 :           factory()->NewFixedArray(elements_size, allocation_);
     608    11819684 :       for (int i = 0; i < elements_size; i++) elems->set(i, *elements[i]);
     609      912508 :       json_array = factory()->NewJSArrayWithElements(elems, kind, allocation_);
     610             :       break;
     611             :     }
     612             :     case PACKED_DOUBLE_ELEMENTS: {
     613          42 :       Handle<FixedDoubleArray> elems = Handle<FixedDoubleArray>::cast(
     614             :           factory()->NewFixedDoubleArray(elements_size, allocation_));
     615         111 :       for (int i = 0; i < elements_size; i++) {
     616          90 :         elems->set(i, elements[i]->Number());
     617             :       }
     618          42 :       json_array = factory()->NewJSArrayWithElements(elems, kind, allocation_);
     619             :       break;
     620             :     }
     621             :     default:
     622           0 :       UNREACHABLE();
     623             :   }
     624             : 
     625      456275 :   return scope.CloseAndEscape(json_array);
     626             : }
     627             : 
     628             : template <bool seq_one_byte>
     629     4926184 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
     630             :   bool negative = false;
     631     4926184 :   int beg_pos = position_;
     632     4926184 :   if (c0_ == '-') {
     633             :     Advance();
     634             :     negative = true;
     635             :   }
     636     4926184 :   if (c0_ == '0') {
     637             :     Advance();
     638             :     // Prefix zero is only allowed if it's the only digit before
     639             :     // a decimal point or exponent.
     640     2046600 :     if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     641             :   } else {
     642             :     uint32_t i = 0;
     643             :     int digits = 0;
     644     3902884 :     if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
     645     9350261 :     do {
     646             :       // This can overflow. That's OK, the "digits < 10" check below
     647             :       // will discard overflown results.
     648     9350261 :       i = i * 10 + c0_ - '0';
     649     9350261 :       digits++;
     650             :       Advance();
     651     9350261 :     } while (IsDecimalDigit(c0_));
     652     3902857 :     if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
     653             :       SkipWhitespace();
     654             :       return Handle<Smi>(Smi::FromInt((negative ? -static_cast<int>(i) : i)),
     655     7756772 :                          isolate());
     656             :     }
     657             :   }
     658     1047762 :   if (c0_ == '.') {
     659             :     Advance();
     660      228358 :     if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     661      146365 :     do {
     662             :       Advance();
     663      146365 :     } while (IsDecimalDigit(c0_));
     664             :   }
     665     2095470 :   if (AsciiAlphaToLower(c0_) == 'e') {
     666             :     Advance();
     667         109 :     if (c0_ == '-' || c0_ == '+') Advance();
     668         218 :     if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
     669          74 :     do {
     670             :       Advance();
     671          74 :     } while (IsDecimalDigit(c0_));
     672             :   }
     673     1047690 :   int length = position_ - beg_pos;
     674             :   double number;
     675             :   if (seq_one_byte) {
     676             :     DisallowHeapAllocation no_gc;
     677     1977854 :     Vector<const uint8_t> chars(seq_source_->GetChars(no_gc) + beg_pos, length);
     678      988927 :     number = StringToDouble(chars,
     679             :                             NO_FLAGS,  // Hex, octal or trailing junk.
     680             :                             std::numeric_limits<double>::quiet_NaN());
     681             :   } else {
     682             :     Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
     683      117526 :     String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
     684             :     Vector<const uint8_t> result =
     685             :         Vector<const uint8_t>(buffer.start(), length);
     686       58763 :     number = StringToDouble(result,
     687             :                             NO_FLAGS,  // Hex, octal or trailing junk.
     688             :                             0.0);
     689             :     buffer.Dispose();
     690             :   }
     691             :   SkipWhitespace();
     692     2095380 :   return factory()->NewNumber(number, allocation_);
     693             : }
     694             : 
     695             : template <typename StringType>
     696             : inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
     697             : 
     698             : template <>
     699             : inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
     700             :   seq_str->SeqTwoByteStringSet(i, c);
     701             : }
     702             : 
     703             : template <>
     704             : inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
     705             :   seq_str->SeqOneByteStringSet(i, c);
     706             : }
     707             : 
     708             : template <typename StringType>
     709             : inline Handle<StringType> NewRawString(Factory* factory, int length,
     710             :                                        AllocationType allocation);
     711             : 
     712             : template <>
     713       50730 : inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length,
     714             :                                              AllocationType allocation) {
     715      101460 :   return factory->NewRawTwoByteString(length, allocation).ToHandleChecked();
     716             : }
     717             : 
     718             : template <>
     719     7151664 : inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length,
     720             :                                              AllocationType allocation) {
     721    14303328 :   return factory->NewRawOneByteString(length, allocation).ToHandleChecked();
     722             : }
     723             : 
     724             : // Scans the rest of a JSON string starting from position_ and writes
     725             : // prefix[start..end] along with the scanned characters into a
     726             : // sequential string of type StringType.
     727             : template <bool seq_one_byte>
     728             : template <typename StringType, typename SinkChar>
     729     7202394 : Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
     730             :     Handle<String> prefix, int start, int end) {
     731     7202394 :   int count = end - start;
     732     7202394 :   int max_length = count + source_length_ - position_;
     733     7202394 :   int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
     734             :   Handle<StringType> seq_string =
     735    14404788 :       NewRawString<StringType>(factory(), length, allocation_);
     736             : 
     737             :   {
     738             :     DisallowHeapAllocation no_gc;
     739             :     // Copy prefix into seq_str.
     740             :     SinkChar* dest = seq_string->GetChars(no_gc);
     741     7202394 :     String::WriteToFlat(*prefix, dest, start, end);
     742             :   }
     743             : 
     744   794904705 :   while (c0_ != '"') {
     745             :     // Check for control character (0x00-0x1F) or unterminated string (<0).
     746   791177314 :     if (c0_ < 0x20) return Handle<String>::null();
     747   791177269 :     if (count >= length) {
     748             :       // We need to create a longer sequential string for the result.
     749     3474704 :       return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
     750             :     }
     751   787702565 :     if (c0_ != '\\') {
     752             :       // If the sink can contain UC16 characters, or source_ contains only
     753             :       // Latin1 characters, there's no need to test whether we can store the
     754             :       // character. Otherwise check whether the UC16 source character can fit
     755             :       // in the Latin1 sink.
     756        5409 :       if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
     757             :           c0_ <= String::kMaxOneByteCharCode) {
     758   745130479 :         SeqStringSet(seq_string, count++, c0_);
     759             :         Advance();
     760             :       } else {
     761             :         // StringType is SeqOneByteString and we just read a non-Latin1 char.
     762           9 :         return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
     763             :       }
     764             :     } else {
     765             :       Advance();  // Advance past the \.
     766    42572077 :       switch (c0_) {
     767             :         case '"':
     768             :         case '\\':
     769             :         case '/':
     770    18507219 :           SeqStringSet(seq_string, count++, c0_);
     771             :           break;
     772             :         case 'b':
     773          14 :           SeqStringSet(seq_string, count++, '\x08');
     774             :           break;
     775             :         case 'f':
     776           9 :           SeqStringSet(seq_string, count++, '\x0C');
     777             :           break;
     778             :         case 'n':
     779    21814357 :           SeqStringSet(seq_string, count++, '\x0A');
     780             :           break;
     781             :         case 'r':
     782          14 :           SeqStringSet(seq_string, count++, '\x0D');
     783             :           break;
     784             :         case 't':
     785           9 :           SeqStringSet(seq_string, count++, '\x09');
     786             :           break;
     787             :         case 'u': {
     788             :           uc32 value = 0;
     789    20253672 :           for (int i = 0; i < 4; i++) {
     790             :             Advance();
     791     9001640 :             int digit = HexValue(c0_);
     792     9001640 :             if (digit < 0) {
     793             :               return Handle<String>::null();
     794             :             }
     795     9001631 :             value = value * 16 + digit;
     796             :           }
     797         205 :           if (sizeof(SinkChar) == kUC16Size ||
     798             :               value <= String::kMaxOneByteCharCode) {
     799     2250210 :             SeqStringSet(seq_string, count++, value);
     800             :             break;
     801             :           } else {
     802             :             // StringType is SeqOneByteString and we just read a non-Latin1
     803             :             // char.
     804         191 :             position_ -= 6;  // Rewind position_ to \ in \uxxxx.
     805             :             Advance();
     806         191 :             return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0,
     807         191 :                                                               count);
     808             :           }
     809             :         }
     810             :         default:
     811             :           return Handle<String>::null();
     812             :       }
     813             :       Advance();
     814             :     }
     815             :   }
     816             : 
     817             :   DCHECK_EQ('"', c0_);
     818             :   // Advance past the last '"'.
     819             :   AdvanceSkipWhitespace();
     820             : 
     821             :   // Shrink seq_string length to count and return.
     822     3727391 :   return SeqString::Truncate(seq_string, count);
     823             : }
     824             : 
     825             : template <bool seq_one_byte>
     826    28502320 : Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
     827             :   DCHECK_EQ('"', c0_);
     828             :   Advance();
     829    28502320 :   if (c0_ == '"') {
     830             :     AdvanceSkipWhitespace();
     831             :     return factory()->empty_string();
     832             :   }
     833             : 
     834             :   if (seq_one_byte) {
     835             :     // Fast path for existing internalized strings.  If the the string being
     836             :     // parsed is not a known internalized string, contains backslashes or
     837             :     // unexpectedly reaches the end of string, return with an empty handle.
     838             : 
     839             :     // We intentionally use local variables instead of fields, compute hash
     840             :     // while we are iterating a string and manually inline StringTable lookup
     841             :     // here.
     842             : 
     843             :     int position = position_;
     844             :     uc32 c0 = c0_;
     845    28117311 :     uint32_t running_hash = static_cast<uint32_t>(HashSeed(isolate()));
     846             :     uint32_t index = 0;
     847             :     bool is_array_index = true;
     848             : 
     849   273632150 :     do {
     850   277309616 :       if (c0 == '\\') {
     851     3677421 :         c0_ = c0;
     852             :         int beg_pos = position_;
     853     3677421 :         position_ = position;
     854             :         return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
     855     3677421 :                                                              position_);
     856             :       }
     857   273632195 :       if (c0 < 0x20) {
     858          18 :         c0_ = c0;
     859          18 :         position_ = position;
     860             :         return Handle<String>::null();
     861             :       }
     862   273632177 :       if (is_array_index) {
     863             :         // With leading zero, the string has to be "0" to be a valid index.
     864    28792541 :         if (!IsDecimalDigit(c0) || (position > position_ && index == 0)) {
     865             :           is_array_index = false;
     866             :         } else {
     867     1592661 :           int d = c0 - '0';
     868     1592661 :           is_array_index = index <= 429496729U - ((d + 3) >> 3);
     869     1592661 :           index = (index * 10) + d;
     870             :         }
     871             :       }
     872             :       running_hash = StringHasher::AddCharacterCore(running_hash,
     873             :                                                     static_cast<uint16_t>(c0));
     874   273632177 :       position++;
     875   273632177 :       if (position >= source_length_) {
     876          27 :         c0_ = kEndOfString;
     877          27 :         position_ = position;
     878             :         return Handle<String>::null();
     879             :       }
     880   273632150 :       c0 = seq_source_->SeqOneByteStringGet(position);
     881             :     } while (c0 != '"');
     882    24439845 :     int length = position - position_;
     883             :     uint32_t hash;
     884    24439845 :     if (is_array_index) {
     885      916579 :       hash =
     886      916579 :           StringHasher::MakeArrayIndexHash(index, length) >> String::kHashShift;
     887    23523266 :     } else if (length <= String::kMaxHashCalcLength) {
     888             :       hash = StringHasher::GetHashCore(running_hash);
     889             :     } else {
     890          25 :       hash = static_cast<uint32_t>(length);
     891             :     }
     892             :     StringTable string_table = isolate()->heap()->string_table();
     893    24439845 :     uint32_t capacity = string_table->Capacity();
     894             :     uint32_t entry = StringTable::FirstProbe(hash, capacity);
     895             :     uint32_t count = 1;
     896             :     Handle<String> result;
     897    16047552 :     while (true) {
     898    40487397 :       Object element = string_table->KeyAt(entry);
     899    40487397 :       if (element->IsUndefined(isolate())) {
     900             :         // Lookup failure.
     901      480952 :         result =
     902             :             factory()->InternalizeOneByteString(seq_source_, position_, length);
     903      480952 :         break;
     904             :       }
     905    40006445 :       if (!element->IsTheHole(isolate())) {
     906             :         DisallowHeapAllocation no_gc;
     907             :         Vector<const uint8_t> string_vector(
     908    79220722 :             seq_source_->GetChars(no_gc) + position_, length);
     909    39610361 :         if (String::cast(element)->IsOneByteEqualTo(string_vector)) {
     910             :           result = Handle<String>(String::cast(element), isolate());
     911             :           DCHECK_EQ(result->Hash(),
     912             :                     (hash << String::kHashShift) >> String::kHashShift);
     913    23958893 :           break;
     914             :         }
     915             :       }
     916    16047552 :       entry = StringTable::NextProbe(entry, count++, capacity);
     917             :     }
     918    24439845 :     position_ = position;
     919             :     // Advance past the last '"'.
     920             :     AdvanceSkipWhitespace();
     921    24439845 :     return result;
     922             :   }
     923             : 
     924      184099 :   int beg_pos = position_;
     925             :   // Fast case for Latin1 only without escape characters.
     926     1267446 :   do {
     927             :     // Check for control character (0x00-0x1F) or unterminated string (<0).
     928     1317524 :     if (c0_ < 0x20) return Handle<String>::null();
     929     1317515 :     if (c0_ != '\\') {
     930     1317481 :       if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
     931             :         Advance();
     932             :       } else {
     933       50035 :         return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos,
     934       50035 :                                                           position_);
     935             :       }
     936             :     } else {
     937          34 :       return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
     938          34 :                                                            position_);
     939             :     }
     940     1267446 :   } while (c0_ != '"');
     941      134021 :   int length = position_ - beg_pos;
     942             :   Handle<String> result =
     943      402063 :       factory()->NewRawOneByteString(length, allocation_).ToHandleChecked();
     944             :   DisallowHeapAllocation no_gc;
     945             :   uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(no_gc);
     946      268042 :   String::WriteToFlat(*source_, dest, beg_pos, position_);
     947             : 
     948             :   DCHECK_EQ('"', c0_);
     949             :   // Advance past the last '"'.
     950             :   AdvanceSkipWhitespace();
     951      134021 :   return result;
     952             : }
     953             : 
     954             : // Explicit instantiation.
     955             : template class JsonParser<true>;
     956             : template class JsonParser<false>;
     957             : 
     958             : }  // namespace internal
     959      122036 : }  // namespace v8

Generated by: LCOV version 1.10