Bug 899936 - OdinMonkey: fix faulty floating point logic in ExtractNumericLiteral (r=mjrosenb)

--HG--
extra : rebase_source : ff323d369202b5b7868165fec7128b934b2afac4
This commit is contained in:
Luke Wagner 2013-07-31 05:26:29 -05:00
parent b956389dc4
commit 9d925d954b
2 changed files with 30 additions and 7 deletions

View File

@ -36,6 +36,7 @@ using mozilla::AddToHash;
using mozilla::ArrayLength;
using mozilla::DebugOnly;
using mozilla::HashGeneric;
using mozilla::IsNaN;
using mozilla::IsNegativeZero;
using mozilla::Maybe;
using mozilla::Move;
@ -755,6 +756,10 @@ IsNumericLiteral(ParseNode *pn)
static NumLit
ExtractNumericLiteral(ParseNode *pn)
{
// The JS grammar treats -42 as -(42) (i.e., with separate grammar
// productions) for the unary - and literal 42). However, the asm.js spec
// recognizes -42 (modulo parens, so -(42) and -((42))) as a single literal
// so fold the two potential parse nodes into a single double value.
JS_ASSERT(IsNumericLiteral(pn));
ParseNode *numberNode;
double d;
@ -766,21 +771,33 @@ ExtractNumericLiteral(ParseNode *pn)
d = NumberNodeValue(numberNode);
}
// The asm.js spec syntactically distinguishes any literal containing a
// decimal point or the literal -0 as having double type.
if (NumberNodeHasFrac(numberNode) || IsNegativeZero(d))
return NumLit(NumLit::Double, DoubleValue(d));
int64_t i64 = int64_t(d);
// The syntactic checks above rule out these double values.
JS_ASSERT(!IsNegativeZero(d));
JS_ASSERT(!IsNaN(d));
// Although doubles can only *precisely* represent 53-bit integers, they
// can *imprecisely* represent integers much bigger than an int64_t.
// Furthermore, d may be inf or -inf. In both cases, casting to an int64_t
// is undefined, so test against the integer bounds using doubles.
if (d < double(INT32_MIN) || d > double(UINT32_MAX))
return NumLit(NumLit::OutOfRangeInt, UndefinedValue());
// With the above syntactic and range limitations, d is definitely an
// integer in the range [INT32_MIN, UINT32_MAX] range.
int64_t i64 = int64_t(d);
if (i64 >= 0) {
if (i64 <= INT32_MAX)
return NumLit(NumLit::Fixnum, Int32Value(i64));
if (i64 <= UINT32_MAX)
return NumLit(NumLit::BigUnsigned, Int32Value(uint32_t(i64)));
return NumLit(NumLit::OutOfRangeInt, UndefinedValue());
JS_ASSERT(i64 <= UINT32_MAX);
return NumLit(NumLit::BigUnsigned, Int32Value(uint32_t(i64)));
}
if (i64 >= INT32_MIN)
return NumLit(NumLit::NegativeInt, Int32Value(i64));
return NumLit(NumLit::OutOfRangeInt, UndefinedValue());
JS_ASSERT(i64 >= INT32_MIN);
return NumLit(NumLit::NegativeInt, Int32Value(i64));
}
static inline bool

View File

@ -19,6 +19,12 @@ assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 10.0 } function g()
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return -10.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), -10.0);
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1e10; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=9007199254740991e0; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=9007199254740992e0; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=9007199254740993e0; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=-9007199254740991e0; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=-9007199254740992e0; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=-9007199254740993e0; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1e100; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1e10000; j=i; return j|0 } return f");
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1000000000000000000; j=i; return j|0 } return f");