Bug 722788 - Use integer math to parse sufficiently-small decimal numbers in JSON text. r=waldo

--HG--
extra : rebase_source : 8bd72909ce94b65ce68b8cb3b64b42948fe24026
This commit is contained in:
Xin Zhang 2013-05-28 10:40:05 -07:00
Родитель c2b6007224
Коммит e893b8a32a
3 изменённых файлов: 38 добавлений и 1 удалений

Просмотреть файл

@ -174,6 +174,24 @@ ComputeAccurateBinaryBaseInteger(const jschar *start, const jschar *end, int bas
return value;
}
double
js::ParseDecimalNumber(const JS::TwoByteChars chars)
{
MOZ_ASSERT(chars.length() > 0);
uint64_t dec = 0;
RangedPtr<jschar> s = chars.start(), end = chars.end();
do {
jschar c = *s;
MOZ_ASSERT('0' <= c && c <= '9');
uint8_t digit = c - '0';
uint64_t next = dec * 10 + digit;
MOZ_ASSERT(next < DOUBLE_INTEGRAL_PRECISION_LIMIT,
"next value won't be an integrally-precise double");
dec = next;
} while (++s < end);
return static_cast<double>(dec);
}
bool
js::GetPrefixInteger(JSContext *cx, const jschar *start, const jschar *end, int base,
const jschar **endp, double *dp)

Просмотреть файл

@ -108,6 +108,15 @@ NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base = 10);
*/
const double DOUBLE_INTEGRAL_PRECISION_LIMIT = uint64_t(1) << 53;
/*
* Parse a decimal number encoded in |chars|. The decimal number must be
* sufficiently small that it will not overflow the integrally-precise range of
* the double type -- that is, the number will be smaller than
* DOUBLE_INTEGRAL_PRECISION_LIMIT
*/
extern double
ParseDecimalNumber(const JS::TwoByteChars chars);
/*
* Compute the positive integer of the given base described immediately at the
* start of the range [start, end) -- no whitespace-skipping, no magical

Просмотреть файл

@ -222,8 +222,18 @@ JSONParser::readNumber()
/* Fast path: no fractional or exponent part. */
if (current == end || (*current != '.' && *current != 'e' && *current != 'E')) {
const jschar *dummy;
TwoByteChars chars(digitStart.get(), current - digitStart);
if (chars.length() < strlen("9007199254740992")) {
// If the decimal number is shorter than the length of 2**53, (the
// largest number a double can represent with integral precision),
// parse it using a decimal-only parser. This comparison is
// conservative but faster than a fully-precise check.
double d = ParseDecimalNumber(chars);
return numberToken(negative ? -d : d);
}
double d;
const jschar *dummy;
if (!GetPrefixInteger(cx, digitStart.get(), current.get(), 10, &dummy, &d))
return token(OOM);
JS_ASSERT(current == dummy);