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

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: Add assert 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') | no next file with comments »
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 == '\\') {
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
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
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
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_
OLDNEW
« no previous file with comments | « no previous file | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698