Bug 863045 - OdinMonkey: fix duplicate-evaluation in double-to-int coercion (r=sstangl)
authorLuke Wagner <luke@mozilla.com>
Wed, 17 Apr 2013 17:34:29 -0700
changeset 129220 5b25aba83eebfb933364249f0fcafdddd72f45a4
parent 129219 d061ec6e84511e6fdd0fc467b577765a0a6f9afe
child 129221 43987922a6b34b8ba4ab3c361a2a5f2bdd2c5e2f
push id24562
push userryanvm@gmail.com
push dateFri, 19 Apr 2013 01:24:04 +0000
treeherdermozilla-central@f8d27fe5d7c0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs863045
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 863045 - OdinMonkey: fix duplicate-evaluation in double-to-int coercion (r=sstangl)
js/src/ion/AsmJS.cpp
js/src/jit-test/tests/asm.js/testFloatingPoint.js
js/src/jit-test/tests/asm.js/testHeapAccess.js
--- a/js/src/ion/AsmJS.cpp
+++ b/js/src/ion/AsmJS.cpp
@@ -3491,33 +3491,48 @@ CheckNeg(FunctionCompiler &f, ParseNode 
         *type = Type::Double;
         return true;
     }
 
     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<MTruncateToInt32>(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<MTruncateToInt32>(operandDef);
-            *type = Type::Signed;
-            return true;
-        }
-    }
+    if (operand->isKind(PNK_BITNOT))
+        return CheckCoerceToInt(f, operand, def, type);
 
     MDefinition *operandDef;
     Type operandType;
     if (!CheckExpr(f, operand, Use::ToInt32, &operandDef, &operandType))
         return false;
 
     if (!operandType.isIntish())
         return f.fail("Operand to ~ must be intish", operand);
--- a/js/src/jit-test/tests/asm.js/testFloatingPoint.js
+++ b/js/src/jit-test/tests/asm.js/testFloatingPoint.js
@@ -3,16 +3,17 @@ load(libdir + "asm.js");
 assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 1.1 } return f"))(), 1.1);
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return +(+(i|0) + .1) } return f"))(1), 1.1);
 assertEq(asmLink(asmCompile(USE_ASM + "function f(d) { d=+d; return +d } 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.0, .1), 1.1);
 assertEq(asmLink(asmCompile(USE_ASM + "function f(i,e) { i=i|0;e=+e; return +(+~~i+e) } return f"))(1, .1), 1.1);
 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<e)|0 } return f"));
 assertEq(f(1.1, 2.2), 1);
 assertEq(f(1.1, 1.1), 0);
 assertEq(f(2.1, 1.1), 0);
 
 var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d<=e)|0 } return f"));
 assertEq(f(1.1, 2.2), 1);
@@ -104,16 +105,19 @@ f64[0] = Infinity;
 assertEq(f(), Infinity);
 f64[0] = -Infinity;
 assertEq(f(), -Infinity);
 
 function ffi(d) { str = String(d) }
 var g = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'var ffi=imp.ffi; function g() { ffi(+f64[0]) } return g'), this, {ffi:ffi}, buf);
 var h = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function g() { return +(+f64[0] < 0.0 ? -+f64[0] : +f64[0]) } return g'), this, null, buf)
 
+function ffi1() { return 2.6 }
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi1=imp.ffi1; function g() { var i=0,j=0.0; i=~~ffi1(); j=+ffi1(); return +(+(i|0)+j) } return g"), null, {ffi1:ffi1})(), 2+2.6);
+
 // that sounds dangerous!
 var a = [0,1,0xffff0000,0x7fff0000,0xfff80000,0x7ff80000,0xfffc0000,0x7ffc0000,0xffffffff,0x0000ffff,0x00008fff7];
 for (i of a) {
     for (j of a) {
         u32[0] = i;
         u32[1] = j;
 
         assertEq(f(), f64[0]);
--- a/js/src/jit-test/tests/asm.js/testHeapAccess.js
+++ b/js/src/jit-test/tests/asm.js/testHeapAccess.js
@@ -77,16 +77,28 @@ assertEq(f(0x100),0);
 
 var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i8[0] = i; return u8[0]|0}; return f');
 var f = asmLink(code, this, null, new ArrayBuffer(4096));
 assertEq(f(0),0);
 assertEq(f(0x7f),0x7f);
 assertEq(f(0xff),0xff);
 assertEq(f(0x100),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])|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;
 var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[((i<<2)+1)>>2]|0 }; return f'), this, null, i32.buffer);
 assertEq(f(0), 13);
 assertEq(f(1), 0xfffeeee);
 var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[((i<<2)+2)>>2]|0 }; return f'), this, null, i32.buffer);
 assertEq(f(0), 13);