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

Side by Side Diff: src/scanner.cc

Issue 6246102: Improve ScanJsonNumber performance. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 10 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 | « src/scanner.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <limits.h>
28 #include "v8.h" 29 #include "v8.h"
29 30
30 #include "ast.h" 31 #include "ast.h"
31 #include "handles.h" 32 #include "handles.h"
32 #include "scanner.h" 33 #include "scanner.h"
34 #include "strtod.h"
33 #include "unicode-inl.h" 35 #include "unicode-inl.h"
34 36
35 namespace v8 { 37 namespace v8 {
36 namespace internal { 38 namespace internal {
37 39
38 // ---------------------------------------------------------------------------- 40 // ----------------------------------------------------------------------------
39 // BufferedUC16CharacterStreams 41 // BufferedUC16CharacterStreams
40 42
41 BufferedUC16CharacterStream::BufferedUC16CharacterStream() 43 BufferedUC16CharacterStream::BufferedUC16CharacterStream()
42 : UC16CharacterStream(), 44 : UC16CharacterStream(),
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 token = Token::COLON; 415 token = Token::COLON;
414 break; 416 break;
415 case ',': 417 case ',':
416 Advance(); 418 Advance();
417 token = Token::COMMA; 419 token = Token::COMMA;
418 break; 420 break;
419 case '"': 421 case '"':
420 token = ScanJsonString(); 422 token = ScanJsonString();
421 break; 423 break;
422 case '-': 424 case '-':
425 Advance();
426 token = ScanJsonNumber();
427 number = -number;
428 break;
423 case '0': 429 case '0':
424 case '1': 430 case '1':
425 case '2': 431 case '2':
426 case '3': 432 case '3':
427 case '4': 433 case '4':
428 case '5': 434 case '5':
429 case '6': 435 case '6':
430 case '7': 436 case '7':
431 case '8': 437 case '8':
432 case '9': 438 case '9':
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 Advance(); 514 Advance();
509 } 515 }
510 } 516 }
511 literal.Complete(); 517 literal.Complete();
512 Advance(); 518 Advance();
513 return Token::STRING; 519 return Token::STRING;
514 } 520 }
515 521
516 522
517 Token::Value JsonScanner::ScanJsonNumber() { 523 Token::Value JsonScanner::ScanJsonNumber() {
518 LiteralScope literal(this); 524 // Maximum number of significant digits in decimal representation.
519 if (c0_ == '-') AddLiteralCharAdvance(); 525 // The longest possible double in decimal representation is
526 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
527 // (768 digits). If we parse a number whose first digits are equal to a
528 // mean of 2 adjacent doubles (that could have up to 769 digits) the result
529 // must be rounded to the bigger one unless the tail consists of zeros, so
530 // we don't need to preserve all the digits.
531 const int kMaxSignificantDigits = 772;
532 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
533 const int kBufferSize = kMaxSignificantDigits + 10;
534 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
535 int buffer_pos = 0;
536
537 // Exponent will be adjusted if insignificant digits of the integer part
538 // or insignificant leading zeros of the fractional part are dropped.
539 int exponent = 0;
540 int significant_digits = 0;
541 int insignificant_digits = 0;
542 int i = 0;
543 bool nonzero_digit_dropped = false;
520 if (c0_ == '0') { 544 if (c0_ == '0') {
521 AddLiteralCharAdvance(); 545 Advance();
522 // Prefix zero is only allowed if it's the only digit before 546 // Prefix zero is only allowed if it's the only digit before
523 // a decimal point or exponent. 547 // a decimal point or exponent.
524 if ('0' <= c0_ && c0_ <= '9') return Token::ILLEGAL; 548 if ('0' <= c0_ && c0_ <= '9') return Token::ILLEGAL;
525 } else { 549 } else {
526 if (c0_ < '1' || c0_ > '9') return Token::ILLEGAL; 550 if (c0_ < '1' || c0_ > '9') return Token::ILLEGAL;
527 do { 551 do {
528 AddLiteralCharAdvance(); 552 if (significant_digits < kMaxSignificantDigits) {
553 ASSERT(buffer_pos < kBufferSize);
554 buffer[buffer_pos++] = static_cast<char>(c0_);
555 significant_digits++;
556 i = i * 10 + c0_ - '0';
557 } else {
558 insignificant_digits++; // Move the digit into the exponential part.
559 nonzero_digit_dropped = nonzero_digit_dropped || c0_ != '0';
560 }
561 Advance();
562 } while (c0_ >= '0' && c0_ <= '9');
563 if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && significant_digits < 10) {
564 number = i;
565 return Token::NUMBER;
566 }
567 }
568 if (c0_ == '.') {
569 Advance();
570 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL;
571 if (significant_digits == 0) {
572 // Integer part consists of 0.
573 // Significant digits start after leading zero(s).
574 while (c0_ == '0') {
575 Advance();
576 exponent--; // Move this 0 into the exponent.
577 }
578 if (c0_ < '0' || c0_ > '9') {
579 number = 0.0;
580 return Token::NUMBER;
581 }
582 }
583 do {
584 if (significant_digits < kMaxSignificantDigits) {
585 ASSERT(buffer_pos < kBufferSize);
586 buffer[buffer_pos++] = static_cast<char>(c0_);
587 significant_digits++;
588 exponent--;
589 } else {
590 // Ignore insignificant digits in the fractional part.
591 nonzero_digit_dropped = nonzero_digit_dropped || c0_ != '0';
592 }
593 Advance();
529 } while (c0_ >= '0' && c0_ <= '9'); 594 } while (c0_ >= '0' && c0_ <= '9');
530 } 595 }
531 if (c0_ == '.') { 596 if (c0_ == 'e' || c0_ == 'E') {
532 AddLiteralCharAdvance(); 597 Advance();
598 bool expsign = (c0_ == '-');
599 if (expsign || c0_ == '+') Advance();
533 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL; 600 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL;
601 const int max_exponent = INT_MAX / 2;
602 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
603 int num = 0;
534 do { 604 do {
535 AddLiteralCharAdvance(); 605 // Check overflow.
606 int digit = c0_ - '0';
607 if (num >= max_exponent / 10
608 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
609 num = max_exponent;
610 } else {
611 num = num * 10 + digit;
612 }
613 Advance();
536 } while (c0_ >= '0' && c0_ <= '9'); 614 } while (c0_ >= '0' && c0_ <= '9');
615 exponent += (expsign ? -num : num);
537 } 616 }
538 if (AsciiAlphaToLower(c0_) == 'e') { 617
539 AddLiteralCharAdvance(); 618 exponent += insignificant_digits;
540 if (c0_ == '-' || c0_ == '+') AddLiteralCharAdvance(); 619 if (nonzero_digit_dropped) {
541 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL; 620 buffer[buffer_pos++] = '1';
542 do { 621 exponent--;
543 AddLiteralCharAdvance();
544 } while (c0_ >= '0' && c0_ <= '9');
545 } 622 }
546 literal.Complete(); 623 ASSERT(buffer_pos < kBufferSize);
624 buffer[buffer_pos] = '\0';
625 number = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
547 return Token::NUMBER; 626 return Token::NUMBER;
548 } 627 }
549 628
550 629
551 Token::Value JsonScanner::ScanJsonIdentifier(const char* text, 630 Token::Value JsonScanner::ScanJsonIdentifier(const char* text,
552 Token::Value token) { 631 Token::Value token) {
553 LiteralScope literal(this); 632 LiteralScope literal(this);
554 while (*text != '\0') { 633 while (*text != '\0') {
555 if (c0_ != *text) return Token::ILLEGAL; 634 if (c0_ != *text) return Token::ILLEGAL;
556 Advance(); 635 Advance();
557 text++; 636 text++;
558 } 637 }
559 if (ScannerConstants::kIsIdentifierPart.get(c0_)) return Token::ILLEGAL; 638 if (ScannerConstants::kIsIdentifierPart.get(c0_)) return Token::ILLEGAL;
560 literal.Complete(); 639 literal.Complete();
561 return token; 640 return token;
562 } 641 }
563 642
564 643
565 644
566 } } // namespace v8::internal 645 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/scanner.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698