Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: src/json-parser.h

Issue 13741010: Eagerly parse expected transitions in JSON. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Only commit after transitioning Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/objects.h » ('j') | src/objects-inl.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 == '\\') {
Yang 2013/04/09 15:47:00 maybe you also need to check for 0x7f, which is al
Toon Verwaest 2013/04/09 16:47:59 Irrelevant, as discussed offline.
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 }
Yang 2013/04/09 15:47:00 I guess an empty line here would make sense.
Toon Verwaest 2013/04/09 16:47:59 Done.
105 Handle<String> ParseJsonInternalizedString() { 131 Handle<String> ParseJsonInternalizedString() {
106 return ScanJsonString<true>(); 132 return ScanJsonString<true>();
107 } 133 }
Yang 2013/04/09 15:47:00 empty line here as well.
Toon Verwaest 2013/04/09 16:47:59 Done.
108 template <bool is_internalized> 134 template <bool is_internalized>
109 Handle<String> ScanJsonString(); 135 Handle<String> ScanJsonString();
110 // Creates a new string and copies prefix[start..end] into the beginning 136 // 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 137 // 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. 138 // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char.
113 template <typename StringType, typename SinkChar> 139 template <typename StringType, typename SinkChar>
114 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end); 140 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
115 141
116 // A JSON number (production JSONNumber) is a subset of the valid JavaScript 142 // A JSON number (production JSONNumber) is a subset of the valid JavaScript
117 // decimal number literals. 143 // decimal number literals.
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 return ReportUnexpectedCharacter(); 313 return ReportUnexpectedCharacter();
288 } 314 }
289 315
290 316
291 // Parse a JSON object. Position must be right at '{'. 317 // Parse a JSON object. Position must be right at '{'.
292 template <bool seq_ascii> 318 template <bool seq_ascii>
293 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() { 319 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
294 HandleScope scope(isolate()); 320 HandleScope scope(isolate());
295 Handle<JSObject> json_object = 321 Handle<JSObject> json_object =
296 factory()->NewJSObject(object_constructor(), pretenure_); 322 factory()->NewJSObject(object_constructor(), pretenure_);
323 Handle<Map> map(json_object->map());
324 ZoneScope zone_scope(zone(), DELETE_ON_EXIT);
325 ZoneList<Handle<Object> > properties(8, zone());
Yang 2013/04/09 15:47:00 You could reuse one zone list through out the enti
Toon Verwaest 2013/04/09 16:47:59 That's unfortunately not possible since objects ar
297 ASSERT_EQ(c0_, '{'); 326 ASSERT_EQ(c0_, '{');
298 327
328 bool transitioning = true;
329
299 AdvanceSkipWhitespace(); 330 AdvanceSkipWhitespace();
300 if (c0_ != '}') { 331 if (c0_ != '}') {
301 do { 332 do {
302 if (c0_ != '"') return ReportUnexpectedCharacter(); 333 if (c0_ != '"') return ReportUnexpectedCharacter();
303 334
304 int start_position = position_; 335 int start_position = position_;
305 Advance(); 336 Advance();
306 337
307 uint32_t index = 0; 338 uint32_t index = 0;
308 if (c0_ >= '0' && c0_ <= '9') { 339 if (c0_ >= '0' && c0_ <= '9') {
(...skipping 23 matching lines...) Expand all
332 continue; 363 continue;
333 } 364 }
334 // Not an index, fallback to the slow path. 365 // Not an index, fallback to the slow path.
335 } 366 }
336 367
337 position_ = start_position; 368 position_ = start_position;
338 #ifdef DEBUG 369 #ifdef DEBUG
339 c0_ = '"'; 370 c0_ = '"';
340 #endif 371 #endif
341 372
342 Handle<String> key = ParseJsonInternalizedString(); 373 Handle<String> key;
343 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); 374 Handle<Object> value;
344 375
345 AdvanceSkipWhitespace(); 376 // Try to follow existing transitions as long as possible. Once we stop
346 Handle<Object> value = ParseJsonValue(); 377 // transitioning, no transition can be found anymore.
347 if (value.is_null()) return ReportUnexpectedCharacter(); 378 if (transitioning) {
379 // First check whether there is a single expected transition. If so, try
380 // to parse it first.
381 bool follow_expected = false;
382 if (seq_ascii) {
383 key = JSObject::ExpectedTransitionKey(map);
384 follow_expected = !key.is_null() && ParseJsonString(key);
385 }
386 // If the expected transition hits, follow it.
387 if (follow_expected) {
388 map = JSObject::ExpectedTransitionTarget(map);
389 } else {
390 // If the expected transition failed, parse an internal string and try
Yang 2013/04/09 15:47:00 "internalized string"
Toon Verwaest 2013/04/09 16:47:59 Done.
391 // to find a matching transition.
392 key = ParseJsonInternalizedString();
393 if (key.is_null()) return ReportUnexpectedCharacter();
348 394
349 if (JSObject::TryTransitionToField(json_object, key)) { 395 Handle<Map> target = JSObject::FindTransitionToField(map, key);
350 int index = json_object->LastAddedFieldIndex(); 396 // If a transition was found, follow it and continue.
351 json_object->FastPropertyAtPut(index, *value); 397 if (!target.is_null()) {
398 map = target;
399 } else {
400 // If no transition was found, commit the intermediate state to the
401 // object and stop transitioning.
402 JSObject::TransitionToMap(json_object, map);
403 int length = properties.length();
404 for (int i = 0; i < length; i++) {
405 json_object->FastPropertyAtPut(i, *properties[i]);
406 }
407 transitioning = false;
408 }
409 }
410 if (c0_ != ':') return ReportUnexpectedCharacter();
411
412 AdvanceSkipWhitespace();
413 value = ParseJsonValue();
414 if (value.is_null()) return ReportUnexpectedCharacter();
415
416 properties.Add(value, zone());
417 if (transitioning) continue;
352 } else { 418 } else {
353 JSObject::SetLocalPropertyIgnoreAttributes( 419 key = ParseJsonInternalizedString();
354 json_object, key, value, NONE); 420 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
421
422 AdvanceSkipWhitespace();
423 value = ParseJsonValue();
424 if (value.is_null()) return ReportUnexpectedCharacter();
355 } 425 }
426
427 JSObject::SetLocalPropertyIgnoreAttributes(
428 json_object, key, value, NONE);
356 } while (MatchSkipWhiteSpace(',')); 429 } while (MatchSkipWhiteSpace(','));
357 if (c0_ != '}') { 430 if (c0_ != '}') {
358 return ReportUnexpectedCharacter(); 431 return ReportUnexpectedCharacter();
359 } 432 }
433
434 // If we transitioned until the very end, transition the map now.
435 if (transitioning) {
436 JSObject::TransitionToMap(json_object, map);
437 int length = properties.length();
438 for (int i = 0; i < length; i++) {
439 json_object->FastPropertyAtPut(i, *properties[i]);
440 }
441 }
360 } 442 }
361 AdvanceSkipWhitespace(); 443 AdvanceSkipWhitespace();
362 return scope.CloseAndEscape(json_object); 444 return scope.CloseAndEscape(json_object);
363 } 445 }
364 446
365 // Parse a JSON array. Position must be right at '['. 447 // Parse a JSON array. Position must be right at '['.
366 template <bool seq_ascii> 448 template <bool seq_ascii>
367 Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() { 449 Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
368 HandleScope scope(isolate()); 450 HandleScope scope(isolate());
369 ZoneScope zone_scope(zone(), DELETE_ON_EXIT); 451 ZoneScope zone_scope(zone(), DELETE_ON_EXIT);
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 } while (c0 != '"'); 719 } while (c0 != '"');
638 int length = position - position_; 720 int length = position - position_;
639 uint32_t hash = (length <= String::kMaxHashCalcLength) 721 uint32_t hash = (length <= String::kMaxHashCalcLength)
640 ? StringHasher::GetHashCore(running_hash) : length; 722 ? StringHasher::GetHashCore(running_hash) : length;
641 Vector<const uint8_t> string_vector( 723 Vector<const uint8_t> string_vector(
642 seq_source_->GetChars() + position_, length); 724 seq_source_->GetChars() + position_, length);
643 StringTable* string_table = isolate()->heap()->string_table(); 725 StringTable* string_table = isolate()->heap()->string_table();
644 uint32_t capacity = string_table->Capacity(); 726 uint32_t capacity = string_table->Capacity();
645 uint32_t entry = StringTable::FirstProbe(hash, capacity); 727 uint32_t entry = StringTable::FirstProbe(hash, capacity);
646 uint32_t count = 1; 728 uint32_t count = 1;
729 Handle<String> result;
647 while (true) { 730 while (true) {
648 Object* element = string_table->KeyAt(entry); 731 Object* element = string_table->KeyAt(entry);
649 if (element == isolate()->heap()->undefined_value()) { 732 if (element == isolate()->heap()->undefined_value()) {
650 // Lookup failure. 733 // Lookup failure.
734 result = factory()->InternalizeOneByteString(
735 seq_source_, position_, length);
651 break; 736 break;
652 } 737 }
653 if (element != isolate()->heap()->the_hole_value() && 738 if (element != isolate()->heap()->the_hole_value() &&
654 String::cast(element)->IsOneByteEqualTo(string_vector)) { 739 String::cast(element)->IsOneByteEqualTo(string_vector)) {
655 // Lookup success, update the current position. 740 result = Handle<String>(String::cast(element), isolate());
656 position_ = position; 741 #ifdef DEBUG
657 // Advance past the last '"'. 742 uint32_t hash_field =
658 AdvanceSkipWhitespace(); 743 (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
659 return Handle<String>(String::cast(element), isolate()); 744 ASSERT_EQ(static_cast<int>(result->Hash()),
745 static_cast<int>(hash_field >> String::kHashShift));
746 #endif
747 break;
660 } 748 }
661 entry = StringTable::NextProbe(entry, count++, capacity); 749 entry = StringTable::NextProbe(entry, count++, capacity);
662 } 750 }
751 position_ = position;
752 // Advance past the last '"'.
753 AdvanceSkipWhitespace();
754 return result;
663 } 755 }
664 756
665 int beg_pos = position_; 757 int beg_pos = position_;
666 // Fast case for ASCII only without escape characters. 758 // Fast case for ASCII only without escape characters.
667 do { 759 do {
668 // Check for control character (0x00-0x1f) or unterminated string (<0). 760 // Check for control character (0x00-0x1f) or unterminated string (<0).
669 if (c0_ < 0x20) return Handle<String>::null(); 761 if (c0_ < 0x20) return Handle<String>::null();
670 if (c0_ != '\\') { 762 if (c0_ != '\\') {
671 if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) { 763 if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) {
672 Advance(); 764 Advance();
673 } else { 765 } else {
674 return SlowScanJsonString<SeqTwoByteString, uc16>(source_, 766 return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
675 beg_pos, 767 beg_pos,
676 position_); 768 position_);
677 } 769 }
678 } else { 770 } else {
679 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, 771 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
680 beg_pos, 772 beg_pos,
681 position_); 773 position_);
682 } 774 }
683 } while (c0_ != '"'); 775 } while (c0_ != '"');
684 int length = position_ - beg_pos; 776 int length = position_ - beg_pos;
685 Handle<String> result; 777 Handle<String> result = factory()->NewRawOneByteString(length, pretenure_);
686 if (seq_ascii && is_internalized) { 778 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
687 result = factory()->InternalizeOneByteString(seq_source_, beg_pos, length); 779 String::WriteToFlat(*source_, dest, beg_pos, position_);
688 } else { 780
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_); 781 ASSERT_EQ('"', c0_);
694 // Advance past the last '"'. 782 // Advance past the last '"'.
695 AdvanceSkipWhitespace(); 783 AdvanceSkipWhitespace();
696 return result; 784 return result;
697 } 785 }
698 786
699 } } // namespace v8::internal 787 } } // namespace v8::internal
700 788
701 #endif // V8_JSON_PARSER_H_ 789 #endif // V8_JSON_PARSER_H_
OLDNEW
« no previous file with comments | « no previous file | src/objects.h » ('j') | src/objects-inl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698