| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 return false; | 95 return false; |
| 96 } | 96 } |
| 97 | 97 |
| 98 // A JSON string (production JSONString) is subset of valid JavaScript string | 98 // A JSON string (production JSONString) is subset of valid JavaScript string |
| 99 // literals. The string must only be double-quoted (not single-quoted), and | 99 // literals. The string must only be double-quoted (not single-quoted), and |
| 100 // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and | 100 // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and |
| 101 // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid. | 101 // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid. |
| 102 Handle<String> ParseJsonString() { | 102 Handle<String> ParseJsonString() { |
| 103 return ScanJsonString<false>(); | 103 return ScanJsonString<false>(); |
| 104 } | 104 } |
| 105 |
| 106 bool ParseJsonString(Handle<String> expected) { |
| 107 int length = expected->length(); |
| 108 if (source_->length() - position_ - 1 > length) { |
| 109 AssertNoAllocation no_gc; |
| 110 String::FlatContent content = expected->GetFlatContent(); |
| 111 if (content.IsAscii()) { |
| 112 ASSERT_EQ('"', c0_); |
| 113 const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1; |
| 114 const uint8_t* expected_chars = content.ToOneByteVector().start(); |
| 115 for (int i = 0; i < length; i++) { |
| 116 uint8_t c0 = input_chars[i]; |
| 117 if (c0 != expected_chars[i] || |
| 118 c0 == '"' || c0 < 0x20 || c0 == '\\') { |
| 119 return false; |
| 120 } |
| 121 } |
| 122 if (input_chars[length] == '"') { |
| 123 position_ = position_ + length + 1; |
| 124 AdvanceSkipWhitespace(); |
| 125 return true; |
| 126 } |
| 127 } |
| 128 } |
| 129 return false; |
| 130 } |
| 131 |
| 105 Handle<String> ParseJsonInternalizedString() { | 132 Handle<String> ParseJsonInternalizedString() { |
| 106 return ScanJsonString<true>(); | 133 return ScanJsonString<true>(); |
| 107 } | 134 } |
| 135 |
| 108 template <bool is_internalized> | 136 template <bool is_internalized> |
| 109 Handle<String> ScanJsonString(); | 137 Handle<String> ScanJsonString(); |
| 110 // Creates a new string and copies prefix[start..end] into the beginning | 138 // Creates a new string and copies prefix[start..end] into the beginning |
| 111 // of it. Then scans the rest of the string, adding characters after the | 139 // of it. Then scans the rest of the string, adding characters after the |
| 112 // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char. | 140 // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char. |
| 113 template <typename StringType, typename SinkChar> | 141 template <typename StringType, typename SinkChar> |
| 114 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end); | 142 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end); |
| 115 | 143 |
| 116 // A JSON number (production JSONNumber) is a subset of the valid JavaScript | 144 // A JSON number (production JSONNumber) is a subset of the valid JavaScript |
| 117 // decimal number literals. | 145 // decimal number literals. |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 return ReportUnexpectedCharacter(); | 315 return ReportUnexpectedCharacter(); |
| 288 } | 316 } |
| 289 | 317 |
| 290 | 318 |
| 291 // Parse a JSON object. Position must be right at '{'. | 319 // Parse a JSON object. Position must be right at '{'. |
| 292 template <bool seq_ascii> | 320 template <bool seq_ascii> |
| 293 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() { | 321 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() { |
| 294 HandleScope scope(isolate()); | 322 HandleScope scope(isolate()); |
| 295 Handle<JSObject> json_object = | 323 Handle<JSObject> json_object = |
| 296 factory()->NewJSObject(object_constructor(), pretenure_); | 324 factory()->NewJSObject(object_constructor(), pretenure_); |
| 325 Handle<Map> map(json_object->map()); |
| 326 ZoneScope zone_scope(zone(), DELETE_ON_EXIT); |
| 327 ZoneList<Handle<Object> > properties(8, zone()); |
| 297 ASSERT_EQ(c0_, '{'); | 328 ASSERT_EQ(c0_, '{'); |
| 298 | 329 |
| 330 bool transitioning = true; |
| 331 |
| 299 AdvanceSkipWhitespace(); | 332 AdvanceSkipWhitespace(); |
| 300 if (c0_ != '}') { | 333 if (c0_ != '}') { |
| 301 do { | 334 do { |
| 302 if (c0_ != '"') return ReportUnexpectedCharacter(); | 335 if (c0_ != '"') return ReportUnexpectedCharacter(); |
| 303 | 336 |
| 304 int start_position = position_; | 337 int start_position = position_; |
| 305 Advance(); | 338 Advance(); |
| 306 | 339 |
| 307 uint32_t index = 0; | 340 uint32_t index = 0; |
| 308 if (c0_ >= '0' && c0_ <= '9') { | 341 if (c0_ >= '0' && c0_ <= '9') { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 332 continue; | 365 continue; |
| 333 } | 366 } |
| 334 // Not an index, fallback to the slow path. | 367 // Not an index, fallback to the slow path. |
| 335 } | 368 } |
| 336 | 369 |
| 337 position_ = start_position; | 370 position_ = start_position; |
| 338 #ifdef DEBUG | 371 #ifdef DEBUG |
| 339 c0_ = '"'; | 372 c0_ = '"'; |
| 340 #endif | 373 #endif |
| 341 | 374 |
| 342 Handle<String> key = ParseJsonInternalizedString(); | 375 Handle<String> key; |
| 343 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); | 376 Handle<Object> value; |
| 344 | 377 |
| 345 AdvanceSkipWhitespace(); | 378 // Try to follow existing transitions as long as possible. Once we stop |
| 346 Handle<Object> value = ParseJsonValue(); | 379 // transitioning, no transition can be found anymore. |
| 347 if (value.is_null()) return ReportUnexpectedCharacter(); | 380 if (transitioning) { |
| 381 // First check whether there is a single expected transition. If so, try |
| 382 // to parse it first. |
| 383 bool follow_expected = false; |
| 384 if (seq_ascii) { |
| 385 key = JSObject::ExpectedTransitionKey(map); |
| 386 follow_expected = !key.is_null() && ParseJsonString(key); |
| 387 } |
| 388 // If the expected transition hits, follow it. |
| 389 if (follow_expected) { |
| 390 map = JSObject::ExpectedTransitionTarget(map); |
| 391 } else { |
| 392 // If the expected transition failed, parse an internalized string and |
| 393 // try to find a matching transition. |
| 394 key = ParseJsonInternalizedString(); |
| 395 if (key.is_null()) return ReportUnexpectedCharacter(); |
| 348 | 396 |
| 349 if (JSObject::TryTransitionToField(json_object, key)) { | 397 Handle<Map> target = JSObject::FindTransitionToField(map, key); |
| 350 int index = json_object->LastAddedFieldIndex(); | 398 // If a transition was found, follow it and continue. |
| 351 json_object->FastPropertyAtPut(index, *value); | 399 if (!target.is_null()) { |
| 400 map = target; |
| 401 } else { |
| 402 // If no transition was found, commit the intermediate state to the |
| 403 // object and stop transitioning. |
| 404 JSObject::TransitionToMap(json_object, map); |
| 405 int length = properties.length(); |
| 406 for (int i = 0; i < length; i++) { |
| 407 json_object->FastPropertyAtPut(i, *properties[i]); |
| 408 } |
| 409 transitioning = false; |
| 410 } |
| 411 } |
| 412 if (c0_ != ':') return ReportUnexpectedCharacter(); |
| 413 |
| 414 AdvanceSkipWhitespace(); |
| 415 value = ParseJsonValue(); |
| 416 if (value.is_null()) return ReportUnexpectedCharacter(); |
| 417 |
| 418 properties.Add(value, zone()); |
| 419 if (transitioning) continue; |
| 352 } else { | 420 } else { |
| 353 JSObject::SetLocalPropertyIgnoreAttributes( | 421 key = ParseJsonInternalizedString(); |
| 354 json_object, key, value, NONE); | 422 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); |
| 423 |
| 424 AdvanceSkipWhitespace(); |
| 425 value = ParseJsonValue(); |
| 426 if (value.is_null()) return ReportUnexpectedCharacter(); |
| 355 } | 427 } |
| 428 |
| 429 JSObject::SetLocalPropertyIgnoreAttributes( |
| 430 json_object, key, value, NONE); |
| 356 } while (MatchSkipWhiteSpace(',')); | 431 } while (MatchSkipWhiteSpace(',')); |
| 357 if (c0_ != '}') { | 432 if (c0_ != '}') { |
| 358 return ReportUnexpectedCharacter(); | 433 return ReportUnexpectedCharacter(); |
| 359 } | 434 } |
| 435 |
| 436 // If we transitioned until the very end, transition the map now. |
| 437 if (transitioning) { |
| 438 JSObject::TransitionToMap(json_object, map); |
| 439 int length = properties.length(); |
| 440 for (int i = 0; i < length; i++) { |
| 441 json_object->FastPropertyAtPut(i, *properties[i]); |
| 442 } |
| 443 } |
| 360 } | 444 } |
| 361 AdvanceSkipWhitespace(); | 445 AdvanceSkipWhitespace(); |
| 362 return scope.CloseAndEscape(json_object); | 446 return scope.CloseAndEscape(json_object); |
| 363 } | 447 } |
| 364 | 448 |
| 365 // Parse a JSON array. Position must be right at '['. | 449 // Parse a JSON array. Position must be right at '['. |
| 366 template <bool seq_ascii> | 450 template <bool seq_ascii> |
| 367 Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() { | 451 Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() { |
| 368 HandleScope scope(isolate()); | 452 HandleScope scope(isolate()); |
| 369 ZoneScope zone_scope(zone(), DELETE_ON_EXIT); | 453 ZoneScope zone_scope(zone(), DELETE_ON_EXIT); |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 } while (c0 != '"'); | 721 } while (c0 != '"'); |
| 638 int length = position - position_; | 722 int length = position - position_; |
| 639 uint32_t hash = (length <= String::kMaxHashCalcLength) | 723 uint32_t hash = (length <= String::kMaxHashCalcLength) |
| 640 ? StringHasher::GetHashCore(running_hash) : length; | 724 ? StringHasher::GetHashCore(running_hash) : length; |
| 641 Vector<const uint8_t> string_vector( | 725 Vector<const uint8_t> string_vector( |
| 642 seq_source_->GetChars() + position_, length); | 726 seq_source_->GetChars() + position_, length); |
| 643 StringTable* string_table = isolate()->heap()->string_table(); | 727 StringTable* string_table = isolate()->heap()->string_table(); |
| 644 uint32_t capacity = string_table->Capacity(); | 728 uint32_t capacity = string_table->Capacity(); |
| 645 uint32_t entry = StringTable::FirstProbe(hash, capacity); | 729 uint32_t entry = StringTable::FirstProbe(hash, capacity); |
| 646 uint32_t count = 1; | 730 uint32_t count = 1; |
| 731 Handle<String> result; |
| 647 while (true) { | 732 while (true) { |
| 648 Object* element = string_table->KeyAt(entry); | 733 Object* element = string_table->KeyAt(entry); |
| 649 if (element == isolate()->heap()->undefined_value()) { | 734 if (element == isolate()->heap()->undefined_value()) { |
| 650 // Lookup failure. | 735 // Lookup failure. |
| 736 result = factory()->InternalizeOneByteString( |
| 737 seq_source_, position_, length); |
| 651 break; | 738 break; |
| 652 } | 739 } |
| 653 if (element != isolate()->heap()->the_hole_value() && | 740 if (element != isolate()->heap()->the_hole_value() && |
| 654 String::cast(element)->IsOneByteEqualTo(string_vector)) { | 741 String::cast(element)->IsOneByteEqualTo(string_vector)) { |
| 655 // Lookup success, update the current position. | 742 result = Handle<String>(String::cast(element), isolate()); |
| 656 position_ = position; | 743 #ifdef DEBUG |
| 657 // Advance past the last '"'. | 744 uint32_t hash_field = |
| 658 AdvanceSkipWhitespace(); | 745 (hash << String::kHashShift) | String::kIsNotArrayIndexMask; |
| 659 return Handle<String>(String::cast(element), isolate()); | 746 ASSERT_EQ(static_cast<int>(result->Hash()), |
| 747 static_cast<int>(hash_field >> String::kHashShift)); |
| 748 #endif |
| 749 break; |
| 660 } | 750 } |
| 661 entry = StringTable::NextProbe(entry, count++, capacity); | 751 entry = StringTable::NextProbe(entry, count++, capacity); |
| 662 } | 752 } |
| 753 position_ = position; |
| 754 // Advance past the last '"'. |
| 755 AdvanceSkipWhitespace(); |
| 756 return result; |
| 663 } | 757 } |
| 664 | 758 |
| 665 int beg_pos = position_; | 759 int beg_pos = position_; |
| 666 // Fast case for ASCII only without escape characters. | 760 // Fast case for ASCII only without escape characters. |
| 667 do { | 761 do { |
| 668 // Check for control character (0x00-0x1f) or unterminated string (<0). | 762 // Check for control character (0x00-0x1f) or unterminated string (<0). |
| 669 if (c0_ < 0x20) return Handle<String>::null(); | 763 if (c0_ < 0x20) return Handle<String>::null(); |
| 670 if (c0_ != '\\') { | 764 if (c0_ != '\\') { |
| 671 if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) { | 765 if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) { |
| 672 Advance(); | 766 Advance(); |
| 673 } else { | 767 } else { |
| 674 return SlowScanJsonString<SeqTwoByteString, uc16>(source_, | 768 return SlowScanJsonString<SeqTwoByteString, uc16>(source_, |
| 675 beg_pos, | 769 beg_pos, |
| 676 position_); | 770 position_); |
| 677 } | 771 } |
| 678 } else { | 772 } else { |
| 679 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, | 773 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, |
| 680 beg_pos, | 774 beg_pos, |
| 681 position_); | 775 position_); |
| 682 } | 776 } |
| 683 } while (c0_ != '"'); | 777 } while (c0_ != '"'); |
| 684 int length = position_ - beg_pos; | 778 int length = position_ - beg_pos; |
| 685 Handle<String> result; | 779 Handle<String> result = factory()->NewRawOneByteString(length, pretenure_); |
| 686 if (seq_ascii && is_internalized) { | 780 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(); |
| 687 result = factory()->InternalizeOneByteString(seq_source_, beg_pos, length); | 781 String::WriteToFlat(*source_, dest, beg_pos, position_); |
| 688 } else { | 782 |
| 689 result = factory()->NewRawOneByteString(length, pretenure_); | |
| 690 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(); | |
| 691 String::WriteToFlat(*source_, dest, beg_pos, position_); | |
| 692 } | |
| 693 ASSERT_EQ('"', c0_); | 783 ASSERT_EQ('"', c0_); |
| 694 // Advance past the last '"'. | 784 // Advance past the last '"'. |
| 695 AdvanceSkipWhitespace(); | 785 AdvanceSkipWhitespace(); |
| 696 return result; | 786 return result; |
| 697 } | 787 } |
| 698 | 788 |
| 699 } } // namespace v8::internal | 789 } } // namespace v8::internal |
| 700 | 790 |
| 701 #endif // V8_JSON_PARSER_H_ | 791 #endif // V8_JSON_PARSER_H_ |
| OLD | NEW |