Chromium Code Reviews| 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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Handle<String> ParseJsonSymbol() { | 105 Handle<String> ParseJsonSymbol() { |
| 106 return ScanJsonString<true>(); | 106 return ScanJsonString<true>(); |
| 107 } | 107 } |
| 108 template <bool is_symbol> | 108 template <bool is_symbol> |
| 109 Handle<String> ScanJsonString(); | 109 Handle<String> ScanJsonString(); |
| 110 // Slow version for unicode support, uses the first ascii_count characters, | 110 // Slow version for unicode support, uses the first ascii_count characters, |
| 111 // as first part of a ConsString | 111 // as first part of a ConsString |
|
Lasse Reichstein
2011/06/29 09:27:29
Comment out of date (what is ascii_count)?
| |
| 112 Handle<String> SlowScanJsonString(int beg_pos); | 112 Handle<String> SlowScanJsonAsciiString(Handle<String> prefix); |
| 113 Handle<String> SlowScanJsonTwoByteString(Handle<String> prefix); | |
| 113 | 114 |
| 114 // A JSON number (production JSONNumber) is a subset of the valid JavaScript | 115 // A JSON number (production JSONNumber) is a subset of the valid JavaScript |
| 115 // decimal number literals. | 116 // decimal number literals. |
| 116 // It includes an optional minus sign, must have at least one | 117 // It includes an optional minus sign, must have at least one |
| 117 // digit before and after a decimal point, may not have prefixed zeros (unless | 118 // digit before and after a decimal point, may not have prefixed zeros (unless |
| 118 // the integer part is zero), and may include an exponent part (e.g., "e-10"). | 119 // the integer part is zero), and may include an exponent part (e.g., "e-10"). |
| 119 // Hexadecimal and octal numbers are not allowed. | 120 // Hexadecimal and octal numbers are not allowed. |
| 120 Handle<Object> ParseJsonNumber(); | 121 Handle<Object> ParseJsonNumber(); |
| 121 | 122 |
| 122 // Parse a single JSON value from input (grammar production JSONValue). | 123 // Parse a single JSON value from input (grammar production JSONValue). |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 number = StringToDouble(isolate()->unicode_cache(), | 404 number = StringToDouble(isolate()->unicode_cache(), |
| 404 result, | 405 result, |
| 405 NO_FLAGS, // Hex, octal or trailing junk. | 406 NO_FLAGS, // Hex, octal or trailing junk. |
| 406 0.0); | 407 0.0); |
| 407 buffer.Dispose(); | 408 buffer.Dispose(); |
| 408 } | 409 } |
| 409 SkipWhitespace(); | 410 SkipWhitespace(); |
| 410 return isolate()->factory()->NewNumber(number); | 411 return isolate()->factory()->NewNumber(number); |
| 411 } | 412 } |
| 412 | 413 |
| 414 | |
| 413 template <bool seq_ascii> | 415 template <bool seq_ascii> |
| 414 Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(int beg_pos) { | 416 Handle<String> JsonParser<seq_ascii>::SlowScanJsonTwoByteString( |
| 415 // The currently scanned ascii characters. | 417 Handle<String> prefix) { |
| 416 Handle<String> ascii(isolate()->factory()->NewStrictSubString(source_, | 418 int length = kInitialSpecialStringSize; |
|
Lasse Reichstein
2011/06/24 13:56:00
Change ...StringSize to ...StringLength. Size soun
| |
| 417 beg_pos, | 419 Handle<String> new_two_byte = |
| 418 position_)); | 420 isolate()->factory()->NewRawTwoByteString(length, NOT_TENURED); |
|
Lasse Reichstein
2011/06/24 13:56:00
If NewRawTwoByteString doesn't return a Handle<Seq
| |
| 419 Handle<String> two_byte = | |
| 420 isolate()->factory()->NewRawTwoByteString(kInitialSpecialStringSize, | |
| 421 NOT_TENURED); | |
| 422 Handle<SeqTwoByteString> seq_two_byte = | 421 Handle<SeqTwoByteString> seq_two_byte = |
| 423 Handle<SeqTwoByteString>::cast(two_byte); | 422 Handle<SeqTwoByteString>::cast(new_two_byte); |
| 424 | |
| 425 int allocation_count = 1; | |
| 426 int count = 0; | 423 int count = 0; |
| 427 | 424 |
| 428 while (c0_ != '"') { | 425 while (c0_ != '"') { |
| 429 // Create new seq string | 426 // Create new seq string |
| 430 if (count >= kInitialSpecialStringSize * allocation_count) { | 427 if (count >= length) { |
| 431 allocation_count = allocation_count * 2; | 428 prefix = isolate()->factory()->NewConsString(prefix, new_two_byte); |
| 432 int new_size = allocation_count * kInitialSpecialStringSize; | 429 length *= 2; |
| 433 Handle<String> new_two_byte = | 430 new_two_byte = isolate()->factory()-> |
| 434 isolate()->factory()->NewRawTwoByteString(new_size, | 431 NewRawTwoByteString(length, NOT_TENURED); |
| 435 NOT_TENURED); | |
| 436 uc16* char_start = | |
| 437 Handle<SeqTwoByteString>::cast(new_two_byte)->GetChars(); | |
| 438 String::WriteToFlat(*seq_two_byte, char_start, 0, count); | |
| 439 seq_two_byte = Handle<SeqTwoByteString>::cast(new_two_byte); | 432 seq_two_byte = Handle<SeqTwoByteString>::cast(new_two_byte); |
| 433 count = 0; | |
| 440 } | 434 } |
| 441 | 435 |
| 442 // Check for control character (0x00-0x1f) or unterminated string (<0). | 436 // Check for control character (0x00-0x1f) or unterminated string (<0). |
| 443 if (c0_ < 0x20) return Handle<String>::null(); | 437 if (c0_ < 0x20) return Handle<String>::null(); |
| 444 if (c0_ != '\\') { | 438 if (c0_ != '\\') { |
| 445 seq_two_byte->SeqTwoByteStringSet(count++, c0_); | 439 seq_two_byte->SeqTwoByteStringSet(count++, c0_); |
| 446 Advance(); | 440 Advance(); |
| 447 } else { | 441 } else { |
| 448 Advance(); | 442 Advance(); // Advance past the \. |
| 449 switch (c0_) { | 443 switch (c0_) { |
| 450 case '"': | 444 case '"': |
| 451 case '\\': | 445 case '\\': |
| 452 case '/': | 446 case '/': |
| 453 seq_two_byte->SeqTwoByteStringSet(count++, c0_); | 447 seq_two_byte->SeqTwoByteStringSet(count++, c0_); |
| 454 break; | 448 break; |
| 455 case 'b': | 449 case 'b': |
| 456 seq_two_byte->SeqTwoByteStringSet(count++, '\x08'); | 450 seq_two_byte->SeqTwoByteStringSet(count++, '\x08'); |
| 457 break; | 451 break; |
| 458 case 'f': | 452 case 'f': |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 479 } | 473 } |
| 480 seq_two_byte->SeqTwoByteStringSet(count++, value); | 474 seq_two_byte->SeqTwoByteStringSet(count++, value); |
| 481 break; | 475 break; |
| 482 } | 476 } |
| 483 default: | 477 default: |
| 484 return Handle<String>::null(); | 478 return Handle<String>::null(); |
| 485 } | 479 } |
| 486 Advance(); | 480 Advance(); |
| 487 } | 481 } |
| 488 } | 482 } |
| 489 // Advance past the last '"'. | |
| 490 ASSERT_EQ('"', c0_); | |
| 491 AdvanceSkipWhitespace(); | |
| 492 | 483 |
| 493 // Shrink the the string to our length. | 484 // Shrink new_two_byte from length to count. |
| 494 if (isolate()->heap()->InNewSpace(*seq_two_byte)) { | 485 if (isolate()->heap()->InNewSpace(*new_two_byte)) { |
| 495 isolate()->heap()->new_space()-> | 486 isolate()->heap()->new_space()-> |
| 496 template ShrinkStringAtAllocationBoundary<SeqTwoByteString>( | 487 template ShrinkStringAtAllocationBoundary<SeqTwoByteString>( |
| 497 *seq_two_byte, count); | 488 *seq_two_byte, count); |
| 498 } else { | 489 } else { |
| 499 int string_size = SeqTwoByteString::SizeFor(count); | 490 int string_size = SeqTwoByteString::SizeFor(count); |
| 500 int allocated_string_size = | 491 int allocated_string_size = SeqTwoByteString::SizeFor(length); |
| 501 SeqTwoByteString::SizeFor(kInitialSpecialStringSize * allocation_count); | |
| 502 int delta = allocated_string_size - string_size; | 492 int delta = allocated_string_size - string_size; |
| 503 Address start_filler_object = seq_two_byte->address() + string_size; | 493 Address start_filler_object = seq_two_byte->address() + string_size; |
| 504 seq_two_byte->set_length(count); | 494 seq_two_byte->set_length(count); |
| 505 isolate()->heap()->CreateFillerObjectAt(start_filler_object, delta); | 495 isolate()->heap()->CreateFillerObjectAt(start_filler_object, delta); |
| 506 } | 496 } |
| 507 return isolate()->factory()->NewConsString(ascii, seq_two_byte); | 497 ASSERT_EQ('"', c0_); |
| 498 AdvanceSkipWhitespace(); | |
| 499 return isolate()->factory()->NewConsString(prefix, new_two_byte); | |
| 500 } | |
| 501 | |
| 502 | |
| 503 template <bool seq_ascii> | |
| 504 Handle<String> JsonParser<seq_ascii>::SlowScanJsonAsciiString( | |
|
Lasse Reichstein
2011/06/24 13:56:00
Sounds like it scans an ASCII string, not that it
| |
| 505 Handle<String> prefix) { | |
| 506 int length = kInitialSpecialStringSize; | |
| 507 Handle<String> new_ascii = | |
| 508 isolate()->factory()->NewRawAsciiString(length, NOT_TENURED); | |
| 509 Handle<SeqAsciiString> seq_ascii_str = | |
| 510 Handle<SeqAsciiString>::cast(new_ascii); | |
| 511 int count = 0; | |
| 512 | |
| 513 while (c0_ != '"') { | |
| 514 // Create new seq string | |
| 515 if (count >= length) { | |
| 516 prefix = isolate()->factory()->NewConsString(prefix, new_ascii); | |
| 517 length *= 2; | |
| 518 new_ascii = isolate()->factory()->NewRawAsciiString(length, NOT_TENURED); | |
| 519 seq_ascii_str = Handle<SeqAsciiString>::cast(new_ascii); | |
| 520 count = 0; | |
| 521 } | |
| 522 | |
| 523 // Check for control character (0x00-0x1f) or unterminated string (<0). | |
| 524 if (c0_ < 0x20) return Handle<String>::null(); | |
| 525 if (c0_ != '\\') { | |
| 526 if (seq_ascii || c0_ <= kMaxAsciiCharCode) { | |
| 527 seq_ascii_str->SeqAsciiStringSet(count++, c0_); | |
| 528 Advance(); | |
| 529 } else { | |
| 530 break; | |
| 531 } | |
| 532 } else { | |
| 533 Advance(); // Advance past the \. | |
| 534 switch (c0_) { | |
| 535 case '"': | |
| 536 case '\\': | |
| 537 case '/': | |
| 538 seq_ascii_str->SeqAsciiStringSet(count++, c0_); | |
| 539 break; | |
| 540 case 'b': | |
| 541 seq_ascii_str->SeqAsciiStringSet(count++, '\x08'); | |
| 542 break; | |
| 543 case 'f': | |
| 544 seq_ascii_str->SeqAsciiStringSet(count++, '\x0c'); | |
| 545 break; | |
| 546 case 'n': | |
| 547 seq_ascii_str->SeqAsciiStringSet(count++, '\x0a'); | |
| 548 break; | |
| 549 case 'r': | |
| 550 seq_ascii_str->SeqAsciiStringSet(count++, '\x0d'); | |
| 551 break; | |
| 552 case 't': | |
| 553 seq_ascii_str->SeqAsciiStringSet(count++, '\x09'); | |
| 554 break; | |
| 555 case 'u': { | |
| 556 uc32 value = 0; | |
| 557 for (int i = 0; i < 4; i++) { | |
| 558 Advance(); | |
| 559 int digit = HexValue(c0_); | |
| 560 if (digit < 0) { | |
| 561 return Handle<String>::null(); | |
| 562 } | |
| 563 value = value * 16 + digit; | |
| 564 } | |
| 565 if (value <= kMaxAsciiCharCode) { | |
| 566 seq_ascii_str->SeqAsciiStringSet(count++, value); | |
| 567 break; | |
| 568 } else { | |
| 569 position_ -= 6; // Rewind position to \ in \uxxxx. | |
| 570 Advance(); | |
| 571 goto outer_loop; // break out of while loop. | |
|
Lasse Reichstein
2011/06/24 13:56:00
I'm really not too keen on using gotos. Really not
| |
| 572 } | |
| 573 } | |
| 574 default: | |
| 575 return Handle<String>::null(); | |
| 576 } | |
| 577 Advance(); | |
| 578 } | |
| 579 } | |
| 580 outer_loop: | |
| 581 // Shrink new_ascii from length to count. | |
| 582 if (isolate()->heap()->InNewSpace(*new_ascii)) { | |
| 583 isolate()->heap()->new_space()-> | |
| 584 template ShrinkStringAtAllocationBoundary<SeqAsciiString>( | |
| 585 *seq_ascii_str, count); | |
| 586 } else { | |
| 587 int string_size = SeqAsciiString::SizeFor(count); | |
|
Lasse Reichstein
2011/06/24 13:56:00
If the truncation would turn a lot of space into f
| |
| 588 int allocated_string_size = SeqAsciiString::SizeFor(length); | |
| 589 int delta = allocated_string_size - string_size; | |
| 590 Address start_filler_object = seq_ascii_str->address() + string_size; | |
| 591 seq_ascii_str->set_length(count); | |
| 592 isolate()->heap()->CreateFillerObjectAt(start_filler_object, delta); | |
| 593 } | |
|
Lasse Reichstein
2011/06/24 13:56:00
If you move the shrinking to a separate function,
| |
| 594 prefix = isolate()->factory()->NewConsString(prefix, new_ascii); | |
| 595 if (c0_ != '"') { | |
| 596 // We have read a non-ascii character - either directly or as \uxxxx. | |
| 597 return this->SlowScanJsonTwoByteString(prefix); | |
| 598 } | |
| 599 ASSERT_EQ('"', c0_); | |
| 600 // Advance past the last '"'. | |
| 601 AdvanceSkipWhitespace(); | |
| 602 return prefix; | |
| 508 } | 603 } |
| 509 | 604 |
| 510 template <bool seq_ascii> | 605 template <bool seq_ascii> |
| 511 template <bool is_symbol> | 606 template <bool is_symbol> |
| 512 Handle<String> JsonParser<seq_ascii>::ScanJsonString() { | 607 Handle<String> JsonParser<seq_ascii>::ScanJsonString() { |
| 513 ASSERT_EQ('"', c0_); | 608 ASSERT_EQ('"', c0_); |
| 514 Advance(); | 609 Advance(); |
| 515 int beg_pos = position_; | 610 int beg_pos = position_; |
| 516 // Fast case for ascii only without escape characters. | 611 // Fast case for ascii only without escape characters. |
| 517 while (c0_ != '"') { | 612 while (c0_ != '"') { |
| 518 // Check for control character (0x00-0x1f) or unterminated string (<0). | 613 // Check for control character (0x00-0x1f) or unterminated string (<0). |
| 519 if (c0_ < 0x20) return Handle<String>::null(); | 614 if (c0_ < 0x20) return Handle<String>::null(); |
| 520 if (c0_ != '\\' && (seq_ascii || c0_ < kMaxAsciiCharCode)) { | 615 if (c0_ != '\\' && (seq_ascii || c0_ <= kMaxAsciiCharCode)) { |
| 521 Advance(); | 616 Advance(); |
| 522 } else { | 617 } else { |
| 523 return this->SlowScanJsonString(beg_pos); | 618 break; |
|
Lasse Reichstein
2011/06/24 13:56:00
Again, you can abstract the part below into a func
| |
| 524 } | 619 } |
| 525 } | 620 } |
| 526 ASSERT_EQ('"', c0_); | 621 Handle<String> result; |
| 527 int end_pos = position_; | 622 if (seq_ascii) { |
| 623 if (is_symbol) { | |
| 624 result = isolate()->factory()->LookupAsciiSymbol(seq_source_, | |
| 625 beg_pos, | |
| 626 position_ - beg_pos); | |
| 627 } else { | |
| 628 result = isolate()->factory()->NewStrictSubString(source_, | |
| 629 beg_pos, | |
| 630 position_); | |
| 631 } | |
| 632 } else { | |
| 633 int length = position_ - beg_pos; | |
| 634 result = isolate()->factory()->NewRawAsciiString(length); | |
| 635 ASSERT(result->IsAsciiRepresentation()); | |
| 636 char* dest = SeqAsciiString::cast(*result)->GetChars(); | |
| 637 String::WriteToFlat(*source_, dest, beg_pos, position_); | |
| 638 } | |
| 639 if (c0_ != '"') { | |
| 640 return this->SlowScanJsonAsciiString(result); | |
| 641 } | |
| 528 // Advance past the last '"'. | 642 // Advance past the last '"'. |
| 529 AdvanceSkipWhitespace(); | 643 AdvanceSkipWhitespace(); |
| 530 if (seq_ascii && is_symbol) { | 644 return result; |
| 531 return isolate()->factory()->LookupAsciiSymbol(seq_source_, | |
| 532 beg_pos, | |
| 533 end_pos - beg_pos); | |
| 534 } else { | |
| 535 return isolate()->factory()->NewStrictSubString(source_, | |
| 536 beg_pos, | |
| 537 end_pos); | |
| 538 } | |
| 539 } | 645 } |
| 540 | 646 |
| 541 } } // namespace v8::internal | 647 } } // namespace v8::internal |
| 542 | 648 |
| 543 #endif // V8_JSON_PARSER_H_ | 649 #endif // V8_JSON_PARSER_H_ |
| OLD | NEW |