From f64976e62d6a65e0e62e1f3e4780a8195fddbbeb Mon Sep 17 00:00:00 2001 From: "sandholm@chromium.org" Date: Mon, 7 Feb 2011 08:57:06 +0000 Subject: [PATCH] Improve ScanJsonNumber. Review URL: http://codereview.chromium.org/6334106 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6658 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/array.js | 8 +++-- src/conversions.cc | 78 +++++++++++++++++++--------------------------- src/parser.cc | 12 ++----- src/scanner.cc | 19 ++++++++++- src/scanner.h | 9 ++++++ 5 files changed, 67 insertions(+), 59 deletions(-) diff --git a/src/array.js b/src/array.js index a0e3e0bb4..1298434d5 100644 --- a/src/array.js +++ b/src/array.js @@ -1018,9 +1018,11 @@ function ArrayIndexOf(element, index) { } else { index = TO_INTEGER(index); // If index is negative, index from the end of the array. - if (index < 0) index = length + index; - // If index is still negative, search the entire array. - if (index < 0) index = 0; + if (index < 0) { + index = length + index; + // If index is still negative, search the entire array. + if (index < 0) index = 0; + } } var min = index; var max = length; diff --git a/src/conversions.cc b/src/conversions.cc index a954d6cc6..a348235d6 100644 --- a/src/conversions.cc +++ b/src/conversions.cc @@ -125,8 +125,8 @@ static bool isDigit(int x, int radix) { } -static double SignedZero(bool sign) { - return sign ? -0.0 : 0.0; +static double SignedZero(bool negative) { + return negative ? -0.0 : 0.0; } @@ -134,14 +134,14 @@ static double SignedZero(bool sign) { template static double InternalStringToIntDouble(Iterator current, EndMark end, - bool sign, + bool negative, bool allow_trailing_junk) { ASSERT(current != end); // Skip leading 0s. while (*current == '0') { ++current; - if (current == end) return SignedZero(sign); + if (current == end) return SignedZero(negative); } int64_t number = 0; @@ -217,7 +217,7 @@ static double InternalStringToIntDouble(Iterator current, ASSERT(static_cast(static_cast(number)) == number); if (exponent == 0) { - if (sign) { + if (negative) { if (number == 0) return -0.0; number = -number; } @@ -227,7 +227,7 @@ static double InternalStringToIntDouble(Iterator current, ASSERT(number != 0); // The double could be constructed faster from number (mantissa), exponent // and sign. Assuming it's a rare case more simple code is used. - return static_cast(sign ? -number : number) * pow(2.0, exponent); + return static_cast(negative ? -number : number) * pow(2.0, exponent); } @@ -238,7 +238,7 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) { if (!AdvanceToNonspace(¤t, end)) return empty_string_val; - bool sign = false; + bool negative = false; bool leading_zero = false; if (*current == '+') { @@ -248,14 +248,14 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) { } else if (*current == '-') { ++current; if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; - sign = true; + negative = true; } if (radix == 0) { // Radix detection. if (*current == '0') { ++current; - if (current == end) return SignedZero(sign); + if (current == end) return SignedZero(negative); if (*current == 'x' || *current == 'X') { radix = 16; ++current; @@ -271,7 +271,7 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) { if (*current == '0') { // Allow "0x" prefix. ++current; - if (current == end) return SignedZero(sign); + if (current == end) return SignedZero(negative); if (*current == 'x' || *current == 'X') { ++current; if (current == end) return JUNK_STRING_VALUE; @@ -287,7 +287,7 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) { while (*current == '0') { leading_zero = true; ++current; - if (current == end) return SignedZero(sign); + if (current == end) return SignedZero(negative); } if (!leading_zero && !isDigit(*current, radix)) { @@ -298,21 +298,21 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) { switch (radix) { case 2: return InternalStringToIntDouble<1>( - current, end, sign, allow_trailing_junk); + current, end, negative, allow_trailing_junk); case 4: return InternalStringToIntDouble<2>( - current, end, sign, allow_trailing_junk); + current, end, negative, allow_trailing_junk); case 8: return InternalStringToIntDouble<3>( - current, end, sign, allow_trailing_junk); + current, end, negative, allow_trailing_junk); case 16: return InternalStringToIntDouble<4>( - current, end, sign, allow_trailing_junk); + current, end, negative, allow_trailing_junk); case 32: return InternalStringToIntDouble<5>( - current, end, sign, allow_trailing_junk); + current, end, negative, allow_trailing_junk); default: UNREACHABLE(); } @@ -344,7 +344,7 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) { ASSERT(buffer_pos < kBufferSize); buffer[buffer_pos] = '\0'; Vector buffer_vector(buffer, buffer_pos); - return sign ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0); + return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0); } // The following code causes accumulating rounding error for numbers greater @@ -406,7 +406,7 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) { return JUNK_STRING_VALUE; } - return sign ? -v : v; + return negative ? -v : v; } @@ -445,7 +445,7 @@ static double InternalStringToDouble(Iterator current, bool nonzero_digit_dropped = false; bool fractional_part = false; - bool sign = false; + bool negative = false; if (*current == '+') { // Ignore leading sign. @@ -454,7 +454,7 @@ static double InternalStringToDouble(Iterator current, } else if (*current == '-') { ++current; if (current == end) return JUNK_STRING_VALUE; - sign = true; + negative = true; } static const char kInfinitySymbol[] = "Infinity"; @@ -468,13 +468,13 @@ static double InternalStringToDouble(Iterator current, } ASSERT(buffer_pos == 0); - return sign ? -V8_INFINITY : V8_INFINITY; + return negative ? -V8_INFINITY : V8_INFINITY; } bool leading_zero = false; if (*current == '0') { ++current; - if (current == end) return SignedZero(sign); + if (current == end) return SignedZero(negative); leading_zero = true; @@ -487,14 +487,14 @@ static double InternalStringToDouble(Iterator current, return InternalStringToIntDouble<4>(current, end, - sign, + negative, allow_trailing_junk); } // Ignore leading zeros in the integer part. while (*current == '0') { ++current; - if (current == end) return SignedZero(sign); + if (current == end) return SignedZero(negative); } } @@ -539,7 +539,7 @@ static double InternalStringToDouble(Iterator current, // leading zeros (if any). while (*current == '0') { ++current; - if (current == end) return SignedZero(sign); + if (current == end) return SignedZero(negative); exponent--; // Move this 0 into the exponent. } } @@ -631,7 +631,7 @@ static double InternalStringToDouble(Iterator current, if (octal) { return InternalStringToIntDouble<3>(buffer, buffer + buffer_pos, - sign, + negative, allow_trailing_junk); } @@ -644,7 +644,7 @@ static double InternalStringToDouble(Iterator current, buffer[buffer_pos] = '\0'; double converted = Strtod(Vector(buffer, buffer_pos), exponent); - return sign ? -converted : converted; + return negative ? -converted : converted; } @@ -702,26 +702,12 @@ double StringToDouble(Vector str, const char* DoubleToCString(double v, Vector buffer) { - StringBuilder builder(buffer.start(), buffer.length()); - switch (fpclassify(v)) { - case FP_NAN: - builder.AddString("NaN"); - break; - - case FP_INFINITE: - if (v < 0.0) { - builder.AddString("-Infinity"); - } else { - builder.AddString("Infinity"); - } - break; - - case FP_ZERO: - builder.AddCharacter('0'); - break; - + case FP_NAN: return "NaN"; + case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity"); + case FP_ZERO: return "0"; default: { + StringBuilder builder(buffer.start(), buffer.length()); int decimal_point; int sign; const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1; @@ -764,9 +750,9 @@ const char* DoubleToCString(double v, Vector buffer) { if (exponent < 0) exponent = -exponent; builder.AddFormatted("%d", exponent); } + return builder.Finalize(); } } - return builder.Finalize(); } diff --git a/src/parser.cc b/src/parser.cc index e495017b5..5353a6346 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -4013,16 +4013,10 @@ Handle JsonParser::GetString() { Handle JsonParser::ParseJsonValue() { Token::Value token = scanner_.Next(); switch (token) { - case Token::STRING: { + case Token::STRING: return GetString(); - } - case Token::NUMBER: { - ASSERT(scanner_.is_literal_ascii()); - double value = StringToDouble(scanner_.literal_ascii_string(), - NO_FLAGS, // Hex, octal or trailing junk. - OS::nan_value()); - return Factory::NewNumber(value); - } + case Token::NUMBER: + return Factory::NewNumber(scanner_.number()); case Token::FALSE_LITERAL: return Factory::false_value(); case Token::TRUE_LITERAL: diff --git a/src/scanner.cc b/src/scanner.cc index b66d10b98..cab8c58bd 100755 --- a/src/scanner.cc +++ b/src/scanner.cc @@ -516,17 +516,30 @@ Token::Value JsonScanner::ScanJsonString() { Token::Value JsonScanner::ScanJsonNumber() { LiteralScope literal(this); - if (c0_ == '-') AddLiteralCharAdvance(); + bool negative = false; + + if (c0_ == '-') { + AddLiteralCharAdvance(); + negative = true; + } if (c0_ == '0') { AddLiteralCharAdvance(); // Prefix zero is only allowed if it's the only digit before // a decimal point or exponent. if ('0' <= c0_ && c0_ <= '9') return Token::ILLEGAL; } else { + int i = 0; + int digits = 0; if (c0_ < '1' || c0_ > '9') return Token::ILLEGAL; do { + i = i * 10 + c0_ - '0'; + digits++; AddLiteralCharAdvance(); } while (c0_ >= '0' && c0_ <= '9'); + if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) { + number_ = (negative ? -i : i); + return Token::NUMBER; + } } if (c0_ == '.') { AddLiteralCharAdvance(); @@ -544,6 +557,10 @@ Token::Value JsonScanner::ScanJsonNumber() { } while (c0_ >= '0' && c0_ <= '9'); } literal.Complete(); + ASSERT_NOT_NULL(next_.literal_chars); + number_ = StringToDouble(next_.literal_chars->ascii_literal(), + NO_FLAGS, // Hex, octal or trailing junk. + OS::nan_value()); return Token::NUMBER; } diff --git a/src/scanner.h b/src/scanner.h index d7621825a..cf2084f55 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -148,6 +148,12 @@ class JsonScanner : public Scanner { // Returns the next token. Token::Value Next(); + // Returns the value of a number token. + double number() { + return number_; + } + + protected: // Skip past JSON whitespace (only space, tab, newline and carrige-return). bool SkipJsonWhiteSpace(); @@ -178,6 +184,9 @@ class JsonScanner : public Scanner { // are the only valid JSON identifiers (productions JSONBooleanLiteral, // JSONNullLiteral). Token::Value ScanJsonIdentifier(const char* text, Token::Value token); + + // Holds the value of a scanned number token. + double number_; }; } } // namespace v8::internal -- 2.34.1