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 |