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

Generated by: LCOV version 1.10