• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/json-parser.h"
6 
7 #include "src/common/message-template.h"
8 #include "src/debug/debug.h"
9 #include "src/numbers/conversions.h"
10 #include "src/numbers/hash-seed-inl.h"
11 #include "src/objects/field-type.h"
12 #include "src/objects/hash-table-inl.h"
13 #include "src/objects/objects-inl.h"
14 #include "src/objects/property-descriptor.h"
15 #include "src/strings/char-predicates-inl.h"
16 #include "src/strings/string-hasher.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 namespace {
22 
GetOneCharJsonToken(uint8_t c)23 constexpr JsonToken GetOneCharJsonToken(uint8_t c) {
24   // clang-format off
25   return
26      c == '"' ? JsonToken::STRING :
27      IsDecimalDigit(c) ?  JsonToken::NUMBER :
28      c == '-' ? JsonToken::NUMBER :
29      c == '[' ? JsonToken::LBRACK :
30      c == '{' ? JsonToken::LBRACE :
31      c == ']' ? JsonToken::RBRACK :
32      c == '}' ? JsonToken::RBRACE :
33      c == 't' ? JsonToken::TRUE_LITERAL :
34      c == 'f' ? JsonToken::FALSE_LITERAL :
35      c == 'n' ? JsonToken::NULL_LITERAL :
36      c == ' ' ? JsonToken::WHITESPACE :
37      c == '\t' ? JsonToken::WHITESPACE :
38      c == '\r' ? JsonToken::WHITESPACE :
39      c == '\n' ? JsonToken::WHITESPACE :
40      c == ':' ? JsonToken::COLON :
41      c == ',' ? JsonToken::COMMA :
42      JsonToken::ILLEGAL;
43   // clang-format on
44 }
45 
46 // Table of one-character tokens, by character (0x00..0xFF only).
47 static const constexpr JsonToken one_char_json_tokens[256] = {
48 #define CALL_GET_SCAN_FLAGS(N) GetOneCharJsonToken(N),
49     INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
50 #undef CALL_GET_SCAN_FLAGS
51 #define CALL_GET_SCAN_FLAGS(N) GetOneCharJsonToken(128 + N),
52         INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
53 #undef CALL_GET_SCAN_FLAGS
54 };
55 
56 enum class EscapeKind : uint8_t {
57   kIllegal,
58   kSelf,
59   kBackspace,
60   kTab,
61   kNewLine,
62   kFormFeed,
63   kCarriageReturn,
64   kUnicode
65 };
66 
67 using EscapeKindField = base::BitField8<EscapeKind, 0, 3>;
68 using MayTerminateStringField = EscapeKindField::Next<bool, 1>;
69 using NumberPartField = MayTerminateStringField::Next<bool, 1>;
70 
MayTerminateJsonString(uint8_t flags)71 constexpr bool MayTerminateJsonString(uint8_t flags) {
72   return MayTerminateStringField::decode(flags);
73 }
74 
GetEscapeKind(uint8_t flags)75 constexpr EscapeKind GetEscapeKind(uint8_t flags) {
76   return EscapeKindField::decode(flags);
77 }
78 
IsNumberPart(uint8_t flags)79 constexpr bool IsNumberPart(uint8_t flags) {
80   return NumberPartField::decode(flags);
81 }
82 
GetJsonScanFlags(uint8_t c)83 constexpr uint8_t GetJsonScanFlags(uint8_t c) {
84   // clang-format off
85   return (c == 'b' ? EscapeKindField::encode(EscapeKind::kBackspace)
86           : c == 't' ? EscapeKindField::encode(EscapeKind::kTab)
87           : c == 'n' ? EscapeKindField::encode(EscapeKind::kNewLine)
88           : c == 'f' ? EscapeKindField::encode(EscapeKind::kFormFeed)
89           : c == 'r' ? EscapeKindField::encode(EscapeKind::kCarriageReturn)
90           : c == 'u' ? EscapeKindField::encode(EscapeKind::kUnicode)
91           : c == '"' ? EscapeKindField::encode(EscapeKind::kSelf)
92           : c == '\\' ? EscapeKindField::encode(EscapeKind::kSelf)
93           : c == '/' ? EscapeKindField::encode(EscapeKind::kSelf)
94           : EscapeKindField::encode(EscapeKind::kIllegal)) |
95          (c < 0x20 ? MayTerminateStringField::encode(true)
96           : c == '"' ? MayTerminateStringField::encode(true)
97           : c == '\\' ? MayTerminateStringField::encode(true)
98           : MayTerminateStringField::encode(false)) |
99          NumberPartField::encode(c == '.' ||
100                                  c == 'e' ||
101                                  c == 'E' ||
102                                  IsDecimalDigit(c) ||
103                                  c == '-' ||
104                                  c == '+');
105   // clang-format on
106 }
107 
108 // Table of one-character scan flags, by character (0x00..0xFF only).
109 static const constexpr uint8_t character_json_scan_flags[256] = {
110 #define CALL_GET_SCAN_FLAGS(N) GetJsonScanFlags(N),
111     INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
112 #undef CALL_GET_SCAN_FLAGS
113 #define CALL_GET_SCAN_FLAGS(N) GetJsonScanFlags(128 + N),
114         INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
115 #undef CALL_GET_SCAN_FLAGS
116 };
117 
118 }  // namespace
119 
Internalize(Isolate * isolate,Handle<Object> object,Handle<Object> reviver)120 MaybeHandle<Object> JsonParseInternalizer::Internalize(Isolate* isolate,
121                                                        Handle<Object> object,
122                                                        Handle<Object> reviver) {
123   DCHECK(reviver->IsCallable());
124   JsonParseInternalizer internalizer(isolate,
125                                      Handle<JSReceiver>::cast(reviver));
126   Handle<JSObject> holder =
127       isolate->factory()->NewJSObject(isolate->object_function());
128   Handle<String> name = isolate->factory()->empty_string();
129   JSObject::AddProperty(isolate, holder, name, object, NONE);
130   return internalizer.InternalizeJsonProperty(holder, name);
131 }
132 
InternalizeJsonProperty(Handle<JSReceiver> holder,Handle<String> name)133 MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
134     Handle<JSReceiver> holder, Handle<String> name) {
135   HandleScope outer_scope(isolate_);
136   Handle<Object> value;
137   ASSIGN_RETURN_ON_EXCEPTION(
138       isolate_, value, Object::GetPropertyOrElement(isolate_, holder, name),
139       Object);
140   if (value->IsJSReceiver()) {
141     Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
142     Maybe<bool> is_array = Object::IsArray(object);
143     if (is_array.IsNothing()) return MaybeHandle<Object>();
144     if (is_array.FromJust()) {
145       Handle<Object> length_object;
146       ASSIGN_RETURN_ON_EXCEPTION(
147           isolate_, length_object,
148           Object::GetLengthFromArrayLike(isolate_, object), Object);
149       double length = length_object->Number();
150       for (double i = 0; i < length; i++) {
151         HandleScope inner_scope(isolate_);
152         Handle<Object> index = isolate_->factory()->NewNumber(i);
153         Handle<String> name = isolate_->factory()->NumberToString(index);
154         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
155       }
156     } else {
157       Handle<FixedArray> contents;
158       ASSIGN_RETURN_ON_EXCEPTION(
159           isolate_, contents,
160           KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
161                                   ENUMERABLE_STRINGS,
162                                   GetKeysConversion::kConvertToString),
163           Object);
164       for (int i = 0; i < contents->length(); i++) {
165         HandleScope inner_scope(isolate_);
166         Handle<String> name(String::cast(contents->get(i)), isolate_);
167         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
168       }
169     }
170   }
171   Handle<Object> argv[] = {name, value};
172   Handle<Object> result;
173   ASSIGN_RETURN_ON_EXCEPTION(
174       isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
175       Object);
176   return outer_scope.CloseAndEscape(result);
177 }
178 
RecurseAndApply(Handle<JSReceiver> holder,Handle<String> name)179 bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
180                                             Handle<String> name) {
181   STACK_CHECK(isolate_, false);
182 
183   Handle<Object> result;
184   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
185       isolate_, result, InternalizeJsonProperty(holder, name), false);
186   Maybe<bool> change_result = Nothing<bool>();
187   if (result->IsUndefined(isolate_)) {
188     change_result = JSReceiver::DeletePropertyOrElement(holder, name,
189                                                         LanguageMode::kSloppy);
190   } else {
191     PropertyDescriptor desc;
192     desc.set_value(result);
193     desc.set_configurable(true);
194     desc.set_enumerable(true);
195     desc.set_writable(true);
196     change_result = JSReceiver::DefineOwnProperty(isolate_, holder, name, &desc,
197                                                   Just(kDontThrow));
198   }
199   MAYBE_RETURN(change_result, false);
200   return true;
201 }
202 
203 template <typename Char>
JsonParser(Isolate * isolate,Handle<String> source)204 JsonParser<Char>::JsonParser(Isolate* isolate, Handle<String> source)
205     : isolate_(isolate),
206       hash_seed_(HashSeed(isolate)),
207       object_constructor_(isolate_->object_function()),
208       original_source_(source) {
209   size_t start = 0;
210   size_t length = source->length();
211   if (source->IsSlicedString()) {
212     SlicedString string = SlicedString::cast(*source);
213     start = string.offset();
214     String parent = string.parent();
215     if (parent.IsThinString()) parent = ThinString::cast(parent).actual();
216     source_ = handle(parent, isolate);
217   } else {
218     source_ = String::Flatten(isolate, source);
219   }
220 
221   if (StringShape(*source_).IsExternal()) {
222     chars_ =
223         static_cast<const Char*>(SeqExternalString::cast(*source_).GetChars());
224     chars_may_relocate_ = false;
225   } else {
226     DisallowHeapAllocation no_gc;
227     isolate->heap()->AddGCEpilogueCallback(UpdatePointersCallback,
228                                            v8::kGCTypeAll, this);
229     chars_ = SeqString::cast(*source_).GetChars(no_gc);
230     chars_may_relocate_ = true;
231   }
232   cursor_ = chars_ + start;
233   end_ = cursor_ + length;
234 }
235 
236 template <typename Char>
ReportUnexpectedToken(JsonToken token)237 void JsonParser<Char>::ReportUnexpectedToken(JsonToken token) {
238   // Some exception (for example stack overflow) is already pending.
239   if (isolate_->has_pending_exception()) return;
240 
241   // Parse failed. Current character is the unexpected token.
242   Factory* factory = this->factory();
243   MessageTemplate message;
244   int offset = original_source_->IsSlicedString()
245                    ? SlicedString::cast(*original_source_).offset()
246                    : 0;
247   int pos = position() - offset;
248   Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(pos), isolate());
249   Handle<Object> arg2;
250 
251   switch (token) {
252     case JsonToken::EOS:
253       message = MessageTemplate::kJsonParseUnexpectedEOS;
254       break;
255     case JsonToken::NUMBER:
256       message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
257       break;
258     case JsonToken::STRING:
259       message = MessageTemplate::kJsonParseUnexpectedTokenString;
260       break;
261     default:
262       message = MessageTemplate::kJsonParseUnexpectedToken;
263       arg2 = arg1;
264       arg1 = factory->LookupSingleCharacterStringFromCode(*cursor_);
265       break;
266   }
267 
268   Handle<Script> script(factory->NewScript(original_source_));
269   if (isolate()->NeedsSourcePositionsForProfiling()) {
270     Script::InitLineEnds(isolate(), script);
271   }
272   // We should sent compile error event because we compile JSON object in
273   // separated source file.
274   isolate()->debug()->OnCompileError(script);
275   MessageLocation location(script, pos, pos + 1);
276   isolate()->ThrowAt(factory->NewSyntaxError(message, arg1, arg2), &location);
277 
278   // Move the cursor to the end so we won't be able to proceed parsing.
279   cursor_ = end_;
280 }
281 
282 template <typename Char>
ReportUnexpectedCharacter(uc32 c)283 void JsonParser<Char>::ReportUnexpectedCharacter(uc32 c) {
284   JsonToken token = JsonToken::ILLEGAL;
285   if (c == kEndOfString) {
286     token = JsonToken::EOS;
287   } else if (c <= unibrow::Latin1::kMaxChar) {
288     token = one_char_json_tokens[c];
289   }
290   return ReportUnexpectedToken(token);
291 }
292 
293 template <typename Char>
~JsonParser()294 JsonParser<Char>::~JsonParser() {
295   if (StringShape(*source_).IsExternal()) {
296     // Check that the string shape hasn't changed. Otherwise our GC hooks are
297     // broken.
298     SeqExternalString::cast(*source_);
299   } else {
300     // Check that the string shape hasn't changed. Otherwise our GC hooks are
301     // broken.
302     SeqString::cast(*source_);
303     isolate()->heap()->RemoveGCEpilogueCallback(UpdatePointersCallback, this);
304   }
305 }
306 
307 template <typename Char>
ParseJson()308 MaybeHandle<Object> JsonParser<Char>::ParseJson() {
309   MaybeHandle<Object> result = ParseJsonValue();
310   if (!Check(JsonToken::EOS)) ReportUnexpectedToken(peek());
311   if (isolate_->has_pending_exception()) return MaybeHandle<Object>();
312   return result;
313 }
314 
315 MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
316                                             Handle<String> key);
317 
318 template <typename Char>
SkipWhitespace()319 void JsonParser<Char>::SkipWhitespace() {
320   next_ = JsonToken::EOS;
321 
322   cursor_ = std::find_if(cursor_, end_, [this](Char c) {
323     JsonToken current = V8_LIKELY(c <= unibrow::Latin1::kMaxChar)
324                             ? one_char_json_tokens[c]
325                             : JsonToken::ILLEGAL;
326     bool result = current != JsonToken::WHITESPACE;
327     if (result) next_ = current;
328     return result;
329   });
330 }
331 
332 template <typename Char>
ScanUnicodeCharacter()333 uc32 JsonParser<Char>::ScanUnicodeCharacter() {
334   uc32 value = 0;
335   for (int i = 0; i < 4; i++) {
336     int digit = HexValue(NextCharacter());
337     if (V8_UNLIKELY(digit < 0)) return kInvalidUnicodeCharacter;
338     value = value * 16 + digit;
339   }
340   return value;
341 }
342 
343 // Parse any JSON value.
344 template <typename Char>
ScanJsonPropertyKey(JsonContinuation * cont)345 JsonString JsonParser<Char>::ScanJsonPropertyKey(JsonContinuation* cont) {
346   {
347     DisallowHeapAllocation no_gc;
348     const Char* start = cursor_;
349     uc32 first = CurrentCharacter();
350     if (first == '\\' && NextCharacter() == 'u') first = ScanUnicodeCharacter();
351     if (IsDecimalDigit(first)) {
352       if (first == '0') {
353         if (NextCharacter() == '"') {
354           advance();
355           // Record element information.
356           cont->elements++;
357           DCHECK_LE(0, cont->max_index);
358           return JsonString(0);
359         }
360       } else {
361         uint32_t index = first - '0';
362         while (true) {
363           cursor_ = std::find_if(cursor_ + 1, end_, [&index](Char c) {
364             return !TryAddArrayIndexChar(&index, c);
365           });
366 
367           if (CurrentCharacter() == '"') {
368             advance();
369             // Record element information.
370             cont->elements++;
371             cont->max_index = Max(cont->max_index, index);
372             return JsonString(index);
373           }
374 
375           if (CurrentCharacter() == '\\' && NextCharacter() == 'u') {
376             if (TryAddArrayIndexChar(&index, ScanUnicodeCharacter())) continue;
377           }
378 
379           break;
380         }
381       }
382     }
383     // Reset cursor_ to start if the key is not an index.
384     cursor_ = start;
385   }
386   return ScanJsonString(true);
387 }
388 
389 namespace {
ParentOfDescriptorOwner(Isolate * isolate,Handle<Map> maybe_root,Handle<Map> source,int descriptor)390 Handle<Map> ParentOfDescriptorOwner(Isolate* isolate, Handle<Map> maybe_root,
391                                     Handle<Map> source, int descriptor) {
392   if (descriptor == 0) {
393     DCHECK_EQ(0, maybe_root->NumberOfOwnDescriptors());
394     return maybe_root;
395   }
396   return handle(source->FindFieldOwner(isolate, InternalIndex(descriptor - 1)),
397                 isolate);
398 }
399 }  // namespace
400 
401 template <typename Char>
BuildJsonObject(const JsonContinuation & cont,const std::vector<JsonProperty> & property_stack,Handle<Map> feedback)402 Handle<Object> JsonParser<Char>::BuildJsonObject(
403     const JsonContinuation& cont,
404     const std::vector<JsonProperty>& property_stack, Handle<Map> feedback) {
405   size_t start = cont.index;
406   int length = static_cast<int>(property_stack.size() - start);
407   int named_length = length - cont.elements;
408 
409   Handle<Map> initial_map = factory()->ObjectLiteralMapFromCache(
410       isolate_->native_context(), named_length);
411 
412   Handle<Map> map = initial_map;
413 
414   Handle<FixedArrayBase> elements = factory()->empty_fixed_array();
415 
416   // First store the elements.
417   if (cont.elements > 0) {
418     // Store as dictionary elements if that would use less memory.
419     if (ShouldConvertToSlowElements(cont.elements, cont.max_index + 1)) {
420       Handle<NumberDictionary> elms =
421           NumberDictionary::New(isolate_, cont.elements);
422       for (int i = 0; i < length; i++) {
423         const JsonProperty& property = property_stack[start + i];
424         if (!property.string.is_index()) continue;
425         uint32_t index = property.string.index();
426         Handle<Object> value = property.value;
427         elms = NumberDictionary::Set(isolate_, elms, index, value);
428       }
429       map = Map::AsElementsKind(isolate_, map, DICTIONARY_ELEMENTS);
430       elements = elms;
431     } else {
432       Handle<FixedArray> elms =
433           factory()->NewFixedArrayWithHoles(cont.max_index + 1);
434       DisallowHeapAllocation no_gc;
435       WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
436       DCHECK_EQ(HOLEY_ELEMENTS, map->elements_kind());
437 
438       for (int i = 0; i < length; i++) {
439         const JsonProperty& property = property_stack[start + i];
440         if (!property.string.is_index()) continue;
441         uint32_t index = property.string.index();
442         Handle<Object> value = property.value;
443         elms->set(static_cast<int>(index), *value, mode);
444       }
445       elements = elms;
446     }
447   }
448 
449   int feedback_descriptors =
450       (feedback.is_null() ||
451        feedback->elements_kind() != map->elements_kind() ||
452        feedback->instance_size() != map->instance_size())
453           ? 0
454           : feedback->NumberOfOwnDescriptors();
455 
456   int i;
457   int descriptor = 0;
458   int new_mutable_double = 0;
459   for (i = 0; i < length; i++) {
460     const JsonProperty& property = property_stack[start + i];
461     if (property.string.is_index()) continue;
462     Handle<String> expected;
463     Handle<Map> target;
464     InternalIndex descriptor_index(descriptor);
465     if (descriptor < feedback_descriptors) {
466       expected =
467           handle(String::cast(feedback->instance_descriptors(kRelaxedLoad)
468                                   .GetKey(descriptor_index)),
469                  isolate_);
470     } else {
471       DisallowHeapAllocation no_gc;
472       TransitionsAccessor transitions(isolate(), *map, &no_gc);
473       expected = transitions.ExpectedTransitionKey();
474       if (!expected.is_null()) {
475         // Directly read out the target while reading out the key, otherwise it
476         // might die while building the string below.
477         target = TransitionsAccessor(isolate(), *map, &no_gc)
478                      .ExpectedTransitionTarget();
479       }
480     }
481 
482     Handle<String> key = MakeString(property.string, expected);
483     if (key.is_identical_to(expected)) {
484       if (descriptor < feedback_descriptors) target = feedback;
485     } else {
486       if (descriptor < feedback_descriptors) {
487         map = ParentOfDescriptorOwner(isolate_, map, feedback, descriptor);
488         feedback_descriptors = 0;
489       }
490       if (!TransitionsAccessor(isolate(), map)
491                .FindTransitionToField(key)
492                .ToHandle(&target)) {
493         break;
494       }
495     }
496 
497     Handle<Object> value = property.value;
498 
499     PropertyDetails details =
500         target->instance_descriptors(kRelaxedLoad).GetDetails(descriptor_index);
501     Representation expected_representation = details.representation();
502 
503     if (!value->FitsRepresentation(expected_representation)) {
504       Representation representation = value->OptimalRepresentation(isolate());
505       representation = representation.generalize(expected_representation);
506       if (!expected_representation.CanBeInPlaceChangedTo(representation)) {
507         map = ParentOfDescriptorOwner(isolate_, map, target, descriptor);
508         break;
509       }
510       Handle<FieldType> value_type =
511           value->OptimalType(isolate(), representation);
512       Map::GeneralizeField(isolate(), target, descriptor_index,
513                            details.constness(), representation, value_type);
514     } else if (expected_representation.IsHeapObject() &&
515                !target->instance_descriptors(kRelaxedLoad)
516                     .GetFieldType(descriptor_index)
517                     .NowContains(value)) {
518       Handle<FieldType> value_type =
519           value->OptimalType(isolate(), expected_representation);
520       Map::GeneralizeField(isolate(), target, descriptor_index,
521                            details.constness(), expected_representation,
522                            value_type);
523     } else if (!FLAG_unbox_double_fields &&
524                expected_representation.IsDouble() && value->IsSmi()) {
525       new_mutable_double++;
526     }
527 
528     DCHECK(target->instance_descriptors(kRelaxedLoad)
529                .GetFieldType(descriptor_index)
530                .NowContains(value));
531     map = target;
532     descriptor++;
533   }
534 
535   // Fast path: Write all transitioned named properties.
536   if (i == length && descriptor < feedback_descriptors) {
537     map = ParentOfDescriptorOwner(isolate_, map, map, descriptor);
538   }
539 
540   // Preallocate all mutable heap numbers so we don't need to allocate while
541   // setting up the object. Otherwise verification of that object may fail.
542   Handle<ByteArray> mutable_double_buffer;
543   // Allocate enough space so we can double-align the payload.
544   const int kMutableDoubleSize = sizeof(double) * 2;
545   STATIC_ASSERT(HeapNumber::kSize <= kMutableDoubleSize);
546   if (new_mutable_double > 0) {
547     mutable_double_buffer =
548         factory()->NewByteArray(kMutableDoubleSize * new_mutable_double);
549   }
550 
551   Handle<JSObject> object = initial_map->is_dictionary_map()
552                                 ? factory()->NewSlowJSObjectFromMap(map)
553                                 : factory()->NewJSObjectFromMap(map);
554   object->set_elements(*elements);
555 
556   {
557     descriptor = 0;
558     DisallowHeapAllocation no_gc;
559     WriteBarrierMode mode = object->GetWriteBarrierMode(no_gc);
560     Address mutable_double_address =
561         mutable_double_buffer.is_null()
562             ? 0
563             : reinterpret_cast<Address>(
564                   mutable_double_buffer->GetDataStartAddress());
565     Address filler_address = mutable_double_address;
566     if (kTaggedSize != kDoubleSize) {
567       if (IsAligned(mutable_double_address, kDoubleAlignment)) {
568         mutable_double_address += kTaggedSize;
569       } else {
570         filler_address += HeapNumber::kSize;
571       }
572     }
573     for (int j = 0; j < i; j++) {
574       const JsonProperty& property = property_stack[start + j];
575       if (property.string.is_index()) continue;
576       InternalIndex descriptor_index(descriptor);
577       PropertyDetails details =
578           map->instance_descriptors(kRelaxedLoad).GetDetails(descriptor_index);
579       Object value = *property.value;
580       FieldIndex index = FieldIndex::ForDescriptor(*map, descriptor_index);
581       descriptor++;
582 
583       if (details.representation().IsDouble()) {
584         if (object->IsUnboxedDoubleField(index)) {
585           uint64_t bits;
586           if (value.IsSmi()) {
587             bits = bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(value)));
588           } else {
589             DCHECK(value.IsHeapNumber());
590             bits = HeapNumber::cast(value).value_as_bits();
591           }
592           object->RawFastDoublePropertyAsBitsAtPut(index, bits);
593           continue;
594         }
595 
596         if (value.IsSmi()) {
597           if (kTaggedSize != kDoubleSize) {
598             // Write alignment filler.
599             HeapObject filler = HeapObject::FromAddress(filler_address);
600             filler.set_map_after_allocation(
601                 *factory()->one_pointer_filler_map());
602             filler_address += kMutableDoubleSize;
603           }
604 
605           uint64_t bits =
606               bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(value)));
607           // Allocate simple heapnumber with immortal map, with non-pointer
608           // payload, so we can skip notifying object layout change.
609 
610           HeapObject hn = HeapObject::FromAddress(mutable_double_address);
611           hn.set_map_after_allocation(*factory()->heap_number_map());
612           HeapNumber::cast(hn).set_value_as_bits(bits);
613           value = hn;
614           mutable_double_address += kMutableDoubleSize;
615         } else {
616           DCHECK(value.IsHeapNumber());
617           HeapObject::cast(value).synchronized_set_map(
618               *factory()->heap_number_map());
619         }
620       }
621       object->RawFastInobjectPropertyAtPut(index, value, mode);
622     }
623     // Make all mutable HeapNumbers alive.
624     if (!mutable_double_buffer.is_null()) {
625 #ifdef DEBUG
626       Address end =
627           reinterpret_cast<Address>(mutable_double_buffer->GetDataEndAddress());
628       if (kTaggedSize != kDoubleSize) {
629         DCHECK_EQ(Min(filler_address, mutable_double_address), end);
630         DCHECK_GE(filler_address, end);
631         DCHECK_GE(mutable_double_address, end);
632       } else {
633         DCHECK_EQ(mutable_double_address, end);
634       }
635 #endif
636       mutable_double_buffer->set_length(0);
637     }
638   }
639 
640   // Slow path: define remaining named properties.
641   for (; i < length; i++) {
642     HandleScope scope(isolate_);
643     const JsonProperty& property = property_stack[start + i];
644     if (property.string.is_index()) continue;
645     Handle<String> key = MakeString(property.string);
646 #ifdef DEBUG
647     uint32_t index;
648     DCHECK(!key->AsArrayIndex(&index));
649 #endif
650     Handle<Object> value = property.value;
651     LookupIterator it(isolate_, object, key, object, LookupIterator::OWN);
652     JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE).Check();
653   }
654 
655   return object;
656 }
657 
658 template <typename Char>
BuildJsonArray(const JsonContinuation & cont,const std::vector<Handle<Object>> & element_stack)659 Handle<Object> JsonParser<Char>::BuildJsonArray(
660     const JsonContinuation& cont,
661     const std::vector<Handle<Object>>& element_stack) {
662   size_t start = cont.index;
663   int length = static_cast<int>(element_stack.size() - start);
664 
665   ElementsKind kind = PACKED_SMI_ELEMENTS;
666   for (size_t i = start; i < element_stack.size(); i++) {
667     Object value = *element_stack[i];
668     if (value.IsHeapObject()) {
669       if (HeapObject::cast(value).IsHeapNumber()) {
670         kind = PACKED_DOUBLE_ELEMENTS;
671       } else {
672         kind = PACKED_ELEMENTS;
673         break;
674       }
675     }
676   }
677 
678   Handle<JSArray> array = factory()->NewJSArray(kind, length, length);
679   if (kind == PACKED_DOUBLE_ELEMENTS) {
680     DisallowHeapAllocation no_gc;
681     FixedDoubleArray elements = FixedDoubleArray::cast(array->elements());
682     for (int i = 0; i < length; i++) {
683       elements.set(i, element_stack[start + i]->Number());
684     }
685   } else {
686     DisallowHeapAllocation no_gc;
687     FixedArray elements = FixedArray::cast(array->elements());
688     WriteBarrierMode mode = kind == PACKED_SMI_ELEMENTS
689                                 ? SKIP_WRITE_BARRIER
690                                 : elements.GetWriteBarrierMode(no_gc);
691     for (int i = 0; i < length; i++) {
692       elements.set(i, *element_stack[start + i], mode);
693     }
694   }
695   return array;
696 }
697 
698 // Parse any JSON value.
699 template <typename Char>
ParseJsonValue()700 MaybeHandle<Object> JsonParser<Char>::ParseJsonValue() {
701   std::vector<JsonContinuation> cont_stack;
702   std::vector<JsonProperty> property_stack;
703   std::vector<Handle<Object>> element_stack;
704 
705   cont_stack.reserve(16);
706   property_stack.reserve(16);
707   element_stack.reserve(16);
708 
709   JsonContinuation cont(isolate_, JsonContinuation::kReturn, 0);
710 
711   Handle<Object> value;
712   while (true) {
713     // Produce a json value.
714     //
715     // Iterate until a value is produced. Starting but not immediately finishing
716     // objects and arrays will cause the loop to continue until a first member
717     // is completed.
718     while (true) {
719       SkipWhitespace();
720       // The switch is immediately followed by 'break' so we can use 'break' to
721       // break out of the loop, and 'continue' to continue the loop.
722       switch (peek()) {
723         case JsonToken::STRING:
724           Consume(JsonToken::STRING);
725           value = MakeString(ScanJsonString(false));
726           break;
727 
728         case JsonToken::NUMBER:
729           value = ParseJsonNumber();
730           break;
731 
732         case JsonToken::LBRACE: {
733           Consume(JsonToken::LBRACE);
734           if (Check(JsonToken::RBRACE)) {
735             // TODO(verwaest): Directly use the map instead.
736             value = factory()->NewJSObject(object_constructor_);
737             break;
738           }
739 
740           // Start parsing an object with properties.
741           cont_stack.emplace_back(std::move(cont));
742           cont = JsonContinuation(isolate_, JsonContinuation::kObjectProperty,
743                                   property_stack.size());
744 
745           // Parse the property key.
746           ExpectNext(JsonToken::STRING);
747           property_stack.emplace_back(ScanJsonPropertyKey(&cont));
748 
749           ExpectNext(JsonToken::COLON);
750 
751           // Continue to start producing the first property value.
752           continue;
753         }
754 
755         case JsonToken::LBRACK:
756           Consume(JsonToken::LBRACK);
757           if (Check(JsonToken::RBRACK)) {
758             value = factory()->NewJSArray(0, PACKED_SMI_ELEMENTS);
759             break;
760           }
761 
762           // Start parsing an array with elements.
763           cont_stack.emplace_back(std::move(cont));
764           cont = JsonContinuation(isolate_, JsonContinuation::kArrayElement,
765                                   element_stack.size());
766 
767           // Continue to start producing the first array element.
768           continue;
769 
770         case JsonToken::TRUE_LITERAL:
771           ScanLiteral("true");
772           value = factory()->true_value();
773           break;
774 
775         case JsonToken::FALSE_LITERAL:
776           ScanLiteral("false");
777           value = factory()->false_value();
778           break;
779 
780         case JsonToken::NULL_LITERAL:
781           ScanLiteral("null");
782           value = factory()->null_value();
783           break;
784 
785         case JsonToken::COLON:
786         case JsonToken::COMMA:
787         case JsonToken::ILLEGAL:
788         case JsonToken::RBRACE:
789         case JsonToken::RBRACK:
790         case JsonToken::EOS:
791           ReportUnexpectedCharacter(CurrentCharacter());
792           // Pop the continuation stack to correctly tear down handle scopes.
793           while (!cont_stack.empty()) {
794             cont = std::move(cont_stack.back());
795             cont_stack.pop_back();
796           }
797           return MaybeHandle<Object>();
798 
799         case JsonToken::WHITESPACE:
800           UNREACHABLE();
801       }
802 
803       // Done producing a value, consume it.
804       break;
805     }
806 
807     // Consume a produced json value.
808     //
809     // Iterate as long as values are produced (arrays or object literals are
810     // finished).
811     while (true) {
812       // The switch is immediately followed by 'break' so we can use 'break' to
813       // break out of the loop, and 'continue' to continue the loop.
814       switch (cont.type()) {
815         case JsonContinuation::kReturn:
816           return cont.scope.CloseAndEscape(value);
817 
818         case JsonContinuation::kObjectProperty: {
819           // Store the previous property value into its property info.
820           property_stack.back().value = value;
821 
822           if (V8_LIKELY(Check(JsonToken::COMMA))) {
823             // Parse the property key.
824             ExpectNext(JsonToken::STRING);
825 
826             property_stack.emplace_back(ScanJsonPropertyKey(&cont));
827             ExpectNext(JsonToken::COLON);
828 
829             // Break to start producing the subsequent property value.
830             break;
831           }
832 
833           Handle<Map> feedback;
834           if (cont_stack.size() > 0 &&
835               cont_stack.back().type() == JsonContinuation::kArrayElement &&
836               cont_stack.back().index < element_stack.size() &&
837               element_stack.back()->IsJSObject()) {
838             Map maybe_feedback = JSObject::cast(*element_stack.back()).map();
839             // Don't consume feedback from objects with a map that's detached
840             // from the transition tree.
841             if (!maybe_feedback.IsDetached(isolate_)) {
842               feedback = handle(maybe_feedback, isolate_);
843               if (feedback->is_deprecated()) {
844                 feedback = Map::Update(isolate_, feedback);
845               }
846             }
847           }
848           value = BuildJsonObject(cont, property_stack, feedback);
849           property_stack.resize(cont.index);
850           Expect(JsonToken::RBRACE);
851 
852           // Return the object.
853           value = cont.scope.CloseAndEscape(value);
854           // Pop the continuation.
855           cont = std::move(cont_stack.back());
856           cont_stack.pop_back();
857           // Consume to produced object.
858           continue;
859         }
860 
861         case JsonContinuation::kArrayElement: {
862           // Store the previous element on the stack.
863           element_stack.emplace_back(value);
864           // Break to start producing the subsequent element value.
865           if (V8_LIKELY(Check(JsonToken::COMMA))) break;
866 
867           value = BuildJsonArray(cont, element_stack);
868           element_stack.resize(cont.index);
869           Expect(JsonToken::RBRACK);
870 
871           // Return the array.
872           value = cont.scope.CloseAndEscape(value);
873           // Pop the continuation.
874           cont = std::move(cont_stack.back());
875           cont_stack.pop_back();
876           // Consume the produced array.
877           continue;
878         }
879       }
880 
881       // Done consuming a value. Produce next value.
882       break;
883     }
884   }
885 }
886 
887 template <typename Char>
AdvanceToNonDecimal()888 void JsonParser<Char>::AdvanceToNonDecimal() {
889   cursor_ =
890       std::find_if(cursor_, end_, [](Char c) { return !IsDecimalDigit(c); });
891 }
892 
893 template <typename Char>
ParseJsonNumber()894 Handle<Object> JsonParser<Char>::ParseJsonNumber() {
895   double number;
896   int sign = 1;
897 
898   {
899     const Char* start = cursor_;
900     DisallowHeapAllocation no_gc;
901 
902     uc32 c = *cursor_;
903     if (c == '-') {
904       sign = -1;
905       c = NextCharacter();
906     }
907 
908     if (c == '0') {
909       // Prefix zero is only allowed if it's the only digit before
910       // a decimal point or exponent.
911       c = NextCharacter();
912       if (base::IsInRange(c, 0,
913                           static_cast<int32_t>(unibrow::Latin1::kMaxChar)) &&
914           IsNumberPart(character_json_scan_flags[c])) {
915         if (V8_UNLIKELY(IsDecimalDigit(c))) {
916           AllowHeapAllocation allow_before_exception;
917           ReportUnexpectedToken(JsonToken::NUMBER);
918           return handle(Smi::FromInt(0), isolate_);
919         }
920       } else if (sign > 0) {
921         return handle(Smi::FromInt(0), isolate_);
922       }
923     } else {
924       const Char* smi_start = cursor_;
925       AdvanceToNonDecimal();
926       if (V8_UNLIKELY(smi_start == cursor_)) {
927         AllowHeapAllocation allow_before_exception;
928         ReportUnexpectedCharacter(CurrentCharacter());
929         return handle(Smi::FromInt(0), isolate_);
930       }
931       uc32 c = CurrentCharacter();
932       STATIC_ASSERT(Smi::IsValid(-999999999));
933       STATIC_ASSERT(Smi::IsValid(999999999));
934       const int kMaxSmiLength = 9;
935       if ((cursor_ - smi_start) <= kMaxSmiLength &&
936           (!base::IsInRange(c, 0,
937                             static_cast<int32_t>(unibrow::Latin1::kMaxChar)) ||
938            !IsNumberPart(character_json_scan_flags[c]))) {
939         // Smi.
940         int32_t i = 0;
941         for (; smi_start != cursor_; smi_start++) {
942           DCHECK(IsDecimalDigit(*smi_start));
943           i = (i * 10) + ((*smi_start) - '0');
944         }
945         // TODO(verwaest): Cache?
946         return handle(Smi::FromInt(i * sign), isolate_);
947       }
948     }
949 
950     if (CurrentCharacter() == '.') {
951       uc32 c = NextCharacter();
952       if (!IsDecimalDigit(c)) {
953         AllowHeapAllocation allow_before_exception;
954         ReportUnexpectedCharacter(c);
955         return handle(Smi::FromInt(0), isolate_);
956       }
957       AdvanceToNonDecimal();
958     }
959 
960     if (AsciiAlphaToLower(CurrentCharacter()) == 'e') {
961       uc32 c = NextCharacter();
962       if (c == '-' || c == '+') c = NextCharacter();
963       if (!IsDecimalDigit(c)) {
964         AllowHeapAllocation allow_before_exception;
965         ReportUnexpectedCharacter(c);
966         return handle(Smi::FromInt(0), isolate_);
967       }
968       AdvanceToNonDecimal();
969     }
970 
971     Vector<const Char> chars(start, cursor_ - start);
972     number = StringToDouble(chars,
973                             NO_FLAGS,  // Hex, octal or trailing junk.
974                             std::numeric_limits<double>::quiet_NaN());
975 
976     DCHECK(!std::isnan(number));
977   }
978 
979   return factory()->NewNumber(number);
980 }
981 
982 namespace {
983 
984 template <typename Char>
Matches(const Vector<const Char> & chars,Handle<String> string)985 bool Matches(const Vector<const Char>& chars, Handle<String> string) {
986   DCHECK(!string.is_null());
987 
988   if (chars.length() != string->length()) return false;
989 
990   DisallowHeapAllocation no_gc;
991   if (string->IsOneByteRepresentation()) {
992     const uint8_t* string_data = string->GetChars<uint8_t>(no_gc);
993     return CompareChars(chars.begin(), string_data, chars.length()) == 0;
994   }
995   const uint16_t* string_data = string->GetChars<uint16_t>(no_gc);
996   return CompareChars(chars.begin(), string_data, chars.length()) == 0;
997 }
998 
999 }  // namespace
1000 
1001 template <typename Char>
1002 template <typename SinkSeqString>
DecodeString(const JsonString & string,Handle<SinkSeqString> intermediate,Handle<String> hint)1003 Handle<String> JsonParser<Char>::DecodeString(
1004     const JsonString& string, Handle<SinkSeqString> intermediate,
1005     Handle<String> hint) {
1006   using SinkChar = typename SinkSeqString::Char;
1007   {
1008     DisallowHeapAllocation no_gc;
1009     SinkChar* dest = intermediate->GetChars(no_gc);
1010     if (!string.has_escape()) {
1011       DCHECK(!string.internalize());
1012       CopyChars(dest, chars_ + string.start(), string.length());
1013       return intermediate;
1014     }
1015     DecodeString(dest, string.start(), string.length());
1016 
1017     if (!string.internalize()) return intermediate;
1018 
1019     Vector<const SinkChar> data(dest, string.length());
1020     if (!hint.is_null() && Matches(data, hint)) return hint;
1021   }
1022 
1023   return factory()->InternalizeString(intermediate, 0, string.length());
1024 }
1025 
1026 template <typename Char>
MakeString(const JsonString & string,Handle<String> hint)1027 Handle<String> JsonParser<Char>::MakeString(const JsonString& string,
1028                                             Handle<String> hint) {
1029   if (string.length() == 0) return factory()->empty_string();
1030 
1031   if (string.internalize() && !string.has_escape()) {
1032     if (!hint.is_null()) {
1033       Vector<const Char> data(chars_ + string.start(), string.length());
1034       if (Matches(data, hint)) return hint;
1035     }
1036     if (chars_may_relocate_) {
1037       return factory()->InternalizeString(Handle<SeqString>::cast(source_),
1038                                           string.start(), string.length(),
1039                                           string.needs_conversion());
1040     }
1041     Vector<const Char> chars(chars_ + string.start(), string.length());
1042     return factory()->InternalizeString(chars, string.needs_conversion());
1043   }
1044 
1045   if (sizeof(Char) == 1 ? V8_LIKELY(!string.needs_conversion())
1046                         : string.needs_conversion()) {
1047     Handle<SeqOneByteString> intermediate =
1048         factory()->NewRawOneByteString(string.length()).ToHandleChecked();
1049     return DecodeString(string, intermediate, hint);
1050   }
1051 
1052   Handle<SeqTwoByteString> intermediate =
1053       factory()->NewRawTwoByteString(string.length()).ToHandleChecked();
1054   return DecodeString(string, intermediate, hint);
1055 }
1056 
1057 template <typename Char>
1058 template <typename SinkChar>
DecodeString(SinkChar * sink,int start,int length)1059 void JsonParser<Char>::DecodeString(SinkChar* sink, int start, int length) {
1060   SinkChar* sink_start = sink;
1061   const Char* cursor = chars_ + start;
1062   while (true) {
1063     const Char* end = cursor + length - (sink - sink_start);
1064     cursor = std::find_if(cursor, end, [&sink](Char c) {
1065       if (c == '\\') return true;
1066       *sink++ = c;
1067       return false;
1068     });
1069 
1070     if (cursor == end) return;
1071 
1072     cursor++;
1073 
1074     switch (GetEscapeKind(character_json_scan_flags[*cursor])) {
1075       case EscapeKind::kSelf:
1076         *sink++ = *cursor;
1077         break;
1078 
1079       case EscapeKind::kBackspace:
1080         *sink++ = '\x08';
1081         break;
1082 
1083       case EscapeKind::kTab:
1084         *sink++ = '\x09';
1085         break;
1086 
1087       case EscapeKind::kNewLine:
1088         *sink++ = '\x0A';
1089         break;
1090 
1091       case EscapeKind::kFormFeed:
1092         *sink++ = '\x0C';
1093         break;
1094 
1095       case EscapeKind::kCarriageReturn:
1096         *sink++ = '\x0D';
1097         break;
1098 
1099       case EscapeKind::kUnicode: {
1100         uc32 value = 0;
1101         for (int i = 0; i < 4; i++) {
1102           value = value * 16 + HexValue(*++cursor);
1103         }
1104         if (value <=
1105             static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
1106           *sink++ = value;
1107         } else {
1108           *sink++ = unibrow::Utf16::LeadSurrogate(value);
1109           *sink++ = unibrow::Utf16::TrailSurrogate(value);
1110         }
1111         break;
1112       }
1113 
1114       case EscapeKind::kIllegal:
1115         UNREACHABLE();
1116     }
1117     cursor++;
1118   }
1119 }
1120 
1121 template <typename Char>
ScanJsonString(bool needs_internalization)1122 JsonString JsonParser<Char>::ScanJsonString(bool needs_internalization) {
1123   DisallowHeapAllocation no_gc;
1124   int start = position();
1125   int offset = start;
1126   bool has_escape = false;
1127   uc32 bits = 0;
1128 
1129   while (true) {
1130     cursor_ = std::find_if(cursor_, end_, [&bits](Char c) {
1131       if (sizeof(Char) == 2 && V8_UNLIKELY(c > unibrow::Latin1::kMaxChar)) {
1132         bits |= c;
1133         return false;
1134       }
1135       return MayTerminateJsonString(character_json_scan_flags[c]);
1136     });
1137 
1138     if (V8_UNLIKELY(is_at_end())) {
1139       AllowHeapAllocation allow_before_exception;
1140       ReportUnexpectedCharacter(kEndOfString);
1141       break;
1142     }
1143 
1144     if (*cursor_ == '"') {
1145       int end = position();
1146       advance();
1147       int length = end - offset;
1148       bool convert = sizeof(Char) == 1 ? bits > unibrow::Latin1::kMaxChar
1149                                        : bits <= unibrow::Latin1::kMaxChar;
1150       return JsonString(start, length, convert, needs_internalization,
1151                         has_escape);
1152     }
1153 
1154     if (*cursor_ == '\\') {
1155       has_escape = true;
1156       uc32 c = NextCharacter();
1157       if (V8_UNLIKELY(!base::IsInRange(
1158               c, 0, static_cast<int32_t>(unibrow::Latin1::kMaxChar)))) {
1159         AllowHeapAllocation allow_before_exception;
1160         ReportUnexpectedCharacter(c);
1161         break;
1162       }
1163 
1164       switch (GetEscapeKind(character_json_scan_flags[c])) {
1165         case EscapeKind::kSelf:
1166         case EscapeKind::kBackspace:
1167         case EscapeKind::kTab:
1168         case EscapeKind::kNewLine:
1169         case EscapeKind::kFormFeed:
1170         case EscapeKind::kCarriageReturn:
1171           offset += 1;
1172           break;
1173 
1174         case EscapeKind::kUnicode: {
1175           uc32 value = ScanUnicodeCharacter();
1176           if (value == kInvalidUnicodeCharacter) {
1177             AllowHeapAllocation allow_before_exception;
1178             ReportUnexpectedCharacter(CurrentCharacter());
1179             return JsonString();
1180           }
1181           bits |= value;
1182           // \uXXXX results in either 1 or 2 Utf16 characters, depending on
1183           // whether the decoded value requires a surrogate pair.
1184           offset += 5 - (value > static_cast<uc32>(
1185                                      unibrow::Utf16::kMaxNonSurrogateCharCode));
1186           break;
1187         }
1188 
1189         case EscapeKind::kIllegal:
1190           AllowHeapAllocation allow_before_exception;
1191           ReportUnexpectedCharacter(c);
1192           return JsonString();
1193       }
1194 
1195       advance();
1196       continue;
1197     }
1198 
1199     DCHECK_LT(*cursor_, 0x20);
1200     AllowHeapAllocation allow_before_exception;
1201     ReportUnexpectedCharacter(*cursor_);
1202     break;
1203   }
1204 
1205   return JsonString();
1206 }
1207 
1208 // Explicit instantiation.
1209 template class JsonParser<uint8_t>;
1210 template class JsonParser<uint16_t>;
1211 
1212 }  // namespace internal
1213 }  // namespace v8
1214