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