From c7bbea87f216b4128aa9ae6391e6739e8d158b47 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Wed, 17 Apr 2013 17:34:29 -0700 Subject: [PATCH] Bug 863045 - OdinMonkey: fix duplicate-evaluation in double-to-int coercion (r=sstangl) --HG-- extra : rebase_source : b6c832b6a2a5a1f25c137ca7e276316b85ff3650 --- js/src/ion/AsmJS.cpp | 39 +++++++++++++------ .../tests/asm.js/testFloatingPoint.js | 4 ++ .../jit-test/tests/asm.js/testHeapAccess.js | 12 ++++++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index de45a28ed71..eb553bd244e 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -3495,24 +3495,39 @@ CheckNeg(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type) return f.fail("Operand to unary - must be an int", operand); } +static bool +CheckCoerceToInt(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type) +{ + JS_ASSERT(expr->isKind(PNK_BITNOT)); + ParseNode *operand = UnaryKid(expr); + + MDefinition *operandDef; + Type operandType; + if (!CheckExpr(f, operand, Use::ToInt32, &operandDef, &operandType)) + return false; + + if (operandType.isDoublish()) { + *def = f.unary(operandDef); + *type = Type::Signed; + return true; + } + + if (!operandType.isIntish()) + return f.fail("Operand to ~ must be intish or doublish", operand); + + *def = operandDef; + *type = Type::Signed; + return true; +} + static bool CheckBitNot(FunctionCompiler &f, ParseNode *neg, MDefinition **def, Type *type) { JS_ASSERT(neg->isKind(PNK_BITNOT)); ParseNode *operand = UnaryKid(neg); - if (operand->isKind(PNK_BITNOT)) { - MDefinition *operandDef; - Type operandType; - if (!CheckExpr(f, UnaryKid(operand), Use::NoCoercion, &operandDef, &operandType)) - return false; - - if (operandType.isDouble()) { - *def = f.unary(operandDef); - *type = Type::Signed; - return true; - } - } + if (operand->isKind(PNK_BITNOT)) + return CheckCoerceToInt(f, operand, def, type); MDefinition *operandDef; Type operandType; diff --git a/js/src/jit-test/tests/asm.js/testFloatingPoint.js b/js/src/jit-test/tests/asm.js/testFloatingPoint.js index 56c5b83f832..b9a1fab188e 100644 --- a/js/src/jit-test/tests/asm.js/testFloatingPoint.js +++ b/js/src/jit-test/tests/asm.js/testFloatingPoint.js @@ -8,6 +8,7 @@ assertEq(asmLink(asmCompile(USE_ASM + "function f(i,e) { i=i|0;e=+e; return +(+~ assertEq(asmLink(asmCompile(USE_ASM + "function f(d,i) { d=+d;i=i|0; return +(d + +(i|0)) } return f"))(.1, 1), 1.1); assertEq(asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d-e) } return f"))(1.1, .8), (1.1-.8)); assertEq(asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d*e) } return f"))(1.1, 2.2), (1.1*2.2)); +assertEq(asmLink(asmCompile(USE_ASM + "function g() { var i=2; return (~~(i=(i+1)|0))|0 } return g"))(), 3); var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d>3] = j; return (~~f64[i>>3])|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(4096)); +assertEq(f(0, 1.3), 1); +assertEq(f(4088, 2.5), 2); +assertEq(f(4096, 3.8), 0); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=+j; f64[i>>3] = j; return +f64[i>>3]}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(4096)); +assertEq(f(0, 1.3), 1.3); +assertEq(f(4088, 2.5), 2.5); +assertEq(f(4096, 3.8), NaN); + var i32 = new Int32Array(4096/4); i32[0] = 13; i32[1] = 0xfffeeee;