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