diff options
Diffstat (limited to 'js/src/jit-test/tests/asm.js')
105 files changed, 14934 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/asm.js/bug1007512.js b/js/src/jit-test/tests/asm.js/bug1007512.js new file mode 100644 index 000000000..657fed621 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1007512.js @@ -0,0 +1,8 @@ +// |jit-test| error: TypeError + +new(function(stdlib, n, heap) { + "use asm" + var x = new stdlib.Uint32Array(heap) + function f() {} + return f +}) diff --git a/js/src/jit-test/tests/asm.js/bug1008636.js b/js/src/jit-test/tests/asm.js/bug1008636.js new file mode 100644 index 000000000..03e52e9b1 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1008636.js @@ -0,0 +1,12 @@ +// |jit-test| error:TypeError +// stdlib is undefined + +(function(stdlib, n, heap) { + "use asm" + var Int16ArrayView = new stdlib.Int16Array(heap) + function f() { + var x = 4. + Int16ArrayView[~~((1 ? .0 : .9) % x) >> 1] = 0 + u(x) + } +})() diff --git a/js/src/jit-test/tests/asm.js/bug1126251.js b/js/src/jit-test/tests/asm.js/bug1126251.js new file mode 100644 index 000000000..8470a9772 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1126251.js @@ -0,0 +1,53 @@ +load(libdir + "asm.js"); + +// Bug 1126251 +var v = asmLink(asmCompile('global', ` + "use asm"; + var frd = global.Math.fround; + function e() { + var x = frd(.1e+71); + x = frd(x / x); + return +x; + } + return e; +`), this)(); + +assertEq(v, NaN); + +if (!isSimdAvailable() || typeof SIMD === 'undefined') { + quit(0); +} + +var v = asmLink(asmCompile('global', ` + "use asm"; + var frd = global.Math.fround; + var Float32x4 = global.SIMD.Float32x4; + var splat = Float32x4.splat; + var ext = Float32x4.extractLane; + function e() { + var v = Float32x4(0,0,0,0); + var x = frd(0.); + v = splat(.1e+71); + x = ext(v,0); + x = frd(x / x); + return +x; + } + return e; +`), this)(); + +assertEq(v, NaN); + +// Bug 1130618: without GVN +setJitCompilerOption("ion.gvn.enable", 0); +var v = asmLink(asmCompile('global', ` + "use asm"; + var Float32x4 = global.SIMD.Float32x4; + var splat = Float32x4.splat; + var ext = Float32x4.extractLane; + function e() { + return +ext(splat(.1e+71),0); + } + return e; +`), this)(); + +assertEq(v, Infinity); diff --git a/js/src/jit-test/tests/asm.js/bug1161298.js b/js/src/jit-test/tests/asm.js/bug1161298.js new file mode 100644 index 000000000..604184915 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1161298.js @@ -0,0 +1,13 @@ +// The length exceeds INT32_MAX and should be rejected. + +if (!this.SharedArrayBuffer) + quit(0); + +var failed = false; +try { + var sab = new SharedArrayBuffer((2147483648)); +} +catch (e) { + failed = true; +} +assertEq(failed, true); diff --git a/js/src/jit-test/tests/asm.js/bug1174372.js b/js/src/jit-test/tests/asm.js/bug1174372.js new file mode 100644 index 000000000..e7031ea10 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1174372.js @@ -0,0 +1,6 @@ +// |jit-test| --no-baseline; --non-writable-jitcode +(function(stdlib, foreign, heap) { + "use asm"; + function f() {} + return f; +})(); diff --git a/js/src/jit-test/tests/asm.js/bug1201124-simd-proxy.js b/js/src/jit-test/tests/asm.js/bug1201124-simd-proxy.js new file mode 100644 index 000000000..edcc069ff --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1201124-simd-proxy.js @@ -0,0 +1,28 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +if (typeof newGlobal !== 'function' || + !isSimdAvailable() || + typeof SIMD === 'undefined') +{ + quit(); +} + +var stdlib = new (newGlobal().Proxy)(this, new Proxy({ + simdGet: 0, + getOwnPropertyDescriptor(t, pk) { + if (pk === "SIMD" && this.simdGet++ === 1) { + return {}; + } + return Reflect.getOwnPropertyDescriptor(t, pk); + } +}, { + get(t, pk, r) { + print("trap", pk); + return Reflect.get(t, pk, r); + } +})); + +var m = asmCompile('stdlib', '"use asm"; var i4=stdlib.SIMD.Int32x4; var i4add=i4.add; return {}'); + +assertAsmLinkFail(m, stdlib); diff --git a/js/src/jit-test/tests/asm.js/bug1219954.js b/js/src/jit-test/tests/asm.js/bug1219954.js new file mode 100644 index 000000000..041c6fe35 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1219954.js @@ -0,0 +1,13 @@ +// |jit-test| slow +"use strict"; + +if (!('oomTest' in this)) + quit(); + +let g = (function() { + "use asm"; + function f() {} + return f; +})(); + +oomTest(() => "" + g); diff --git a/js/src/jit-test/tests/asm.js/bug1268955-usestrict-semantics.js b/js/src/jit-test/tests/asm.js/bug1268955-usestrict-semantics.js new file mode 100644 index 000000000..501c4392d --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1268955-usestrict-semantics.js @@ -0,0 +1,19 @@ + +var scope = {}; +scope.mod = eval(`"use strict"; (function() { "use asm"; function f() {} return f; });`); + +scope.fun = scope.mod(); + +var caught = false; +for (let callee of ['mod', 'fun']) { + for (let getter of ['caller', 'arguments']) { + caught = false; + try { + scope[callee][getter]; + } catch (e) { + caught = true; + assertEq(e instanceof TypeError, true); + } + assertEq(caught, true); + } +} diff --git a/js/src/jit-test/tests/asm.js/bug1276028.js b/js/src/jit-test/tests/asm.js/bug1276028.js new file mode 100644 index 000000000..16f564060 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1276028.js @@ -0,0 +1,6 @@ +load(libdir + "asm.js"); + +var f = asmLink(asmCompile(USE_ASM + "function a234567() { return 42 } return a234567")); +assertEq(f(), 42); +enableSPSProfiling(); +assertEq(f(), 42); diff --git a/js/src/jit-test/tests/asm.js/bug1306506.js b/js/src/jit-test/tests/asm.js/bug1306506.js new file mode 100644 index 000000000..69cfc7b0e --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug1306506.js @@ -0,0 +1,7 @@ +f = (function(stdlib, foreign, heap) { + "use asm"; + function f() { + return (1, 1 / 0)|0; + } + return f; +}); diff --git a/js/src/jit-test/tests/asm.js/bug855526.js b/js/src/jit-test/tests/asm.js/bug855526.js new file mode 100644 index 000000000..fd75b137d --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug855526.js @@ -0,0 +1,13 @@ +// Don't assert. +try { + eval('\ + function asmModule(g, foreign, heap) {\ + "use asm";\ + let HEAP8 = new g.Int8Array(heap);\ + function f() { return 17; } \ + return {f: f};\ + }\ + let m = asmModule("", "", 1, "");\ + '); +} catch (ex) { +} diff --git a/js/src/jit-test/tests/asm.js/bug885976.js b/js/src/jit-test/tests/asm.js/bug885976.js new file mode 100644 index 000000000..303a8d07f --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug885976.js @@ -0,0 +1,12 @@ +// |jit-test| error: TypeError +function test(stdlib, foreign) { + "use asm" + var ff = foreign.ff + function f(y) { + y = +y; + ff(0); + } + return f; +}; +f = test(this, {ff: Object.defineProperty}); +f(); diff --git a/js/src/jit-test/tests/asm.js/bug923867.js b/js/src/jit-test/tests/asm.js/bug923867.js new file mode 100644 index 000000000..59bd296b8 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug923867.js @@ -0,0 +1,8 @@ +(function(a) { + "use asm" + var Infinity = a.Infinity + function f() { + Infinity - (2 ? (1. / .0) : +0) + } + return f +})(this)() diff --git a/js/src/jit-test/tests/asm.js/bug927389.js b/js/src/jit-test/tests/asm.js/bug927389.js new file mode 100644 index 000000000..ad2ea74d7 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug927389.js @@ -0,0 +1,6 @@ +(function() { + "use asm" + function f() { + +~~1.1 + } +})() diff --git a/js/src/jit-test/tests/asm.js/bug928450.js b/js/src/jit-test/tests/asm.js/bug928450.js new file mode 100644 index 000000000..a12036735 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug928450.js @@ -0,0 +1,18 @@ +(function() { + "use asm"; + function f() { + i((1.5 != 2.) ? 3 : 0); + } + return f; +})(); + +// Bug 933104 +(function() { + "use asm"; + function f(x) { + x = +x; + x = -2.; + (x > -1.5) ? 0 : 0; + } + return f; +})() diff --git a/js/src/jit-test/tests/asm.js/bug940864.js b/js/src/jit-test/tests/asm.js/bug940864.js new file mode 100644 index 000000000..4df37bb40 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug940864.js @@ -0,0 +1,10 @@ +function a() +{ + "use asm"; + function f() + { + return (((((-1) >>> (0+0)) | 0) % 10000) >> (0+0)) | 0; + } + return f; +} +assertEq(a()(), -1); diff --git a/js/src/jit-test/tests/asm.js/bug941877.js b/js/src/jit-test/tests/asm.js/bug941877.js new file mode 100644 index 000000000..c2033cf8d --- /dev/null +++ b/js/src/jit-test/tests/asm.js/bug941877.js @@ -0,0 +1,164 @@ +load(libdir + "asm.js"); + +function FunctionBody(f) { + var str = f.toString(); + var firstBrace = str.indexOf('{'); + var lastBrace = str.lastIndexOf('}'); + return str.substr(firstBrace + 1, lastBrace - firstBrace - 1); +} + +var F = (function (stdlib, n, heap) { + var Int16ArrayView = new stdlib.Int16Array(heap); + function f(i0, d1) { + i0 = i0 | 0 + d1 = +d1 + var d2 = 1. + var i3 = 0 + Int16ArrayView[0] = i0 + d2 = (.0 / .0) + switch ((i0 + i0) | 0) { + case 0: + d2 = .0 + break + }; + (((i3 - (0 < 0)) >>> ((.0 < -0) + (.0 > .0))) / 0) >> (0 + (((0 + 0) ^ +(9 > 0)) | 0)) + } + return f; +}); + +var compiled = asmCompile('stdlib', 'n', 'heap', USE_ASM + FunctionBody(F)); +asmLink(compiled, this, null, new ArrayBuffer(BUF_MIN))(); + +var F = (function(stdlib, n, heap) { + var Float64ArrayView = new stdlib.Float64Array(heap) + function f() { + Float64ArrayView[0] = +(0xffffffff / 0xffffffff >> 0) + } + return f; +}); + +var compiled = asmCompile('stdlib', 'n', 'heap', USE_ASM + FunctionBody(F)); +asmLink(compiled, this, null, new ArrayBuffer(BUF_MIN))(); + +function test0(x) +{ + return (x >>> 0) % 10; +} +assertEq(test0(25), 5); +assertEq(test0(24), 4); +assertEq(test0(23), 3); +assertEq(test0(0), 0); +assertEq(test0(4294967295), 5); + +function test1(x) +{ + return (x >>> 2) % 10; +} +assertEq(test1(25), 6); +assertEq(test1(24), 6); +assertEq(test1(23), 5); +assertEq(test1(4294967295), 3); + +function test2(x, y) +{ + return (x >>> 0) % (y >>> 0); +} +assertEq(test2(25, 3), 1); +assertEq(test2(24, 4), 0); +assertEq(test2(4294967295, 10), 5); +assertEq(test2(23, 0), NaN); + +function test3() +{ + function f(x, y) + { + x = x|0; + y = y|0; + var t = 0; + t = (((x|0) % (y|0))|0) > -2; + return t|0; + } + return f; +} +var compiled = asmCompile(USE_ASM + FunctionBody(test3)); +var linked = asmLink(compiled); +assertEq(linked(4294967290, 4294967295), 1); +assertEq(linked(4294967290, 4294967295), 1); + +function test4() +{ + function f(x, y) + { + x = x|0; + y = y|0; + var t = 0; + t = (((x>>>0) % (y>>>0)) >>> 0) > 0; + return t|0; + } + return f; +} +var compiled = asmCompile(USE_ASM + FunctionBody(test4)); +var linked = asmLink(compiled); +assertEq(linked(4294967290, 4294967295), 1); +assertEq(linked(4294967290, 4294967295), 1); + +function test5() +{ + function f(x, y) + { + x = x|0; + y = y|0; + var t = 0.; + t = +(((x>>>0) % (y>>>0)) >>> 0) * 1.01; + return +t; + } + return f; +} +var compiled = asmCompile(USE_ASM + FunctionBody(test5)); +var linked = asmLink(compiled); +assertEq(linked(4294967290, 4294967295), 4337916962.9); +assertEq(linked(4294967290, 4294967295), 4337916962.9); + +function test6() +{ + function f(x, y) + { + x = x|0; + y = y|0; + return ((x>>>1) % (y>>>1))|0; + } + return f; +} +var compiled = asmCompile(USE_ASM + FunctionBody(test6)); +var linked = asmLink(compiled); +assertEq(linked(23847, 7), 1); +assertEq(linked(23848, 7), 2); + +function test7() +{ + function f(x) + { + x = x|0; + return ((x>>>0) / 8)|0; + } + return f; +} +var compiled = asmCompile(USE_ASM + FunctionBody(test7)); +var linked = asmLink(compiled); +assertEq(linked(23847, 7), 2980); +assertEq(linked(23848, 7), 2981); + +function test8() +{ + function f(i,j) + { + i=i|0;j=j|0; + return ((i>>>0)/(j>>>0))|0; + } + return f; +} +var compiled = asmCompile(USE_ASM + FunctionBody(test8)); +var linked = asmLink(compiled); +assertEq(linked(2147483647, 0), 0); +assertEq(linked(2147483646, 0), 0); diff --git a/js/src/jit-test/tests/asm.js/directives.txt b/js/src/jit-test/tests/asm.js/directives.txt new file mode 100644 index 000000000..bdc583321 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/directives.txt @@ -0,0 +1 @@ +|jit-test| test-also-noasmjs; test-also-wasm-baseline diff --git a/js/src/jit-test/tests/asm.js/gating.js b/js/src/jit-test/tests/asm.js/gating.js new file mode 100644 index 000000000..8c2168fb6 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/gating.js @@ -0,0 +1,79 @@ +// Check gating of shared memory features in asm.js (bug 1171540, +// bug 1231624, bug 1231338, bug 1231335). +// +// In asm.js, importing any atomic is a signal that shared memory is +// being used. If an atomic is imported, and if shared memory is +// disabled in the build or in the run then an error should be +// signaled for the module. +// +// We check these constraints during linking: the linker checks that +// the buffer has the right type and that the Atomics - if used - have +// their expected values; if shared memory is disabled then the +// Atomics object will be absent from the global or it will have +// values that are not the expected built-in values and the link will +// fail as desired. + +load(libdir + "asm.js"); + +if (!isAsmJSCompilationAvailable()) + quit(0); + +setJitCompilerOption('asmjs.atomics.enable', 1); + +if (!this.Atomics) { + this.Atomics = { load: function (x, y) { return 0 }, + store: function (x, y, z) { return 0 }, + exchange: function (x, y, z) { return 0 }, + add: function (x, y, z) { return 0 }, + sub: function (x, y, z) { return 0 }, + and: function (x, y, z) { return 0 }, + or: function (x, y, z) { return 0 }, + xor: function (x, y, z) { return 0 }, + compareExchange: function (x, y, z, w) { return 0 } + }; +} + + +var module_a = asmCompile("stdlib", "foreign", "heap", ` + "use asm"; + + var ld = stdlib.Atomics.load; + + function f() { return 0; } + return { f:f }; +`); + +var module_b = asmCompile("stdlib", "foreign", "heap", ` + "use asm"; + + var ld = stdlib.Atomics.load; + var i32a = new stdlib.Int32Array(heap); + + function f() { return 0; } + return { f:f }; +`); + +var module_c = asmCompile("stdlib", "foreign", "heap", ` + "use asm"; + + var i32a = new stdlib.Int32Array(heap); + + function f() { return 0; } + return { f:f }; +`); + +assertEq(isAsmJSModule(module_a), true); +assertEq(isAsmJSModule(module_b), true); +assertEq(isAsmJSModule(module_c), true); + +if (!this.SharedArrayBuffer) { + assertAsmLinkFail(module_a, this, {}, new ArrayBuffer(65536)); // Buffer is ignored, Atomics are bad +} else { + asmLink(module_a, this, {}, new ArrayBuffer(65536)); // Buffer is ignored, Atomics are good + assertAsmLinkFail(module_b, this, {}, new ArrayBuffer(65536)); // Buffer is wrong type +} + +asmLink(module_c, this, {}, new ArrayBuffer(65536)); // Buffer is right type + +if (this.SharedArrayBuffer) + assertAsmLinkFail(module_c, this, {}, new SharedArrayBuffer(65536)); // Buffer is wrong type diff --git a/js/src/jit-test/tests/asm.js/neuter-during-arguments-coercion.js b/js/src/jit-test/tests/asm.js/neuter-during-arguments-coercion.js new file mode 100644 index 000000000..bfe8913e7 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/neuter-during-arguments-coercion.js @@ -0,0 +1,27 @@ +load(libdir + "asm.js"); + +function f(stdlib, foreign, buffer) +{ + "use asm"; + var i32 = new stdlib.Int32Array(buffer); + function set(v) + { + v=v|0; + i32[5] = v; + } + return set; +} +if (isAsmJSCompilationAvailable()) + assertEq(isAsmJSModule(f), true); + +var i32 = new Int32Array(65536); +var buffer = i32.buffer; +var set = f(this, null, buffer); +if (isAsmJSCompilationAvailable()) + assertEq(isAsmJSFunction(set), true); + +try +{ + set({ valueOf() { detachArrayBuffer(buffer); return 17; } }); +} +catch (e) { /* if an exception thrown, swallow */ } diff --git a/js/src/jit-test/tests/asm.js/oom-helper-thread-plus-validation-error.js b/js/src/jit-test/tests/asm.js/oom-helper-thread-plus-validation-error.js new file mode 100644 index 000000000..272337823 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/oom-helper-thread-plus-validation-error.js @@ -0,0 +1,11 @@ +if (typeof oomAfterAllocations !== 'function' || typeof evaluate !== 'function') + quit(); + +oomAfterAllocations(10, 2); +evaluate(`function mod(stdlib, ffi, heap) { + "use asm"; + function f3(k) { + k = k | 0; + } + function g3(k) {} +}`); diff --git a/js/src/jit-test/tests/asm.js/oom-helper-thread.js b/js/src/jit-test/tests/asm.js/oom-helper-thread.js new file mode 100644 index 000000000..bb1550ba1 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/oom-helper-thread.js @@ -0,0 +1,8 @@ +// |jit-test| exitstatus: 3 + +if (typeof oomAfterAllocations !== 'function') { + quit(3); +} + +oomAfterAllocations(50, 2); +eval("(function() {'use asm'; function f() { return +pow(.0, .0) })") diff --git a/js/src/jit-test/tests/asm.js/simd-fbirds.js b/js/src/jit-test/tests/asm.js/simd-fbirds.js new file mode 100644 index 000000000..97b7e2974 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/simd-fbirds.js @@ -0,0 +1,198 @@ +/* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ; js-indent-level : 2 ; js-curly-indent-offset: 0 -*- */ +/* vim: set ts=4 et sw=4 tw=80: */ + +// Author: Peter Jensen + +load(libdir + "asm.js"); +if (!isSimdAvailable() || typeof SIMD === 'undefined') { + print("won't run tests as simd extensions aren't activated yet"); + quit(0); +} + +const NUM_BIRDS = 30; +const NUM_UPDATES = 20; +const ACCEL_DATA_STEPS = 30; + +var buffer = new ArrayBuffer(0x200000); +var bufferF32 = new Float32Array(buffer); + +var actualBirds = 0; + +function init() { + actualBirds = 0; + // Make it a power of two, for quick modulo wrapping. + var accelDataValues = [10.0, 9.5, 9.0, 8.0, 7.0, 6.0, 5.5, 5.0, 5.0, 5.0, 5.5, 6.0, 7.0, 8.0, 9.0, 10.0]; + accelDataValues = accelDataValues.map(function(v) { return 50*v; }); + var accelDataValuesLength = accelDataValues.length; + assertEq(accelDataValuesLength, 16); // Hard coded in the asm.js module + for (i = 0; i < accelDataValuesLength; i++) + bufferF32[i + NUM_BIRDS * 2] = accelDataValues[i]; +} + +function addBird(pos, vel) { + bufferF32[actualBirds] = pos; + bufferF32[actualBirds + NUM_BIRDS] = vel; + actualBirds++; + return actualBirds - 1; +} + +function getActualBirds() { + return actualBirds; +} + +var code = ` + "use asm"; + var toF = global.Math.fround; + var u8 = new global.Uint8Array(buffer); + var f32 = new global.Float32Array(buffer); + const maxBirds = 100000; + const maxBirdsx4 = 400000; + const maxBirdsx8 = 800000; + const accelMask = 0x3c; + const mk4 = 0x000ffff0; + + const getMaxPos = 1000.0; + const getAccelDataSteps = imp.accelDataSteps | 0; + var getActualBirds = imp.getActualBirds; + + var i4 = global.SIMD.Int32x4; + var f4 = global.SIMD.Float32x4; + var b4 = global.SIMD.Bool32x4; + var i4add = i4.add; + var i4and = i4.and; + var f4select = f4.select; + var f4add = f4.add; + var f4sub = f4.sub; + var f4mul = f4.mul; + var f4greaterThan = f4.greaterThan; + var f4splat = f4.splat; + var f4load = f4.load; + var f4store = f4.store; + var b4any = b4.anyTrue; + + const zerox4 = f4(0.0,0.0,0.0,0.0); + + function declareHeapSize() { + f32[0x0007ffff] = toF(0.0); + } + + function update(timeDelta) { + timeDelta = toF(timeDelta); + // var steps = Math.ceil(timeDelta/accelData.interval); + var steps = 0; + var subTimeDelta = toF(0.0); + var actualBirds = 0; + var maxPos = toF(0.0); + var maxPosx4 = f4(0.0,0.0,0.0,0.0); + var subTimeDeltax4 = f4(0.0,0.0,0.0,0.0); + var subTimeDeltaSquaredx4 = f4(0.0,0.0,0.0,0.0); + var point5x4 = f4(0.5, 0.5, 0.5, 0.5); + var i = 0; + var len = 0; + var accelIndex = 0; + var newPosx4 = f4(0.0,0.0,0.0,0.0); + var newVelx4 = f4(0.0,0.0,0.0,0.0); + var accel = toF(0.0); + var accelx4 = f4(0.0,0.0,0.0,0.0); + var a = 0; + var posDeltax4 = f4(0.0,0.0,0.0,0.0); + var cmpx4 = b4(0,0,0,0); + var newVelTruex4 = f4(0.0,0.0,0.0,0.0); + + steps = getAccelDataSteps | 0; + subTimeDelta = toF(toF(timeDelta / toF(steps | 0)) / toF(1000.0)); + actualBirds = getActualBirds() | 0; + maxPos = toF(+getMaxPos); + maxPosx4 = f4splat(maxPos); + subTimeDeltax4 = f4splat(subTimeDelta); + subTimeDeltaSquaredx4 = f4mul(subTimeDeltax4, subTimeDeltax4); + + len = ((actualBirds + 3) >> 2) << 4; + + for (i = 0; (i | 0) < (len | 0); i = (i + 16) | 0) { + accelIndex = 0; + newPosx4 = f4load(u8, i & mk4); + newVelx4 = f4load(u8, (i & mk4) + maxBirdsx4); + for (a = 0; (a | 0) < (steps | 0); a = (a + 1) | 0) { + accel = toF(f32[(accelIndex & accelMask) + maxBirdsx8 >> 2]); + accelx4 = f4splat(accel); + accelIndex = (accelIndex + 4) | 0; + posDeltax4 = f4mul(point5x4, f4mul(accelx4, subTimeDeltaSquaredx4)); + posDeltax4 = f4add(posDeltax4, f4mul(newVelx4, subTimeDeltax4)); + newPosx4 = f4add(newPosx4, posDeltax4); + newVelx4 = f4add(newVelx4, f4mul(accelx4, subTimeDeltax4)); + cmpx4 = f4greaterThan(newPosx4, maxPosx4); + + if (b4any(cmpx4)) { + // Work around unimplemented 'neg' operation, using 0 - x. + newVelTruex4 = f4sub(zerox4, newVelx4); + newVelx4 = f4select(cmpx4, newVelTruex4, newVelx4); + } + } + f4store(u8, i & mk4, newPosx4); + f4store(u8, (i & mk4) + maxBirdsx4, newVelx4); + } + } + + return update; +` + +var ffi = { + getActualBirds, + accelDataSteps: ACCEL_DATA_STEPS +}; + +var fbirds = asmLink(asmCompile('global', 'imp', 'buffer', code), this, ffi, buffer); + +init(); +for (var i = 0; i < NUM_BIRDS; i++) { + addBird(i / 10, Math.exp(2, NUM_BIRDS - i)); +} + +var b = dateNow(); +for (var j = 0; j < NUM_UPDATES; j++) { + fbirds(16); +} +print(dateNow() - b); + +assertEq(bufferF32[0], 0); +assertEq(bufferF32[1], 0.10000000149011612); +assertEq(bufferF32[2], 0.20000000298023224); +assertEq(bufferF32[3], 0.30000001192092896); +assertEq(bufferF32[4], 0.4000000059604645); +assertEq(bufferF32[5], 0.5); +assertEq(bufferF32[6], 0.6000000238418579); +assertEq(bufferF32[7], 0.699999988079071); +assertEq(bufferF32[8], 0.800000011920929); +assertEq(bufferF32[9], 0.8999999761581421); +assertEq(bufferF32[10], 1); +assertEq(bufferF32[11], 1.100000023841858); +assertEq(bufferF32[12], 1.2000000476837158); +assertEq(bufferF32[13], 1.2999999523162842); +assertEq(bufferF32[14], 1.399999976158142); +assertEq(bufferF32[15], 1.5); +assertEq(bufferF32[16], 1.600000023841858); +assertEq(bufferF32[17], 1.7000000476837158); +assertEq(bufferF32[18], 1.7999999523162842); +assertEq(bufferF32[19], 1.899999976158142); +assertEq(bufferF32[20], 2); +assertEq(bufferF32[21], 2.0999999046325684); +assertEq(bufferF32[22], 2.200000047683716); +assertEq(bufferF32[23], 2.299999952316284); +assertEq(bufferF32[24], 2.4000000953674316); +assertEq(bufferF32[25], 2.5); +assertEq(bufferF32[26], 2.5999999046325684); +assertEq(bufferF32[27], 2.700000047683716); +assertEq(bufferF32[28], 2.799999952316284); +assertEq(bufferF32[29], 2.9000000953674316); + + +// Code used to generate the assertEq list above. +function generateAssertList() { + var buf = ''; + for (var k = 0; k < NUM_BIRDS; k++) { + buf += 'assertEq(bufferF32['+ k + '], ' + bufferF32[k] + ');\n'; + } + print(buf); +} +//generateAssertList(); diff --git a/js/src/jit-test/tests/asm.js/simd-mandelbrot.js b/js/src/jit-test/tests/asm.js/simd-mandelbrot.js new file mode 100644 index 000000000..349f2062d --- /dev/null +++ b/js/src/jit-test/tests/asm.js/simd-mandelbrot.js @@ -0,0 +1,1819 @@ +/* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ; js-indent-level : 2 ; js-curly-indent-offset: 0 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +// Mandelbrot using SIMD +// Author: Peter Jensen, Intel Corporation + +load(libdir + "asm.js"); +if (!isSimdAvailable() || typeof SIMD === 'undefined') { + print("won't run tests as simd extensions aren't activated yet"); + quit(0); +} + +// global variables +const MAX_ITERATIONS = 10; +const DRAW_ITERATIONS = 10; + +const CANVAS_WIDTH = 20; +const CANVAS_HEIGHT = 20; + +const LIMIT_SHOW = 20 * 20 * 4; + +// Asm.js module buffer. +var buffer = new ArrayBuffer(16 * 1024 * 1024); +var view = new Uint8Array(buffer); + +var moduleCode = ` + "use asm" + var b8 = new global.Uint8Array(buffer); + var toF = global.Math.fround; + var i4 = global.SIMD.Int32x4; + var ci4 = i4.check; + var f4 = global.SIMD.Float32x4; + var i4add = i4.add; + var i4and = i4.and; + var i4ext = i4.extractLane; + var i4sel = i4.select; + var f4add = f4.add; + var f4sub = f4.sub; + var f4mul = f4.mul; + var f4lessThanOrEqual = f4.lessThanOrEqual; + var f4splat = f4.splat; + var imul = global.Math.imul; + var b4 = global.SIMD.Bool32x4; + var b4any = b4.anyTrue; + const zero4 = i4(0,0,0,0), one4 = i4(1,1,1,1), two4 = f4(2,2,2,2), four4 = f4(4,4,4,4); + + const mk0 = 0x007fffff; + + function declareHeapLength() { + b8[0x00ffffff] = 0; + } + + function mapColorAndSetPixel (x, y, width, value, max_iterations) { + x = x | 0; + y = y | 0; + width = width | 0; + value = value | 0; + max_iterations = max_iterations | 0; + + var rgb = 0, r = 0, g = 0, b = 0, index = 0; + + index = (((imul((width >>> 0), (y >>> 0)) + x) | 0) * 4) | 0; + if ((value | 0) == (max_iterations | 0)) { + r = 0; + g = 0; + b = 0; + } else { + rgb = ~~toF(toF(toF(toF(value >>> 0) * toF(0xffff)) / toF(max_iterations >>> 0)) * toF(0xff)); + r = rgb & 0xff; + g = (rgb >>> 8) & 0xff; + b = (rgb >>> 16) & 0xff; + } + b8[(index & mk0) >> 0] = r; + b8[(index & mk0) + 1 >> 0] = g; + b8[(index & mk0) + 2 >> 0] = b; + b8[(index & mk0) + 3 >> 0] = 255; + } + + function mandelPixelX4 (xf, yf, yd, max_iterations) { + xf = toF(xf); + yf = toF(yf); + yd = toF(yd); + max_iterations = max_iterations | 0; + var c_re4 = f4(0,0,0,0), c_im4 = f4(0,0,0,0); + var z_re4 = f4(0,0,0,0), z_im4 = f4(0,0,0,0); + var count4 = i4(0,0,0,0); + var z_re24 = f4(0,0,0,0), z_im24 = f4(0,0,0,0); + var new_re4 = f4(0,0,0,0), new_im4 = f4(0,0,0,0); + var i = 0; + var mb4 = b4(0,0,0,0); + + c_re4 = f4splat(xf); + c_im4 = f4(yf, toF(yd + yf), toF(yd + toF(yd + yf)), toF(yd + toF(yd + toF(yd + yf)))); + + z_re4 = c_re4; + z_im4 = c_im4; + + for (i = 0; (i | 0) < (max_iterations | 0); i = (i + 1) | 0) { + z_re24 = f4mul(z_re4, z_re4); + z_im24 = f4mul(z_im4, z_im4); + mb4 = f4lessThanOrEqual(f4add(z_re24, z_im24), four4); + // If all 4 values are greater than 4.0, there's no reason to continue. + if (!b4any(mb4)) + break; + + new_re4 = f4sub(z_re24, z_im24); + new_im4 = f4mul(f4mul(two4, z_re4), z_im4); + z_re4 = f4add(c_re4, new_re4); + z_im4 = f4add(c_im4, new_im4); + count4 = i4add(count4, i4sel(mb4, one4, zero4)); + } + return ci4(count4); + } + + function mandelColumnX4 (x, width, height, xf, yf, yd, max_iterations) { + x = x | 0; + width = width | 0; + height = height | 0; + xf = toF(xf); + yf = toF(yf); + yd = toF(yd); + max_iterations = max_iterations | 0; + + var y = 0; + var ydx4 = toF(0); + var m4 = i4(0,0,0,0); + + ydx4 = toF(yd * toF(4)); + for (y = 0; (y | 0) < (height | 0); y = (y + 4) | 0) { + m4 = ci4(mandelPixelX4(toF(xf), toF(yf), toF(yd), max_iterations)); + mapColorAndSetPixel(x | 0, y | 0, width, i4ext(m4,0), max_iterations); + mapColorAndSetPixel(x | 0, (y + 1) | 0, width, i4ext(m4,1), max_iterations); + mapColorAndSetPixel(x | 0, (y + 2) | 0, width, i4ext(m4,2), max_iterations); + mapColorAndSetPixel(x | 0, (y + 3) | 0, width, i4ext(m4,3), max_iterations); + yf = toF(yf + ydx4); + } + } + + function mandel (width, height, xc, yc, scale, max_iterations) { + width = width | 0; + height = height | 0; + xc = toF(xc); + yc = toF(yc); + scale = toF(scale); + max_iterations = max_iterations | 0; + + var x0 = toF(0), y0 = toF(0); + var xd = toF(0), yd = toF(0); + var xf = toF(0); + var x = 0; + + x0 = toF(xc - toF(scale * toF(1.5))); + y0 = toF(yc - scale); + xd = toF(toF(scale * toF(3)) / toF(width >>> 0)); + yd = toF(toF(scale * toF(2)) / toF(height >>> 0)); + xf = x0; + + for (x = 0; (x | 0) < (width | 0); x = (x + 1) | 0) { + mandelColumnX4(x, width, height, xf, y0, yd, max_iterations); + xf = toF(xf + xd); + } + } + + return mandel; +`; + +var FFI = {}; +var mandelbro = asmLink(asmCompile('global', 'ffi', 'buffer', moduleCode), this, FFI, buffer); + +function animateMandelbrot () { + var scale_start = 1.0; + var scale_end = 0.0005; + var xc_start = -0.5; + var yc_start = 0.0; + var xc_end = 0.0; + var yc_end = 0.75; + var steps = 200.0; + var scale_step = (scale_end - scale_start)/steps; + var xc_step = (xc_end - xc_start)/steps; + var yc_step = (yc_end - yc_start)/steps; + var scale = scale_start; + var xc = xc_start; + var yc = yc_start; + var i = 0; + var now = dateNow(); + + function draw1 () { + mandelbro(CANVAS_WIDTH, CANVAS_HEIGHT, xc, yc, scale, MAX_ITERATIONS); + if (scale < scale_end || scale > scale_start) { + scale_step = -scale_step; + xc_step = -xc_step; + yc_step = -yc_step; + } + scale += scale_step; + xc += xc_step; + yc += yc_step; + i++; + } + + var b = dateNow(); + for (var j = DRAW_ITERATIONS; j --> 0;) + draw1(); + print(dateNow() - b); +} + +animateMandelbrot(); + +assertEq(view[0], 0, "0th value should be 0"); +assertEq(view[1], 0, "1th value should be 0"); +assertEq(view[2], 0, "2th value should be 0"); +assertEq(view[3], 255, "3th value should be 255"); +assertEq(view[4], 230, "4th value should be 230"); +assertEq(view[5], 127, "5th value should be 127"); +assertEq(view[6], 25, "6th value should be 25"); +assertEq(view[7], 255, "7th value should be 255"); +assertEq(view[8], 230, "8th value should be 230"); +assertEq(view[9], 127, "9th value should be 127"); +assertEq(view[10], 25, "10th value should be 25"); +assertEq(view[11], 255, "11th value should be 255"); +assertEq(view[12], 205, "12th value should be 205"); +assertEq(view[13], 255, "13th value should be 255"); +assertEq(view[14], 50, "14th value should be 50"); +assertEq(view[15], 255, "15th value should be 255"); +assertEq(view[16], 205, "16th value should be 205"); +assertEq(view[17], 255, "17th value should be 255"); +assertEq(view[18], 50, "18th value should be 50"); +assertEq(view[19], 255, "19th value should be 255"); +assertEq(view[20], 205, "20th value should be 205"); +assertEq(view[21], 255, "21th value should be 255"); +assertEq(view[22], 50, "22th value should be 50"); +assertEq(view[23], 255, "23th value should be 255"); +assertEq(view[24], 205, "24th value should be 205"); +assertEq(view[25], 255, "25th value should be 255"); +assertEq(view[26], 50, "26th value should be 50"); +assertEq(view[27], 255, "27th value should be 255"); +assertEq(view[28], 205, "28th value should be 205"); +assertEq(view[29], 255, "29th value should be 255"); +assertEq(view[30], 50, "30th value should be 50"); +assertEq(view[31], 255, "31th value should be 255"); +assertEq(view[32], 179, "32th value should be 179"); +assertEq(view[33], 127, "33th value should be 127"); +assertEq(view[34], 76, "34th value should be 76"); +assertEq(view[35], 255, "35th value should be 255"); +assertEq(view[36], 179, "36th value should be 179"); +assertEq(view[37], 127, "37th value should be 127"); +assertEq(view[38], 76, "38th value should be 76"); +assertEq(view[39], 255, "39th value should be 255"); +assertEq(view[40], 179, "40th value should be 179"); +assertEq(view[41], 127, "41th value should be 127"); +assertEq(view[42], 76, "42th value should be 76"); +assertEq(view[43], 255, "43th value should be 255"); +assertEq(view[44], 154, "44th value should be 154"); +assertEq(view[45], 255, "45th value should be 255"); +assertEq(view[46], 101, "46th value should be 101"); +assertEq(view[47], 255, "47th value should be 255"); +assertEq(view[48], 78, "48th value should be 78"); +assertEq(view[49], 127, "49th value should be 127"); +assertEq(view[50], 178, "50th value should be 178"); +assertEq(view[51], 255, "51th value should be 255"); +assertEq(view[52], 52, "52th value should be 52"); +assertEq(view[53], 255, "53th value should be 255"); +assertEq(view[54], 203, "54th value should be 203"); +assertEq(view[55], 255, "55th value should be 255"); +assertEq(view[56], 154, "56th value should be 154"); +assertEq(view[57], 255, "57th value should be 255"); +assertEq(view[58], 101, "58th value should be 101"); +assertEq(view[59], 255, "59th value should be 255"); +assertEq(view[60], 179, "60th value should be 179"); +assertEq(view[61], 127, "61th value should be 127"); +assertEq(view[62], 76, "62th value should be 76"); +assertEq(view[63], 255, "63th value should be 255"); +assertEq(view[64], 205, "64th value should be 205"); +assertEq(view[65], 255, "65th value should be 255"); +assertEq(view[66], 50, "66th value should be 50"); +assertEq(view[67], 255, "67th value should be 255"); +assertEq(view[68], 205, "68th value should be 205"); +assertEq(view[69], 255, "69th value should be 255"); +assertEq(view[70], 50, "70th value should be 50"); +assertEq(view[71], 255, "71th value should be 255"); +assertEq(view[72], 230, "72th value should be 230"); +assertEq(view[73], 127, "73th value should be 127"); +assertEq(view[74], 25, "74th value should be 25"); +assertEq(view[75], 255, "75th value should be 255"); +assertEq(view[76], 230, "76th value should be 230"); +assertEq(view[77], 127, "77th value should be 127"); +assertEq(view[78], 25, "78th value should be 25"); +assertEq(view[79], 255, "79th value should be 255"); +assertEq(view[80], 0, "80th value should be 0"); +assertEq(view[81], 0, "81th value should be 0"); +assertEq(view[82], 0, "82th value should be 0"); +assertEq(view[83], 255, "83th value should be 255"); +assertEq(view[84], 230, "84th value should be 230"); +assertEq(view[85], 127, "85th value should be 127"); +assertEq(view[86], 25, "86th value should be 25"); +assertEq(view[87], 255, "87th value should be 255"); +assertEq(view[88], 205, "88th value should be 205"); +assertEq(view[89], 255, "89th value should be 255"); +assertEq(view[90], 50, "90th value should be 50"); +assertEq(view[91], 255, "91th value should be 255"); +assertEq(view[92], 205, "92th value should be 205"); +assertEq(view[93], 255, "93th value should be 255"); +assertEq(view[94], 50, "94th value should be 50"); +assertEq(view[95], 255, "95th value should be 255"); +assertEq(view[96], 205, "96th value should be 205"); +assertEq(view[97], 255, "97th value should be 255"); +assertEq(view[98], 50, "98th value should be 50"); +assertEq(view[99], 255, "99th value should be 255"); +assertEq(view[100], 205, "100th value should be 205"); +assertEq(view[101], 255, "101th value should be 255"); +assertEq(view[102], 50, "102th value should be 50"); +assertEq(view[103], 255, "103th value should be 255"); +assertEq(view[104], 205, "104th value should be 205"); +assertEq(view[105], 255, "105th value should be 255"); +assertEq(view[106], 50, "106th value should be 50"); +assertEq(view[107], 255, "107th value should be 255"); +assertEq(view[108], 205, "108th value should be 205"); +assertEq(view[109], 255, "109th value should be 255"); +assertEq(view[110], 50, "110th value should be 50"); +assertEq(view[111], 255, "111th value should be 255"); +assertEq(view[112], 179, "112th value should be 179"); +assertEq(view[113], 127, "113th value should be 127"); +assertEq(view[114], 76, "114th value should be 76"); +assertEq(view[115], 255, "115th value should be 255"); +assertEq(view[116], 179, "116th value should be 179"); +assertEq(view[117], 127, "117th value should be 127"); +assertEq(view[118], 76, "118th value should be 76"); +assertEq(view[119], 255, "119th value should be 255"); +assertEq(view[120], 154, "120th value should be 154"); +assertEq(view[121], 255, "121th value should be 255"); +assertEq(view[122], 101, "122th value should be 101"); +assertEq(view[123], 255, "123th value should be 255"); +assertEq(view[124], 103, "124th value should be 103"); +assertEq(view[125], 255, "125th value should be 255"); +assertEq(view[126], 152, "126th value should be 152"); +assertEq(view[127], 255, "127th value should be 255"); +assertEq(view[128], 0, "128th value should be 0"); +assertEq(view[129], 0, "129th value should be 0"); +assertEq(view[130], 0, "130th value should be 0"); +assertEq(view[131], 255, "131th value should be 255"); +assertEq(view[132], 0, "132th value should be 0"); +assertEq(view[133], 0, "133th value should be 0"); +assertEq(view[134], 0, "134th value should be 0"); +assertEq(view[135], 255, "135th value should be 255"); +assertEq(view[136], 128, "136th value should be 128"); +assertEq(view[137], 127, "137th value should be 127"); +assertEq(view[138], 127, "138th value should be 127"); +assertEq(view[139], 255, "139th value should be 255"); +assertEq(view[140], 154, "140th value should be 154"); +assertEq(view[141], 255, "141th value should be 255"); +assertEq(view[142], 101, "142th value should be 101"); +assertEq(view[143], 255, "143th value should be 255"); +assertEq(view[144], 179, "144th value should be 179"); +assertEq(view[145], 127, "145th value should be 127"); +assertEq(view[146], 76, "146th value should be 76"); +assertEq(view[147], 255, "147th value should be 255"); +assertEq(view[148], 205, "148th value should be 205"); +assertEq(view[149], 255, "149th value should be 255"); +assertEq(view[150], 50, "150th value should be 50"); +assertEq(view[151], 255, "151th value should be 255"); +assertEq(view[152], 205, "152th value should be 205"); +assertEq(view[153], 255, "153th value should be 255"); +assertEq(view[154], 50, "154th value should be 50"); +assertEq(view[155], 255, "155th value should be 255"); +assertEq(view[156], 230, "156th value should be 230"); +assertEq(view[157], 127, "157th value should be 127"); +assertEq(view[158], 25, "158th value should be 25"); +assertEq(view[159], 255, "159th value should be 255"); +assertEq(view[160], 0, "160th value should be 0"); +assertEq(view[161], 0, "161th value should be 0"); +assertEq(view[162], 0, "162th value should be 0"); +assertEq(view[163], 255, "163th value should be 255"); +assertEq(view[164], 230, "164th value should be 230"); +assertEq(view[165], 127, "165th value should be 127"); +assertEq(view[166], 25, "166th value should be 25"); +assertEq(view[167], 255, "167th value should be 255"); +assertEq(view[168], 205, "168th value should be 205"); +assertEq(view[169], 255, "169th value should be 255"); +assertEq(view[170], 50, "170th value should be 50"); +assertEq(view[171], 255, "171th value should be 255"); +assertEq(view[172], 205, "172th value should be 205"); +assertEq(view[173], 255, "173th value should be 255"); +assertEq(view[174], 50, "174th value should be 50"); +assertEq(view[175], 255, "175th value should be 255"); +assertEq(view[176], 205, "176th value should be 205"); +assertEq(view[177], 255, "177th value should be 255"); +assertEq(view[178], 50, "178th value should be 50"); +assertEq(view[179], 255, "179th value should be 255"); +assertEq(view[180], 205, "180th value should be 205"); +assertEq(view[181], 255, "181th value should be 255"); +assertEq(view[182], 50, "182th value should be 50"); +assertEq(view[183], 255, "183th value should be 255"); +assertEq(view[184], 205, "184th value should be 205"); +assertEq(view[185], 255, "185th value should be 255"); +assertEq(view[186], 50, "186th value should be 50"); +assertEq(view[187], 255, "187th value should be 255"); +assertEq(view[188], 179, "188th value should be 179"); +assertEq(view[189], 127, "189th value should be 127"); +assertEq(view[190], 76, "190th value should be 76"); +assertEq(view[191], 255, "191th value should be 255"); +assertEq(view[192], 179, "192th value should be 179"); +assertEq(view[193], 127, "193th value should be 127"); +assertEq(view[194], 76, "194th value should be 76"); +assertEq(view[195], 255, "195th value should be 255"); +assertEq(view[196], 154, "196th value should be 154"); +assertEq(view[197], 255, "197th value should be 255"); +assertEq(view[198], 101, "198th value should be 101"); +assertEq(view[199], 255, "199th value should be 255"); +assertEq(view[200], 103, "200th value should be 103"); +assertEq(view[201], 255, "201th value should be 255"); +assertEq(view[202], 152, "202th value should be 152"); +assertEq(view[203], 255, "203th value should be 255"); +assertEq(view[204], 78, "204th value should be 78"); +assertEq(view[205], 127, "205th value should be 127"); +assertEq(view[206], 178, "206th value should be 178"); +assertEq(view[207], 255, "207th value should be 255"); +assertEq(view[208], 0, "208th value should be 0"); +assertEq(view[209], 0, "209th value should be 0"); +assertEq(view[210], 0, "210th value should be 0"); +assertEq(view[211], 255, "211th value should be 255"); +assertEq(view[212], 0, "212th value should be 0"); +assertEq(view[213], 0, "213th value should be 0"); +assertEq(view[214], 0, "214th value should be 0"); +assertEq(view[215], 255, "215th value should be 255"); +assertEq(view[216], 78, "216th value should be 78"); +assertEq(view[217], 127, "217th value should be 127"); +assertEq(view[218], 178, "218th value should be 178"); +assertEq(view[219], 255, "219th value should be 255"); +assertEq(view[220], 128, "220th value should be 128"); +assertEq(view[221], 127, "221th value should be 127"); +assertEq(view[222], 127, "222th value should be 127"); +assertEq(view[223], 255, "223th value should be 255"); +assertEq(view[224], 154, "224th value should be 154"); +assertEq(view[225], 255, "225th value should be 255"); +assertEq(view[226], 101, "226th value should be 101"); +assertEq(view[227], 255, "227th value should be 255"); +assertEq(view[228], 205, "228th value should be 205"); +assertEq(view[229], 255, "229th value should be 255"); +assertEq(view[230], 50, "230th value should be 50"); +assertEq(view[231], 255, "231th value should be 255"); +assertEq(view[232], 205, "232th value should be 205"); +assertEq(view[233], 255, "233th value should be 255"); +assertEq(view[234], 50, "234th value should be 50"); +assertEq(view[235], 255, "235th value should be 255"); +assertEq(view[236], 230, "236th value should be 230"); +assertEq(view[237], 127, "237th value should be 127"); +assertEq(view[238], 25, "238th value should be 25"); +assertEq(view[239], 255, "239th value should be 255"); +assertEq(view[240], 0, "240th value should be 0"); +assertEq(view[241], 0, "241th value should be 0"); +assertEq(view[242], 0, "242th value should be 0"); +assertEq(view[243], 255, "243th value should be 255"); +assertEq(view[244], 205, "244th value should be 205"); +assertEq(view[245], 255, "245th value should be 255"); +assertEq(view[246], 50, "246th value should be 50"); +assertEq(view[247], 255, "247th value should be 255"); +assertEq(view[248], 205, "248th value should be 205"); +assertEq(view[249], 255, "249th value should be 255"); +assertEq(view[250], 50, "250th value should be 50"); +assertEq(view[251], 255, "251th value should be 255"); +assertEq(view[252], 205, "252th value should be 205"); +assertEq(view[253], 255, "253th value should be 255"); +assertEq(view[254], 50, "254th value should be 50"); +assertEq(view[255], 255, "255th value should be 255"); +assertEq(view[256], 205, "256th value should be 205"); +assertEq(view[257], 255, "257th value should be 255"); +assertEq(view[258], 50, "258th value should be 50"); +assertEq(view[259], 255, "259th value should be 255"); +assertEq(view[260], 205, "260th value should be 205"); +assertEq(view[261], 255, "261th value should be 255"); +assertEq(view[262], 50, "262th value should be 50"); +assertEq(view[263], 255, "263th value should be 255"); +assertEq(view[264], 179, "264th value should be 179"); +assertEq(view[265], 127, "265th value should be 127"); +assertEq(view[266], 76, "266th value should be 76"); +assertEq(view[267], 255, "267th value should be 255"); +assertEq(view[268], 179, "268th value should be 179"); +assertEq(view[269], 127, "269th value should be 127"); +assertEq(view[270], 76, "270th value should be 76"); +assertEq(view[271], 255, "271th value should be 255"); +assertEq(view[272], 154, "272th value should be 154"); +assertEq(view[273], 255, "273th value should be 255"); +assertEq(view[274], 101, "274th value should be 101"); +assertEq(view[275], 255, "275th value should be 255"); +assertEq(view[276], 52, "276th value should be 52"); +assertEq(view[277], 255, "277th value should be 255"); +assertEq(view[278], 203, "278th value should be 203"); +assertEq(view[279], 255, "279th value should be 255"); +assertEq(view[280], 0, "280th value should be 0"); +assertEq(view[281], 0, "281th value should be 0"); +assertEq(view[282], 0, "282th value should be 0"); +assertEq(view[283], 255, "283th value should be 255"); +assertEq(view[284], 0, "284th value should be 0"); +assertEq(view[285], 0, "285th value should be 0"); +assertEq(view[286], 0, "286th value should be 0"); +assertEq(view[287], 255, "287th value should be 255"); +assertEq(view[288], 0, "288th value should be 0"); +assertEq(view[289], 0, "289th value should be 0"); +assertEq(view[290], 0, "290th value should be 0"); +assertEq(view[291], 255, "291th value should be 255"); +assertEq(view[292], 0, "292th value should be 0"); +assertEq(view[293], 0, "293th value should be 0"); +assertEq(view[294], 0, "294th value should be 0"); +assertEq(view[295], 255, "295th value should be 255"); +assertEq(view[296], 0, "296th value should be 0"); +assertEq(view[297], 0, "297th value should be 0"); +assertEq(view[298], 0, "298th value should be 0"); +assertEq(view[299], 255, "299th value should be 255"); +assertEq(view[300], 52, "300th value should be 52"); +assertEq(view[301], 255, "301th value should be 255"); +assertEq(view[302], 203, "302th value should be 203"); +assertEq(view[303], 255, "303th value should be 255"); +assertEq(view[304], 52, "304th value should be 52"); +assertEq(view[305], 255, "305th value should be 255"); +assertEq(view[306], 203, "306th value should be 203"); +assertEq(view[307], 255, "307th value should be 255"); +assertEq(view[308], 179, "308th value should be 179"); +assertEq(view[309], 127, "309th value should be 127"); +assertEq(view[310], 76, "310th value should be 76"); +assertEq(view[311], 255, "311th value should be 255"); +assertEq(view[312], 205, "312th value should be 205"); +assertEq(view[313], 255, "313th value should be 255"); +assertEq(view[314], 50, "314th value should be 50"); +assertEq(view[315], 255, "315th value should be 255"); +assertEq(view[316], 205, "316th value should be 205"); +assertEq(view[317], 255, "317th value should be 255"); +assertEq(view[318], 50, "318th value should be 50"); +assertEq(view[319], 255, "319th value should be 255"); +assertEq(view[320], 230, "320th value should be 230"); +assertEq(view[321], 127, "321th value should be 127"); +assertEq(view[322], 25, "322th value should be 25"); +assertEq(view[323], 255, "323th value should be 255"); +assertEq(view[324], 205, "324th value should be 205"); +assertEq(view[325], 255, "325th value should be 255"); +assertEq(view[326], 50, "326th value should be 50"); +assertEq(view[327], 255, "327th value should be 255"); +assertEq(view[328], 205, "328th value should be 205"); +assertEq(view[329], 255, "329th value should be 255"); +assertEq(view[330], 50, "330th value should be 50"); +assertEq(view[331], 255, "331th value should be 255"); +assertEq(view[332], 205, "332th value should be 205"); +assertEq(view[333], 255, "333th value should be 255"); +assertEq(view[334], 50, "334th value should be 50"); +assertEq(view[335], 255, "335th value should be 255"); +assertEq(view[336], 205, "336th value should be 205"); +assertEq(view[337], 255, "337th value should be 255"); +assertEq(view[338], 50, "338th value should be 50"); +assertEq(view[339], 255, "339th value should be 255"); +assertEq(view[340], 179, "340th value should be 179"); +assertEq(view[341], 127, "341th value should be 127"); +assertEq(view[342], 76, "342th value should be 76"); +assertEq(view[343], 255, "343th value should be 255"); +assertEq(view[344], 154, "344th value should be 154"); +assertEq(view[345], 255, "345th value should be 255"); +assertEq(view[346], 101, "346th value should be 101"); +assertEq(view[347], 255, "347th value should be 255"); +assertEq(view[348], 154, "348th value should be 154"); +assertEq(view[349], 255, "349th value should be 255"); +assertEq(view[350], 101, "350th value should be 101"); +assertEq(view[351], 255, "351th value should be 255"); +assertEq(view[352], 128, "352th value should be 128"); +assertEq(view[353], 127, "353th value should be 127"); +assertEq(view[354], 127, "354th value should be 127"); +assertEq(view[355], 255, "355th value should be 255"); +assertEq(view[356], 52, "356th value should be 52"); +assertEq(view[357], 255, "357th value should be 255"); +assertEq(view[358], 203, "358th value should be 203"); +assertEq(view[359], 255, "359th value should be 255"); +assertEq(view[360], 0, "360th value should be 0"); +assertEq(view[361], 0, "361th value should be 0"); +assertEq(view[362], 0, "362th value should be 0"); +assertEq(view[363], 255, "363th value should be 255"); +assertEq(view[364], 0, "364th value should be 0"); +assertEq(view[365], 0, "365th value should be 0"); +assertEq(view[366], 0, "366th value should be 0"); +assertEq(view[367], 255, "367th value should be 255"); +assertEq(view[368], 0, "368th value should be 0"); +assertEq(view[369], 0, "369th value should be 0"); +assertEq(view[370], 0, "370th value should be 0"); +assertEq(view[371], 255, "371th value should be 255"); +assertEq(view[372], 0, "372th value should be 0"); +assertEq(view[373], 0, "373th value should be 0"); +assertEq(view[374], 0, "374th value should be 0"); +assertEq(view[375], 255, "375th value should be 255"); +assertEq(view[376], 0, "376th value should be 0"); +assertEq(view[377], 0, "377th value should be 0"); +assertEq(view[378], 0, "378th value should be 0"); +assertEq(view[379], 255, "379th value should be 255"); +assertEq(view[380], 0, "380th value should be 0"); +assertEq(view[381], 0, "381th value should be 0"); +assertEq(view[382], 0, "382th value should be 0"); +assertEq(view[383], 255, "383th value should be 255"); +assertEq(view[384], 52, "384th value should be 52"); +assertEq(view[385], 255, "385th value should be 255"); +assertEq(view[386], 203, "386th value should be 203"); +assertEq(view[387], 255, "387th value should be 255"); +assertEq(view[388], 179, "388th value should be 179"); +assertEq(view[389], 127, "389th value should be 127"); +assertEq(view[390], 76, "390th value should be 76"); +assertEq(view[391], 255, "391th value should be 255"); +assertEq(view[392], 205, "392th value should be 205"); +assertEq(view[393], 255, "393th value should be 255"); +assertEq(view[394], 50, "394th value should be 50"); +assertEq(view[395], 255, "395th value should be 255"); +assertEq(view[396], 205, "396th value should be 205"); +assertEq(view[397], 255, "397th value should be 255"); +assertEq(view[398], 50, "398th value should be 50"); +assertEq(view[399], 255, "399th value should be 255"); +assertEq(view[400], 205, "400th value should be 205"); +assertEq(view[401], 255, "401th value should be 255"); +assertEq(view[402], 50, "402th value should be 50"); +assertEq(view[403], 255, "403th value should be 255"); +assertEq(view[404], 205, "404th value should be 205"); +assertEq(view[405], 255, "405th value should be 255"); +assertEq(view[406], 50, "406th value should be 50"); +assertEq(view[407], 255, "407th value should be 255"); +assertEq(view[408], 205, "408th value should be 205"); +assertEq(view[409], 255, "409th value should be 255"); +assertEq(view[410], 50, "410th value should be 50"); +assertEq(view[411], 255, "411th value should be 255"); +assertEq(view[412], 205, "412th value should be 205"); +assertEq(view[413], 255, "413th value should be 255"); +assertEq(view[414], 50, "414th value should be 50"); +assertEq(view[415], 255, "415th value should be 255"); +assertEq(view[416], 154, "416th value should be 154"); +assertEq(view[417], 255, "417th value should be 255"); +assertEq(view[418], 101, "418th value should be 101"); +assertEq(view[419], 255, "419th value should be 255"); +assertEq(view[420], 128, "420th value should be 128"); +assertEq(view[421], 127, "421th value should be 127"); +assertEq(view[422], 127, "422th value should be 127"); +assertEq(view[423], 255, "423th value should be 255"); +assertEq(view[424], 154, "424th value should be 154"); +assertEq(view[425], 255, "425th value should be 255"); +assertEq(view[426], 101, "426th value should be 101"); +assertEq(view[427], 255, "427th value should be 255"); +assertEq(view[428], 128, "428th value should be 128"); +assertEq(view[429], 127, "429th value should be 127"); +assertEq(view[430], 127, "430th value should be 127"); +assertEq(view[431], 255, "431th value should be 255"); +assertEq(view[432], 103, "432th value should be 103"); +assertEq(view[433], 255, "433th value should be 255"); +assertEq(view[434], 152, "434th value should be 152"); +assertEq(view[435], 255, "435th value should be 255"); +assertEq(view[436], 0, "436th value should be 0"); +assertEq(view[437], 0, "437th value should be 0"); +assertEq(view[438], 0, "438th value should be 0"); +assertEq(view[439], 255, "439th value should be 255"); +assertEq(view[440], 0, "440th value should be 0"); +assertEq(view[441], 0, "441th value should be 0"); +assertEq(view[442], 0, "442th value should be 0"); +assertEq(view[443], 255, "443th value should be 255"); +assertEq(view[444], 0, "444th value should be 0"); +assertEq(view[445], 0, "445th value should be 0"); +assertEq(view[446], 0, "446th value should be 0"); +assertEq(view[447], 255, "447th value should be 255"); +assertEq(view[448], 0, "448th value should be 0"); +assertEq(view[449], 0, "449th value should be 0"); +assertEq(view[450], 0, "450th value should be 0"); +assertEq(view[451], 255, "451th value should be 255"); +assertEq(view[452], 0, "452th value should be 0"); +assertEq(view[453], 0, "453th value should be 0"); +assertEq(view[454], 0, "454th value should be 0"); +assertEq(view[455], 255, "455th value should be 255"); +assertEq(view[456], 0, "456th value should be 0"); +assertEq(view[457], 0, "457th value should be 0"); +assertEq(view[458], 0, "458th value should be 0"); +assertEq(view[459], 255, "459th value should be 255"); +assertEq(view[460], 0, "460th value should be 0"); +assertEq(view[461], 0, "461th value should be 0"); +assertEq(view[462], 0, "462th value should be 0"); +assertEq(view[463], 255, "463th value should be 255"); +assertEq(view[464], 78, "464th value should be 78"); +assertEq(view[465], 127, "465th value should be 127"); +assertEq(view[466], 178, "466th value should be 178"); +assertEq(view[467], 255, "467th value should be 255"); +assertEq(view[468], 154, "468th value should be 154"); +assertEq(view[469], 255, "469th value should be 255"); +assertEq(view[470], 101, "470th value should be 101"); +assertEq(view[471], 255, "471th value should be 255"); +assertEq(view[472], 205, "472th value should be 205"); +assertEq(view[473], 255, "473th value should be 255"); +assertEq(view[474], 50, "474th value should be 50"); +assertEq(view[475], 255, "475th value should be 255"); +assertEq(view[476], 205, "476th value should be 205"); +assertEq(view[477], 255, "477th value should be 255"); +assertEq(view[478], 50, "478th value should be 50"); +assertEq(view[479], 255, "479th value should be 255"); +assertEq(view[480], 205, "480th value should be 205"); +assertEq(view[481], 255, "481th value should be 255"); +assertEq(view[482], 50, "482th value should be 50"); +assertEq(view[483], 255, "483th value should be 255"); +assertEq(view[484], 205, "484th value should be 205"); +assertEq(view[485], 255, "485th value should be 255"); +assertEq(view[486], 50, "486th value should be 50"); +assertEq(view[487], 255, "487th value should be 255"); +assertEq(view[488], 179, "488th value should be 179"); +assertEq(view[489], 127, "489th value should be 127"); +assertEq(view[490], 76, "490th value should be 76"); +assertEq(view[491], 255, "491th value should be 255"); +assertEq(view[492], 179, "492th value should be 179"); +assertEq(view[493], 127, "493th value should be 127"); +assertEq(view[494], 76, "494th value should be 76"); +assertEq(view[495], 255, "495th value should be 255"); +assertEq(view[496], 128, "496th value should be 128"); +assertEq(view[497], 127, "497th value should be 127"); +assertEq(view[498], 127, "498th value should be 127"); +assertEq(view[499], 255, "499th value should be 255"); +assertEq(view[500], 52, "500th value should be 52"); +assertEq(view[501], 255, "501th value should be 255"); +assertEq(view[502], 203, "502th value should be 203"); +assertEq(view[503], 255, "503th value should be 255"); +assertEq(view[504], 0, "504th value should be 0"); +assertEq(view[505], 0, "505th value should be 0"); +assertEq(view[506], 0, "506th value should be 0"); +assertEq(view[507], 255, "507th value should be 255"); +assertEq(view[508], 78, "508th value should be 78"); +assertEq(view[509], 127, "509th value should be 127"); +assertEq(view[510], 178, "510th value should be 178"); +assertEq(view[511], 255, "511th value should be 255"); +assertEq(view[512], 52, "512th value should be 52"); +assertEq(view[513], 255, "513th value should be 255"); +assertEq(view[514], 203, "514th value should be 203"); +assertEq(view[515], 255, "515th value should be 255"); +assertEq(view[516], 0, "516th value should be 0"); +assertEq(view[517], 0, "517th value should be 0"); +assertEq(view[518], 0, "518th value should be 0"); +assertEq(view[519], 255, "519th value should be 255"); +assertEq(view[520], 0, "520th value should be 0"); +assertEq(view[521], 0, "521th value should be 0"); +assertEq(view[522], 0, "522th value should be 0"); +assertEq(view[523], 255, "523th value should be 255"); +assertEq(view[524], 0, "524th value should be 0"); +assertEq(view[525], 0, "525th value should be 0"); +assertEq(view[526], 0, "526th value should be 0"); +assertEq(view[527], 255, "527th value should be 255"); +assertEq(view[528], 0, "528th value should be 0"); +assertEq(view[529], 0, "529th value should be 0"); +assertEq(view[530], 0, "530th value should be 0"); +assertEq(view[531], 255, "531th value should be 255"); +assertEq(view[532], 0, "532th value should be 0"); +assertEq(view[533], 0, "533th value should be 0"); +assertEq(view[534], 0, "534th value should be 0"); +assertEq(view[535], 255, "535th value should be 255"); +assertEq(view[536], 0, "536th value should be 0"); +assertEq(view[537], 0, "537th value should be 0"); +assertEq(view[538], 0, "538th value should be 0"); +assertEq(view[539], 255, "539th value should be 255"); +assertEq(view[540], 0, "540th value should be 0"); +assertEq(view[541], 0, "541th value should be 0"); +assertEq(view[542], 0, "542th value should be 0"); +assertEq(view[543], 255, "543th value should be 255"); +assertEq(view[544], 0, "544th value should be 0"); +assertEq(view[545], 0, "545th value should be 0"); +assertEq(view[546], 0, "546th value should be 0"); +assertEq(view[547], 255, "547th value should be 255"); +assertEq(view[548], 154, "548th value should be 154"); +assertEq(view[549], 255, "549th value should be 255"); +assertEq(view[550], 101, "550th value should be 101"); +assertEq(view[551], 255, "551th value should be 255"); +assertEq(view[552], 205, "552th value should be 205"); +assertEq(view[553], 255, "553th value should be 255"); +assertEq(view[554], 50, "554th value should be 50"); +assertEq(view[555], 255, "555th value should be 255"); +assertEq(view[556], 205, "556th value should be 205"); +assertEq(view[557], 255, "557th value should be 255"); +assertEq(view[558], 50, "558th value should be 50"); +assertEq(view[559], 255, "559th value should be 255"); +assertEq(view[560], 205, "560th value should be 205"); +assertEq(view[561], 255, "561th value should be 255"); +assertEq(view[562], 50, "562th value should be 50"); +assertEq(view[563], 255, "563th value should be 255"); +assertEq(view[564], 179, "564th value should be 179"); +assertEq(view[565], 127, "565th value should be 127"); +assertEq(view[566], 76, "566th value should be 76"); +assertEq(view[567], 255, "567th value should be 255"); +assertEq(view[568], 179, "568th value should be 179"); +assertEq(view[569], 127, "569th value should be 127"); +assertEq(view[570], 76, "570th value should be 76"); +assertEq(view[571], 255, "571th value should be 255"); +assertEq(view[572], 154, "572th value should be 154"); +assertEq(view[573], 255, "573th value should be 255"); +assertEq(view[574], 101, "574th value should be 101"); +assertEq(view[575], 255, "575th value should be 255"); +assertEq(view[576], 103, "576th value should be 103"); +assertEq(view[577], 255, "577th value should be 255"); +assertEq(view[578], 152, "578th value should be 152"); +assertEq(view[579], 255, "579th value should be 255"); +assertEq(view[580], 0, "580th value should be 0"); +assertEq(view[581], 0, "581th value should be 0"); +assertEq(view[582], 0, "582th value should be 0"); +assertEq(view[583], 255, "583th value should be 255"); +assertEq(view[584], 0, "584th value should be 0"); +assertEq(view[585], 0, "585th value should be 0"); +assertEq(view[586], 0, "586th value should be 0"); +assertEq(view[587], 255, "587th value should be 255"); +assertEq(view[588], 0, "588th value should be 0"); +assertEq(view[589], 0, "589th value should be 0"); +assertEq(view[590], 0, "590th value should be 0"); +assertEq(view[591], 255, "591th value should be 255"); +assertEq(view[592], 0, "592th value should be 0"); +assertEq(view[593], 0, "593th value should be 0"); +assertEq(view[594], 0, "594th value should be 0"); +assertEq(view[595], 255, "595th value should be 255"); +assertEq(view[596], 0, "596th value should be 0"); +assertEq(view[597], 0, "597th value should be 0"); +assertEq(view[598], 0, "598th value should be 0"); +assertEq(view[599], 255, "599th value should be 255"); +assertEq(view[600], 0, "600th value should be 0"); +assertEq(view[601], 0, "601th value should be 0"); +assertEq(view[602], 0, "602th value should be 0"); +assertEq(view[603], 255, "603th value should be 255"); +assertEq(view[604], 0, "604th value should be 0"); +assertEq(view[605], 0, "605th value should be 0"); +assertEq(view[606], 0, "606th value should be 0"); +assertEq(view[607], 255, "607th value should be 255"); +assertEq(view[608], 0, "608th value should be 0"); +assertEq(view[609], 0, "609th value should be 0"); +assertEq(view[610], 0, "610th value should be 0"); +assertEq(view[611], 255, "611th value should be 255"); +assertEq(view[612], 0, "612th value should be 0"); +assertEq(view[613], 0, "613th value should be 0"); +assertEq(view[614], 0, "614th value should be 0"); +assertEq(view[615], 255, "615th value should be 255"); +assertEq(view[616], 0, "616th value should be 0"); +assertEq(view[617], 0, "617th value should be 0"); +assertEq(view[618], 0, "618th value should be 0"); +assertEq(view[619], 255, "619th value should be 255"); +assertEq(view[620], 0, "620th value should be 0"); +assertEq(view[621], 0, "621th value should be 0"); +assertEq(view[622], 0, "622th value should be 0"); +assertEq(view[623], 255, "623th value should be 255"); +assertEq(view[624], 0, "624th value should be 0"); +assertEq(view[625], 0, "625th value should be 0"); +assertEq(view[626], 0, "626th value should be 0"); +assertEq(view[627], 255, "627th value should be 255"); +assertEq(view[628], 154, "628th value should be 154"); +assertEq(view[629], 255, "629th value should be 255"); +assertEq(view[630], 101, "630th value should be 101"); +assertEq(view[631], 255, "631th value should be 255"); +assertEq(view[632], 205, "632th value should be 205"); +assertEq(view[633], 255, "633th value should be 255"); +assertEq(view[634], 50, "634th value should be 50"); +assertEq(view[635], 255, "635th value should be 255"); +assertEq(view[636], 205, "636th value should be 205"); +assertEq(view[637], 255, "637th value should be 255"); +assertEq(view[638], 50, "638th value should be 50"); +assertEq(view[639], 255, "639th value should be 255"); +assertEq(view[640], 179, "640th value should be 179"); +assertEq(view[641], 127, "641th value should be 127"); +assertEq(view[642], 76, "642th value should be 76"); +assertEq(view[643], 255, "643th value should be 255"); +assertEq(view[644], 179, "644th value should be 179"); +assertEq(view[645], 127, "645th value should be 127"); +assertEq(view[646], 76, "646th value should be 76"); +assertEq(view[647], 255, "647th value should be 255"); +assertEq(view[648], 154, "648th value should be 154"); +assertEq(view[649], 255, "649th value should be 255"); +assertEq(view[650], 101, "650th value should be 101"); +assertEq(view[651], 255, "651th value should be 255"); +assertEq(view[652], 128, "652th value should be 128"); +assertEq(view[653], 127, "653th value should be 127"); +assertEq(view[654], 127, "654th value should be 127"); +assertEq(view[655], 255, "655th value should be 255"); +assertEq(view[656], 52, "656th value should be 52"); +assertEq(view[657], 255, "657th value should be 255"); +assertEq(view[658], 203, "658th value should be 203"); +assertEq(view[659], 255, "659th value should be 255"); +assertEq(view[660], 0, "660th value should be 0"); +assertEq(view[661], 0, "661th value should be 0"); +assertEq(view[662], 0, "662th value should be 0"); +assertEq(view[663], 255, "663th value should be 255"); +assertEq(view[664], 0, "664th value should be 0"); +assertEq(view[665], 0, "665th value should be 0"); +assertEq(view[666], 0, "666th value should be 0"); +assertEq(view[667], 255, "667th value should be 255"); +assertEq(view[668], 0, "668th value should be 0"); +assertEq(view[669], 0, "669th value should be 0"); +assertEq(view[670], 0, "670th value should be 0"); +assertEq(view[671], 255, "671th value should be 255"); +assertEq(view[672], 0, "672th value should be 0"); +assertEq(view[673], 0, "673th value should be 0"); +assertEq(view[674], 0, "674th value should be 0"); +assertEq(view[675], 255, "675th value should be 255"); +assertEq(view[676], 0, "676th value should be 0"); +assertEq(view[677], 0, "677th value should be 0"); +assertEq(view[678], 0, "678th value should be 0"); +assertEq(view[679], 255, "679th value should be 255"); +assertEq(view[680], 0, "680th value should be 0"); +assertEq(view[681], 0, "681th value should be 0"); +assertEq(view[682], 0, "682th value should be 0"); +assertEq(view[683], 255, "683th value should be 255"); +assertEq(view[684], 0, "684th value should be 0"); +assertEq(view[685], 0, "685th value should be 0"); +assertEq(view[686], 0, "686th value should be 0"); +assertEq(view[687], 255, "687th value should be 255"); +assertEq(view[688], 0, "688th value should be 0"); +assertEq(view[689], 0, "689th value should be 0"); +assertEq(view[690], 0, "690th value should be 0"); +assertEq(view[691], 255, "691th value should be 255"); +assertEq(view[692], 0, "692th value should be 0"); +assertEq(view[693], 0, "693th value should be 0"); +assertEq(view[694], 0, "694th value should be 0"); +assertEq(view[695], 255, "695th value should be 255"); +assertEq(view[696], 0, "696th value should be 0"); +assertEq(view[697], 0, "697th value should be 0"); +assertEq(view[698], 0, "698th value should be 0"); +assertEq(view[699], 255, "699th value should be 255"); +assertEq(view[700], 0, "700th value should be 0"); +assertEq(view[701], 0, "701th value should be 0"); +assertEq(view[702], 0, "702th value should be 0"); +assertEq(view[703], 255, "703th value should be 255"); +assertEq(view[704], 0, "704th value should be 0"); +assertEq(view[705], 0, "705th value should be 0"); +assertEq(view[706], 0, "706th value should be 0"); +assertEq(view[707], 255, "707th value should be 255"); +assertEq(view[708], 154, "708th value should be 154"); +assertEq(view[709], 255, "709th value should be 255"); +assertEq(view[710], 101, "710th value should be 101"); +assertEq(view[711], 255, "711th value should be 255"); +assertEq(view[712], 179, "712th value should be 179"); +assertEq(view[713], 127, "713th value should be 127"); +assertEq(view[714], 76, "714th value should be 76"); +assertEq(view[715], 255, "715th value should be 255"); +assertEq(view[716], 205, "716th value should be 205"); +assertEq(view[717], 255, "717th value should be 255"); +assertEq(view[718], 50, "718th value should be 50"); +assertEq(view[719], 255, "719th value should be 255"); +assertEq(view[720], 154, "720th value should be 154"); +assertEq(view[721], 255, "721th value should be 255"); +assertEq(view[722], 101, "722th value should be 101"); +assertEq(view[723], 255, "723th value should be 255"); +assertEq(view[724], 52, "724th value should be 52"); +assertEq(view[725], 255, "725th value should be 255"); +assertEq(view[726], 203, "726th value should be 203"); +assertEq(view[727], 255, "727th value should be 255"); +assertEq(view[728], 128, "728th value should be 128"); +assertEq(view[729], 127, "729th value should be 127"); +assertEq(view[730], 127, "730th value should be 127"); +assertEq(view[731], 255, "731th value should be 255"); +assertEq(view[732], 78, "732th value should be 78"); +assertEq(view[733], 127, "733th value should be 127"); +assertEq(view[734], 178, "734th value should be 178"); +assertEq(view[735], 255, "735th value should be 255"); +assertEq(view[736], 0, "736th value should be 0"); +assertEq(view[737], 0, "737th value should be 0"); +assertEq(view[738], 0, "738th value should be 0"); +assertEq(view[739], 255, "739th value should be 255"); +assertEq(view[740], 0, "740th value should be 0"); +assertEq(view[741], 0, "741th value should be 0"); +assertEq(view[742], 0, "742th value should be 0"); +assertEq(view[743], 255, "743th value should be 255"); +assertEq(view[744], 0, "744th value should be 0"); +assertEq(view[745], 0, "745th value should be 0"); +assertEq(view[746], 0, "746th value should be 0"); +assertEq(view[747], 255, "747th value should be 255"); +assertEq(view[748], 0, "748th value should be 0"); +assertEq(view[749], 0, "749th value should be 0"); +assertEq(view[750], 0, "750th value should be 0"); +assertEq(view[751], 255, "751th value should be 255"); +assertEq(view[752], 0, "752th value should be 0"); +assertEq(view[753], 0, "753th value should be 0"); +assertEq(view[754], 0, "754th value should be 0"); +assertEq(view[755], 255, "755th value should be 255"); +assertEq(view[756], 0, "756th value should be 0"); +assertEq(view[757], 0, "757th value should be 0"); +assertEq(view[758], 0, "758th value should be 0"); +assertEq(view[759], 255, "759th value should be 255"); +assertEq(view[760], 0, "760th value should be 0"); +assertEq(view[761], 0, "761th value should be 0"); +assertEq(view[762], 0, "762th value should be 0"); +assertEq(view[763], 255, "763th value should be 255"); +assertEq(view[764], 0, "764th value should be 0"); +assertEq(view[765], 0, "765th value should be 0"); +assertEq(view[766], 0, "766th value should be 0"); +assertEq(view[767], 255, "767th value should be 255"); +assertEq(view[768], 0, "768th value should be 0"); +assertEq(view[769], 0, "769th value should be 0"); +assertEq(view[770], 0, "770th value should be 0"); +assertEq(view[771], 255, "771th value should be 255"); +assertEq(view[772], 0, "772th value should be 0"); +assertEq(view[773], 0, "773th value should be 0"); +assertEq(view[774], 0, "774th value should be 0"); +assertEq(view[775], 255, "775th value should be 255"); +assertEq(view[776], 0, "776th value should be 0"); +assertEq(view[777], 0, "777th value should be 0"); +assertEq(view[778], 0, "778th value should be 0"); +assertEq(view[779], 255, "779th value should be 255"); +assertEq(view[780], 0, "780th value should be 0"); +assertEq(view[781], 0, "781th value should be 0"); +assertEq(view[782], 0, "782th value should be 0"); +assertEq(view[783], 255, "783th value should be 255"); +assertEq(view[784], 78, "784th value should be 78"); +assertEq(view[785], 127, "785th value should be 127"); +assertEq(view[786], 178, "786th value should be 178"); +assertEq(view[787], 255, "787th value should be 255"); +assertEq(view[788], 154, "788th value should be 154"); +assertEq(view[789], 255, "789th value should be 255"); +assertEq(view[790], 101, "790th value should be 101"); +assertEq(view[791], 255, "791th value should be 255"); +assertEq(view[792], 179, "792th value should be 179"); +assertEq(view[793], 127, "793th value should be 127"); +assertEq(view[794], 76, "794th value should be 76"); +assertEq(view[795], 255, "795th value should be 255"); +assertEq(view[796], 205, "796th value should be 205"); +assertEq(view[797], 255, "797th value should be 255"); +assertEq(view[798], 50, "798th value should be 50"); +assertEq(view[799], 255, "799th value should be 255"); +assertEq(view[800], 128, "800th value should be 128"); +assertEq(view[801], 127, "801th value should be 127"); +assertEq(view[802], 127, "802th value should be 127"); +assertEq(view[803], 255, "803th value should be 255"); +assertEq(view[804], 0, "804th value should be 0"); +assertEq(view[805], 0, "805th value should be 0"); +assertEq(view[806], 0, "806th value should be 0"); +assertEq(view[807], 255, "807th value should be 255"); +assertEq(view[808], 26, "808th value should be 26"); +assertEq(view[809], 127, "809th value should be 127"); +assertEq(view[810], 229, "810th value should be 229"); +assertEq(view[811], 255, "811th value should be 255"); +assertEq(view[812], 0, "812th value should be 0"); +assertEq(view[813], 0, "813th value should be 0"); +assertEq(view[814], 0, "814th value should be 0"); +assertEq(view[815], 255, "815th value should be 255"); +assertEq(view[816], 0, "816th value should be 0"); +assertEq(view[817], 0, "817th value should be 0"); +assertEq(view[818], 0, "818th value should be 0"); +assertEq(view[819], 255, "819th value should be 255"); +assertEq(view[820], 0, "820th value should be 0"); +assertEq(view[821], 0, "821th value should be 0"); +assertEq(view[822], 0, "822th value should be 0"); +assertEq(view[823], 255, "823th value should be 255"); +assertEq(view[824], 0, "824th value should be 0"); +assertEq(view[825], 0, "825th value should be 0"); +assertEq(view[826], 0, "826th value should be 0"); +assertEq(view[827], 255, "827th value should be 255"); +assertEq(view[828], 0, "828th value should be 0"); +assertEq(view[829], 0, "829th value should be 0"); +assertEq(view[830], 0, "830th value should be 0"); +assertEq(view[831], 255, "831th value should be 255"); +assertEq(view[832], 0, "832th value should be 0"); +assertEq(view[833], 0, "833th value should be 0"); +assertEq(view[834], 0, "834th value should be 0"); +assertEq(view[835], 255, "835th value should be 255"); +assertEq(view[836], 0, "836th value should be 0"); +assertEq(view[837], 0, "837th value should be 0"); +assertEq(view[838], 0, "838th value should be 0"); +assertEq(view[839], 255, "839th value should be 255"); +assertEq(view[840], 0, "840th value should be 0"); +assertEq(view[841], 0, "841th value should be 0"); +assertEq(view[842], 0, "842th value should be 0"); +assertEq(view[843], 255, "843th value should be 255"); +assertEq(view[844], 0, "844th value should be 0"); +assertEq(view[845], 0, "845th value should be 0"); +assertEq(view[846], 0, "846th value should be 0"); +assertEq(view[847], 255, "847th value should be 255"); +assertEq(view[848], 0, "848th value should be 0"); +assertEq(view[849], 0, "849th value should be 0"); +assertEq(view[850], 0, "850th value should be 0"); +assertEq(view[851], 255, "851th value should be 255"); +assertEq(view[852], 0, "852th value should be 0"); +assertEq(view[853], 0, "853th value should be 0"); +assertEq(view[854], 0, "854th value should be 0"); +assertEq(view[855], 255, "855th value should be 255"); +assertEq(view[856], 0, "856th value should be 0"); +assertEq(view[857], 0, "857th value should be 0"); +assertEq(view[858], 0, "858th value should be 0"); +assertEq(view[859], 255, "859th value should be 255"); +assertEq(view[860], 0, "860th value should be 0"); +assertEq(view[861], 0, "861th value should be 0"); +assertEq(view[862], 0, "862th value should be 0"); +assertEq(view[863], 255, "863th value should be 255"); +assertEq(view[864], 103, "864th value should be 103"); +assertEq(view[865], 255, "865th value should be 255"); +assertEq(view[866], 152, "866th value should be 152"); +assertEq(view[867], 255, "867th value should be 255"); +assertEq(view[868], 154, "868th value should be 154"); +assertEq(view[869], 255, "869th value should be 255"); +assertEq(view[870], 101, "870th value should be 101"); +assertEq(view[871], 255, "871th value should be 255"); +assertEq(view[872], 179, "872th value should be 179"); +assertEq(view[873], 127, "873th value should be 127"); +assertEq(view[874], 76, "874th value should be 76"); +assertEq(view[875], 255, "875th value should be 255"); +assertEq(view[876], 205, "876th value should be 205"); +assertEq(view[877], 255, "877th value should be 255"); +assertEq(view[878], 50, "878th value should be 50"); +assertEq(view[879], 255, "879th value should be 255"); +assertEq(view[880], 179, "880th value should be 179"); +assertEq(view[881], 127, "881th value should be 127"); +assertEq(view[882], 76, "882th value should be 76"); +assertEq(view[883], 255, "883th value should be 255"); +assertEq(view[884], 179, "884th value should be 179"); +assertEq(view[885], 127, "885th value should be 127"); +assertEq(view[886], 76, "886th value should be 76"); +assertEq(view[887], 255, "887th value should be 255"); +assertEq(view[888], 128, "888th value should be 128"); +assertEq(view[889], 127, "889th value should be 127"); +assertEq(view[890], 127, "890th value should be 127"); +assertEq(view[891], 255, "891th value should be 255"); +assertEq(view[892], 103, "892th value should be 103"); +assertEq(view[893], 255, "893th value should be 255"); +assertEq(view[894], 152, "894th value should be 152"); +assertEq(view[895], 255, "895th value should be 255"); +assertEq(view[896], 26, "896th value should be 26"); +assertEq(view[897], 127, "897th value should be 127"); +assertEq(view[898], 229, "898th value should be 229"); +assertEq(view[899], 255, "899th value should be 255"); +assertEq(view[900], 0, "900th value should be 0"); +assertEq(view[901], 0, "901th value should be 0"); +assertEq(view[902], 0, "902th value should be 0"); +assertEq(view[903], 255, "903th value should be 255"); +assertEq(view[904], 0, "904th value should be 0"); +assertEq(view[905], 0, "905th value should be 0"); +assertEq(view[906], 0, "906th value should be 0"); +assertEq(view[907], 255, "907th value should be 255"); +assertEq(view[908], 0, "908th value should be 0"); +assertEq(view[909], 0, "909th value should be 0"); +assertEq(view[910], 0, "910th value should be 0"); +assertEq(view[911], 255, "911th value should be 255"); +assertEq(view[912], 0, "912th value should be 0"); +assertEq(view[913], 0, "913th value should be 0"); +assertEq(view[914], 0, "914th value should be 0"); +assertEq(view[915], 255, "915th value should be 255"); +assertEq(view[916], 0, "916th value should be 0"); +assertEq(view[917], 0, "917th value should be 0"); +assertEq(view[918], 0, "918th value should be 0"); +assertEq(view[919], 255, "919th value should be 255"); +assertEq(view[920], 0, "920th value should be 0"); +assertEq(view[921], 0, "921th value should be 0"); +assertEq(view[922], 0, "922th value should be 0"); +assertEq(view[923], 255, "923th value should be 255"); +assertEq(view[924], 0, "924th value should be 0"); +assertEq(view[925], 0, "925th value should be 0"); +assertEq(view[926], 0, "926th value should be 0"); +assertEq(view[927], 255, "927th value should be 255"); +assertEq(view[928], 0, "928th value should be 0"); +assertEq(view[929], 0, "929th value should be 0"); +assertEq(view[930], 0, "930th value should be 0"); +assertEq(view[931], 255, "931th value should be 255"); +assertEq(view[932], 0, "932th value should be 0"); +assertEq(view[933], 0, "933th value should be 0"); +assertEq(view[934], 0, "934th value should be 0"); +assertEq(view[935], 255, "935th value should be 255"); +assertEq(view[936], 0, "936th value should be 0"); +assertEq(view[937], 0, "937th value should be 0"); +assertEq(view[938], 0, "938th value should be 0"); +assertEq(view[939], 255, "939th value should be 255"); +assertEq(view[940], 0, "940th value should be 0"); +assertEq(view[941], 0, "941th value should be 0"); +assertEq(view[942], 0, "942th value should be 0"); +assertEq(view[943], 255, "943th value should be 255"); +assertEq(view[944], 0, "944th value should be 0"); +assertEq(view[945], 0, "945th value should be 0"); +assertEq(view[946], 0, "946th value should be 0"); +assertEq(view[947], 255, "947th value should be 255"); +assertEq(view[948], 154, "948th value should be 154"); +assertEq(view[949], 255, "949th value should be 255"); +assertEq(view[950], 101, "950th value should be 101"); +assertEq(view[951], 255, "951th value should be 255"); +assertEq(view[952], 179, "952th value should be 179"); +assertEq(view[953], 127, "953th value should be 127"); +assertEq(view[954], 76, "954th value should be 76"); +assertEq(view[955], 255, "955th value should be 255"); +assertEq(view[956], 205, "956th value should be 205"); +assertEq(view[957], 255, "957th value should be 255"); +assertEq(view[958], 50, "958th value should be 50"); +assertEq(view[959], 255, "959th value should be 255"); +assertEq(view[960], 179, "960th value should be 179"); +assertEq(view[961], 127, "961th value should be 127"); +assertEq(view[962], 76, "962th value should be 76"); +assertEq(view[963], 255, "963th value should be 255"); +assertEq(view[964], 179, "964th value should be 179"); +assertEq(view[965], 127, "965th value should be 127"); +assertEq(view[966], 76, "966th value should be 76"); +assertEq(view[967], 255, "967th value should be 255"); +assertEq(view[968], 179, "968th value should be 179"); +assertEq(view[969], 127, "969th value should be 127"); +assertEq(view[970], 76, "970th value should be 76"); +assertEq(view[971], 255, "971th value should be 255"); +assertEq(view[972], 154, "972th value should be 154"); +assertEq(view[973], 255, "973th value should be 255"); +assertEq(view[974], 101, "974th value should be 101"); +assertEq(view[975], 255, "975th value should be 255"); +assertEq(view[976], 103, "976th value should be 103"); +assertEq(view[977], 255, "977th value should be 255"); +assertEq(view[978], 152, "978th value should be 152"); +assertEq(view[979], 255, "979th value should be 255"); +assertEq(view[980], 0, "980th value should be 0"); +assertEq(view[981], 0, "981th value should be 0"); +assertEq(view[982], 0, "982th value should be 0"); +assertEq(view[983], 255, "983th value should be 255"); +assertEq(view[984], 0, "984th value should be 0"); +assertEq(view[985], 0, "985th value should be 0"); +assertEq(view[986], 0, "986th value should be 0"); +assertEq(view[987], 255, "987th value should be 255"); +assertEq(view[988], 0, "988th value should be 0"); +assertEq(view[989], 0, "989th value should be 0"); +assertEq(view[990], 0, "990th value should be 0"); +assertEq(view[991], 255, "991th value should be 255"); +assertEq(view[992], 0, "992th value should be 0"); +assertEq(view[993], 0, "993th value should be 0"); +assertEq(view[994], 0, "994th value should be 0"); +assertEq(view[995], 255, "995th value should be 255"); +assertEq(view[996], 0, "996th value should be 0"); +assertEq(view[997], 0, "997th value should be 0"); +assertEq(view[998], 0, "998th value should be 0"); +assertEq(view[999], 255, "999th value should be 255"); +assertEq(view[1000], 0, "1000th value should be 0"); +assertEq(view[1001], 0, "1001th value should be 0"); +assertEq(view[1002], 0, "1002th value should be 0"); +assertEq(view[1003], 255, "1003th value should be 255"); +assertEq(view[1004], 0, "1004th value should be 0"); +assertEq(view[1005], 0, "1005th value should be 0"); +assertEq(view[1006], 0, "1006th value should be 0"); +assertEq(view[1007], 255, "1007th value should be 255"); +assertEq(view[1008], 0, "1008th value should be 0"); +assertEq(view[1009], 0, "1009th value should be 0"); +assertEq(view[1010], 0, "1010th value should be 0"); +assertEq(view[1011], 255, "1011th value should be 255"); +assertEq(view[1012], 0, "1012th value should be 0"); +assertEq(view[1013], 0, "1013th value should be 0"); +assertEq(view[1014], 0, "1014th value should be 0"); +assertEq(view[1015], 255, "1015th value should be 255"); +assertEq(view[1016], 0, "1016th value should be 0"); +assertEq(view[1017], 0, "1017th value should be 0"); +assertEq(view[1018], 0, "1018th value should be 0"); +assertEq(view[1019], 255, "1019th value should be 255"); +assertEq(view[1020], 0, "1020th value should be 0"); +assertEq(view[1021], 0, "1021th value should be 0"); +assertEq(view[1022], 0, "1022th value should be 0"); +assertEq(view[1023], 255, "1023th value should be 255"); +assertEq(view[1024], 0, "1024th value should be 0"); +assertEq(view[1025], 0, "1025th value should be 0"); +assertEq(view[1026], 0, "1026th value should be 0"); +assertEq(view[1027], 255, "1027th value should be 255"); +assertEq(view[1028], 154, "1028th value should be 154"); +assertEq(view[1029], 255, "1029th value should be 255"); +assertEq(view[1030], 101, "1030th value should be 101"); +assertEq(view[1031], 255, "1031th value should be 255"); +assertEq(view[1032], 205, "1032th value should be 205"); +assertEq(view[1033], 255, "1033th value should be 255"); +assertEq(view[1034], 50, "1034th value should be 50"); +assertEq(view[1035], 255, "1035th value should be 255"); +assertEq(view[1036], 205, "1036th value should be 205"); +assertEq(view[1037], 255, "1037th value should be 255"); +assertEq(view[1038], 50, "1038th value should be 50"); +assertEq(view[1039], 255, "1039th value should be 255"); +assertEq(view[1040], 205, "1040th value should be 205"); +assertEq(view[1041], 255, "1041th value should be 255"); +assertEq(view[1042], 50, "1042th value should be 50"); +assertEq(view[1043], 255, "1043th value should be 255"); +assertEq(view[1044], 179, "1044th value should be 179"); +assertEq(view[1045], 127, "1045th value should be 127"); +assertEq(view[1046], 76, "1046th value should be 76"); +assertEq(view[1047], 255, "1047th value should be 255"); +assertEq(view[1048], 179, "1048th value should be 179"); +assertEq(view[1049], 127, "1049th value should be 127"); +assertEq(view[1050], 76, "1050th value should be 76"); +assertEq(view[1051], 255, "1051th value should be 255"); +assertEq(view[1052], 154, "1052th value should be 154"); +assertEq(view[1053], 255, "1053th value should be 255"); +assertEq(view[1054], 101, "1054th value should be 101"); +assertEq(view[1055], 255, "1055th value should be 255"); +assertEq(view[1056], 128, "1056th value should be 128"); +assertEq(view[1057], 127, "1057th value should be 127"); +assertEq(view[1058], 127, "1058th value should be 127"); +assertEq(view[1059], 255, "1059th value should be 255"); +assertEq(view[1060], 0, "1060th value should be 0"); +assertEq(view[1061], 0, "1061th value should be 0"); +assertEq(view[1062], 0, "1062th value should be 0"); +assertEq(view[1063], 255, "1063th value should be 255"); +assertEq(view[1064], 0, "1064th value should be 0"); +assertEq(view[1065], 0, "1065th value should be 0"); +assertEq(view[1066], 0, "1066th value should be 0"); +assertEq(view[1067], 255, "1067th value should be 255"); +assertEq(view[1068], 26, "1068th value should be 26"); +assertEq(view[1069], 127, "1069th value should be 127"); +assertEq(view[1070], 229, "1070th value should be 229"); +assertEq(view[1071], 255, "1071th value should be 255"); +assertEq(view[1072], 26, "1072th value should be 26"); +assertEq(view[1073], 127, "1073th value should be 127"); +assertEq(view[1074], 229, "1074th value should be 229"); +assertEq(view[1075], 255, "1075th value should be 255"); +assertEq(view[1076], 0, "1076th value should be 0"); +assertEq(view[1077], 0, "1077th value should be 0"); +assertEq(view[1078], 0, "1078th value should be 0"); +assertEq(view[1079], 255, "1079th value should be 255"); +assertEq(view[1080], 0, "1080th value should be 0"); +assertEq(view[1081], 0, "1081th value should be 0"); +assertEq(view[1082], 0, "1082th value should be 0"); +assertEq(view[1083], 255, "1083th value should be 255"); +assertEq(view[1084], 0, "1084th value should be 0"); +assertEq(view[1085], 0, "1085th value should be 0"); +assertEq(view[1086], 0, "1086th value should be 0"); +assertEq(view[1087], 255, "1087th value should be 255"); +assertEq(view[1088], 0, "1088th value should be 0"); +assertEq(view[1089], 0, "1089th value should be 0"); +assertEq(view[1090], 0, "1090th value should be 0"); +assertEq(view[1091], 255, "1091th value should be 255"); +assertEq(view[1092], 0, "1092th value should be 0"); +assertEq(view[1093], 0, "1093th value should be 0"); +assertEq(view[1094], 0, "1094th value should be 0"); +assertEq(view[1095], 255, "1095th value should be 255"); +assertEq(view[1096], 0, "1096th value should be 0"); +assertEq(view[1097], 0, "1097th value should be 0"); +assertEq(view[1098], 0, "1098th value should be 0"); +assertEq(view[1099], 255, "1099th value should be 255"); +assertEq(view[1100], 0, "1100th value should be 0"); +assertEq(view[1101], 0, "1101th value should be 0"); +assertEq(view[1102], 0, "1102th value should be 0"); +assertEq(view[1103], 255, "1103th value should be 255"); +assertEq(view[1104], 0, "1104th value should be 0"); +assertEq(view[1105], 0, "1105th value should be 0"); +assertEq(view[1106], 0, "1106th value should be 0"); +assertEq(view[1107], 255, "1107th value should be 255"); +assertEq(view[1108], 154, "1108th value should be 154"); +assertEq(view[1109], 255, "1109th value should be 255"); +assertEq(view[1110], 101, "1110th value should be 101"); +assertEq(view[1111], 255, "1111th value should be 255"); +assertEq(view[1112], 205, "1112th value should be 205"); +assertEq(view[1113], 255, "1113th value should be 255"); +assertEq(view[1114], 50, "1114th value should be 50"); +assertEq(view[1115], 255, "1115th value should be 255"); +assertEq(view[1116], 205, "1116th value should be 205"); +assertEq(view[1117], 255, "1117th value should be 255"); +assertEq(view[1118], 50, "1118th value should be 50"); +assertEq(view[1119], 255, "1119th value should be 255"); +assertEq(view[1120], 205, "1120th value should be 205"); +assertEq(view[1121], 255, "1121th value should be 255"); +assertEq(view[1122], 50, "1122th value should be 50"); +assertEq(view[1123], 255, "1123th value should be 255"); +assertEq(view[1124], 205, "1124th value should be 205"); +assertEq(view[1125], 255, "1125th value should be 255"); +assertEq(view[1126], 50, "1126th value should be 50"); +assertEq(view[1127], 255, "1127th value should be 255"); +assertEq(view[1128], 205, "1128th value should be 205"); +assertEq(view[1129], 255, "1129th value should be 255"); +assertEq(view[1130], 50, "1130th value should be 50"); +assertEq(view[1131], 255, "1131th value should be 255"); +assertEq(view[1132], 179, "1132th value should be 179"); +assertEq(view[1133], 127, "1133th value should be 127"); +assertEq(view[1134], 76, "1134th value should be 76"); +assertEq(view[1135], 255, "1135th value should be 255"); +assertEq(view[1136], 154, "1136th value should be 154"); +assertEq(view[1137], 255, "1137th value should be 255"); +assertEq(view[1138], 101, "1138th value should be 101"); +assertEq(view[1139], 255, "1139th value should be 255"); +assertEq(view[1140], 128, "1140th value should be 128"); +assertEq(view[1141], 127, "1141th value should be 127"); +assertEq(view[1142], 127, "1142th value should be 127"); +assertEq(view[1143], 255, "1143th value should be 255"); +assertEq(view[1144], 128, "1144th value should be 128"); +assertEq(view[1145], 127, "1145th value should be 127"); +assertEq(view[1146], 127, "1146th value should be 127"); +assertEq(view[1147], 255, "1147th value should be 255"); +assertEq(view[1148], 103, "1148th value should be 103"); +assertEq(view[1149], 255, "1149th value should be 255"); +assertEq(view[1150], 152, "1150th value should be 152"); +assertEq(view[1151], 255, "1151th value should be 255"); +assertEq(view[1152], 78, "1152th value should be 78"); +assertEq(view[1153], 127, "1153th value should be 127"); +assertEq(view[1154], 178, "1154th value should be 178"); +assertEq(view[1155], 255, "1155th value should be 255"); +assertEq(view[1156], 0, "1156th value should be 0"); +assertEq(view[1157], 0, "1157th value should be 0"); +assertEq(view[1158], 0, "1158th value should be 0"); +assertEq(view[1159], 255, "1159th value should be 255"); +assertEq(view[1160], 0, "1160th value should be 0"); +assertEq(view[1161], 0, "1161th value should be 0"); +assertEq(view[1162], 0, "1162th value should be 0"); +assertEq(view[1163], 255, "1163th value should be 255"); +assertEq(view[1164], 0, "1164th value should be 0"); +assertEq(view[1165], 0, "1165th value should be 0"); +assertEq(view[1166], 0, "1166th value should be 0"); +assertEq(view[1167], 255, "1167th value should be 255"); +assertEq(view[1168], 0, "1168th value should be 0"); +assertEq(view[1169], 0, "1169th value should be 0"); +assertEq(view[1170], 0, "1170th value should be 0"); +assertEq(view[1171], 255, "1171th value should be 255"); +assertEq(view[1172], 0, "1172th value should be 0"); +assertEq(view[1173], 0, "1173th value should be 0"); +assertEq(view[1174], 0, "1174th value should be 0"); +assertEq(view[1175], 255, "1175th value should be 255"); +assertEq(view[1176], 0, "1176th value should be 0"); +assertEq(view[1177], 0, "1177th value should be 0"); +assertEq(view[1178], 0, "1178th value should be 0"); +assertEq(view[1179], 255, "1179th value should be 255"); +assertEq(view[1180], 0, "1180th value should be 0"); +assertEq(view[1181], 0, "1181th value should be 0"); +assertEq(view[1182], 0, "1182th value should be 0"); +assertEq(view[1183], 255, "1183th value should be 255"); +assertEq(view[1184], 26, "1184th value should be 26"); +assertEq(view[1185], 127, "1185th value should be 127"); +assertEq(view[1186], 229, "1186th value should be 229"); +assertEq(view[1187], 255, "1187th value should be 255"); +assertEq(view[1188], 154, "1188th value should be 154"); +assertEq(view[1189], 255, "1189th value should be 255"); +assertEq(view[1190], 101, "1190th value should be 101"); +assertEq(view[1191], 255, "1191th value should be 255"); +assertEq(view[1192], 205, "1192th value should be 205"); +assertEq(view[1193], 255, "1193th value should be 255"); +assertEq(view[1194], 50, "1194th value should be 50"); +assertEq(view[1195], 255, "1195th value should be 255"); +assertEq(view[1196], 205, "1196th value should be 205"); +assertEq(view[1197], 255, "1197th value should be 255"); +assertEq(view[1198], 50, "1198th value should be 50"); +assertEq(view[1199], 255, "1199th value should be 255"); +assertEq(view[1200], 230, "1200th value should be 230"); +assertEq(view[1201], 127, "1201th value should be 127"); +assertEq(view[1202], 25, "1202th value should be 25"); +assertEq(view[1203], 255, "1203th value should be 255"); +assertEq(view[1204], 205, "1204th value should be 205"); +assertEq(view[1205], 255, "1205th value should be 255"); +assertEq(view[1206], 50, "1206th value should be 50"); +assertEq(view[1207], 255, "1207th value should be 255"); +assertEq(view[1208], 205, "1208th value should be 205"); +assertEq(view[1209], 255, "1209th value should be 255"); +assertEq(view[1210], 50, "1210th value should be 50"); +assertEq(view[1211], 255, "1211th value should be 255"); +assertEq(view[1212], 205, "1212th value should be 205"); +assertEq(view[1213], 255, "1213th value should be 255"); +assertEq(view[1214], 50, "1214th value should be 50"); +assertEq(view[1215], 255, "1215th value should be 255"); +assertEq(view[1216], 205, "1216th value should be 205"); +assertEq(view[1217], 255, "1217th value should be 255"); +assertEq(view[1218], 50, "1218th value should be 50"); +assertEq(view[1219], 255, "1219th value should be 255"); +assertEq(view[1220], 154, "1220th value should be 154"); +assertEq(view[1221], 255, "1221th value should be 255"); +assertEq(view[1222], 101, "1222th value should be 101"); +assertEq(view[1223], 255, "1223th value should be 255"); +assertEq(view[1224], 154, "1224th value should be 154"); +assertEq(view[1225], 255, "1225th value should be 255"); +assertEq(view[1226], 101, "1226th value should be 101"); +assertEq(view[1227], 255, "1227th value should be 255"); +assertEq(view[1228], 154, "1228th value should be 154"); +assertEq(view[1229], 255, "1229th value should be 255"); +assertEq(view[1230], 101, "1230th value should be 101"); +assertEq(view[1231], 255, "1231th value should be 255"); +assertEq(view[1232], 128, "1232th value should be 128"); +assertEq(view[1233], 127, "1233th value should be 127"); +assertEq(view[1234], 127, "1234th value should be 127"); +assertEq(view[1235], 255, "1235th value should be 255"); +assertEq(view[1236], 26, "1236th value should be 26"); +assertEq(view[1237], 127, "1237th value should be 127"); +assertEq(view[1238], 229, "1238th value should be 229"); +assertEq(view[1239], 255, "1239th value should be 255"); +assertEq(view[1240], 0, "1240th value should be 0"); +assertEq(view[1241], 0, "1241th value should be 0"); +assertEq(view[1242], 0, "1242th value should be 0"); +assertEq(view[1243], 255, "1243th value should be 255"); +assertEq(view[1244], 0, "1244th value should be 0"); +assertEq(view[1245], 0, "1245th value should be 0"); +assertEq(view[1246], 0, "1246th value should be 0"); +assertEq(view[1247], 255, "1247th value should be 255"); +assertEq(view[1248], 0, "1248th value should be 0"); +assertEq(view[1249], 0, "1249th value should be 0"); +assertEq(view[1250], 0, "1250th value should be 0"); +assertEq(view[1251], 255, "1251th value should be 255"); +assertEq(view[1252], 0, "1252th value should be 0"); +assertEq(view[1253], 0, "1253th value should be 0"); +assertEq(view[1254], 0, "1254th value should be 0"); +assertEq(view[1255], 255, "1255th value should be 255"); +assertEq(view[1256], 0, "1256th value should be 0"); +assertEq(view[1257], 0, "1257th value should be 0"); +assertEq(view[1258], 0, "1258th value should be 0"); +assertEq(view[1259], 255, "1259th value should be 255"); +assertEq(view[1260], 0, "1260th value should be 0"); +assertEq(view[1261], 0, "1261th value should be 0"); +assertEq(view[1262], 0, "1262th value should be 0"); +assertEq(view[1263], 255, "1263th value should be 255"); +assertEq(view[1264], 78, "1264th value should be 78"); +assertEq(view[1265], 127, "1265th value should be 127"); +assertEq(view[1266], 178, "1266th value should be 178"); +assertEq(view[1267], 255, "1267th value should be 255"); +assertEq(view[1268], 179, "1268th value should be 179"); +assertEq(view[1269], 127, "1269th value should be 127"); +assertEq(view[1270], 76, "1270th value should be 76"); +assertEq(view[1271], 255, "1271th value should be 255"); +assertEq(view[1272], 205, "1272th value should be 205"); +assertEq(view[1273], 255, "1273th value should be 255"); +assertEq(view[1274], 50, "1274th value should be 50"); +assertEq(view[1275], 255, "1275th value should be 255"); +assertEq(view[1276], 205, "1276th value should be 205"); +assertEq(view[1277], 255, "1277th value should be 255"); +assertEq(view[1278], 50, "1278th value should be 50"); +assertEq(view[1279], 255, "1279th value should be 255"); +assertEq(view[1280], 0, "1280th value should be 0"); +assertEq(view[1281], 0, "1281th value should be 0"); +assertEq(view[1282], 0, "1282th value should be 0"); +assertEq(view[1283], 255, "1283th value should be 255"); +assertEq(view[1284], 205, "1284th value should be 205"); +assertEq(view[1285], 255, "1285th value should be 255"); +assertEq(view[1286], 50, "1286th value should be 50"); +assertEq(view[1287], 255, "1287th value should be 255"); +assertEq(view[1288], 205, "1288th value should be 205"); +assertEq(view[1289], 255, "1289th value should be 255"); +assertEq(view[1290], 50, "1290th value should be 50"); +assertEq(view[1291], 255, "1291th value should be 255"); +assertEq(view[1292], 205, "1292th value should be 205"); +assertEq(view[1293], 255, "1293th value should be 255"); +assertEq(view[1294], 50, "1294th value should be 50"); +assertEq(view[1295], 255, "1295th value should be 255"); +assertEq(view[1296], 205, "1296th value should be 205"); +assertEq(view[1297], 255, "1297th value should be 255"); +assertEq(view[1298], 50, "1298th value should be 50"); +assertEq(view[1299], 255, "1299th value should be 255"); +assertEq(view[1300], 205, "1300th value should be 205"); +assertEq(view[1301], 255, "1301th value should be 255"); +assertEq(view[1302], 50, "1302th value should be 50"); +assertEq(view[1303], 255, "1303th value should be 255"); +assertEq(view[1304], 179, "1304th value should be 179"); +assertEq(view[1305], 127, "1305th value should be 127"); +assertEq(view[1306], 76, "1306th value should be 76"); +assertEq(view[1307], 255, "1307th value should be 255"); +assertEq(view[1308], 154, "1308th value should be 154"); +assertEq(view[1309], 255, "1309th value should be 255"); +assertEq(view[1310], 101, "1310th value should be 101"); +assertEq(view[1311], 255, "1311th value should be 255"); +assertEq(view[1312], 154, "1312th value should be 154"); +assertEq(view[1313], 255, "1313th value should be 255"); +assertEq(view[1314], 101, "1314th value should be 101"); +assertEq(view[1315], 255, "1315th value should be 255"); +assertEq(view[1316], 0, "1316th value should be 0"); +assertEq(view[1317], 0, "1317th value should be 0"); +assertEq(view[1318], 0, "1318th value should be 0"); +assertEq(view[1319], 255, "1319th value should be 255"); +assertEq(view[1320], 0, "1320th value should be 0"); +assertEq(view[1321], 0, "1321th value should be 0"); +assertEq(view[1322], 0, "1322th value should be 0"); +assertEq(view[1323], 255, "1323th value should be 255"); +assertEq(view[1324], 0, "1324th value should be 0"); +assertEq(view[1325], 0, "1325th value should be 0"); +assertEq(view[1326], 0, "1326th value should be 0"); +assertEq(view[1327], 255, "1327th value should be 255"); +assertEq(view[1328], 0, "1328th value should be 0"); +assertEq(view[1329], 0, "1329th value should be 0"); +assertEq(view[1330], 0, "1330th value should be 0"); +assertEq(view[1331], 255, "1331th value should be 255"); +assertEq(view[1332], 0, "1332th value should be 0"); +assertEq(view[1333], 0, "1333th value should be 0"); +assertEq(view[1334], 0, "1334th value should be 0"); +assertEq(view[1335], 255, "1335th value should be 255"); +assertEq(view[1336], 0, "1336th value should be 0"); +assertEq(view[1337], 0, "1337th value should be 0"); +assertEq(view[1338], 0, "1338th value should be 0"); +assertEq(view[1339], 255, "1339th value should be 255"); +assertEq(view[1340], 0, "1340th value should be 0"); +assertEq(view[1341], 0, "1341th value should be 0"); +assertEq(view[1342], 0, "1342th value should be 0"); +assertEq(view[1343], 255, "1343th value should be 255"); +assertEq(view[1344], 0, "1344th value should be 0"); +assertEq(view[1345], 0, "1345th value should be 0"); +assertEq(view[1346], 0, "1346th value should be 0"); +assertEq(view[1347], 255, "1347th value should be 255"); +assertEq(view[1348], 179, "1348th value should be 179"); +assertEq(view[1349], 127, "1349th value should be 127"); +assertEq(view[1350], 76, "1350th value should be 76"); +assertEq(view[1351], 255, "1351th value should be 255"); +assertEq(view[1352], 205, "1352th value should be 205"); +assertEq(view[1353], 255, "1353th value should be 255"); +assertEq(view[1354], 50, "1354th value should be 50"); +assertEq(view[1355], 255, "1355th value should be 255"); +assertEq(view[1356], 205, "1356th value should be 205"); +assertEq(view[1357], 255, "1357th value should be 255"); +assertEq(view[1358], 50, "1358th value should be 50"); +assertEq(view[1359], 255, "1359th value should be 255"); +assertEq(view[1360], 0, "1360th value should be 0"); +assertEq(view[1361], 0, "1361th value should be 0"); +assertEq(view[1362], 0, "1362th value should be 0"); +assertEq(view[1363], 255, "1363th value should be 255"); +assertEq(view[1364], 205, "1364th value should be 205"); +assertEq(view[1365], 255, "1365th value should be 255"); +assertEq(view[1366], 50, "1366th value should be 50"); +assertEq(view[1367], 255, "1367th value should be 255"); +assertEq(view[1368], 205, "1368th value should be 205"); +assertEq(view[1369], 255, "1369th value should be 255"); +assertEq(view[1370], 50, "1370th value should be 50"); +assertEq(view[1371], 255, "1371th value should be 255"); +assertEq(view[1372], 205, "1372th value should be 205"); +assertEq(view[1373], 255, "1373th value should be 255"); +assertEq(view[1374], 50, "1374th value should be 50"); +assertEq(view[1375], 255, "1375th value should be 255"); +assertEq(view[1376], 205, "1376th value should be 205"); +assertEq(view[1377], 255, "1377th value should be 255"); +assertEq(view[1378], 50, "1378th value should be 50"); +assertEq(view[1379], 255, "1379th value should be 255"); +assertEq(view[1380], 205, "1380th value should be 205"); +assertEq(view[1381], 255, "1381th value should be 255"); +assertEq(view[1382], 50, "1382th value should be 50"); +assertEq(view[1383], 255, "1383th value should be 255"); +assertEq(view[1384], 205, "1384th value should be 205"); +assertEq(view[1385], 255, "1385th value should be 255"); +assertEq(view[1386], 50, "1386th value should be 50"); +assertEq(view[1387], 255, "1387th value should be 255"); +assertEq(view[1388], 179, "1388th value should be 179"); +assertEq(view[1389], 127, "1389th value should be 127"); +assertEq(view[1390], 76, "1390th value should be 76"); +assertEq(view[1391], 255, "1391th value should be 255"); +assertEq(view[1392], 179, "1392th value should be 179"); +assertEq(view[1393], 127, "1393th value should be 127"); +assertEq(view[1394], 76, "1394th value should be 76"); +assertEq(view[1395], 255, "1395th value should be 255"); +assertEq(view[1396], 103, "1396th value should be 103"); +assertEq(view[1397], 255, "1397th value should be 255"); +assertEq(view[1398], 152, "1398th value should be 152"); +assertEq(view[1399], 255, "1399th value should be 255"); +assertEq(view[1400], 78, "1400th value should be 78"); +assertEq(view[1401], 127, "1401th value should be 127"); +assertEq(view[1402], 178, "1402th value should be 178"); +assertEq(view[1403], 255, "1403th value should be 255"); +assertEq(view[1404], 52, "1404th value should be 52"); +assertEq(view[1405], 255, "1405th value should be 255"); +assertEq(view[1406], 203, "1406th value should be 203"); +assertEq(view[1407], 255, "1407th value should be 255"); +assertEq(view[1408], 0, "1408th value should be 0"); +assertEq(view[1409], 0, "1409th value should be 0"); +assertEq(view[1410], 0, "1410th value should be 0"); +assertEq(view[1411], 255, "1411th value should be 255"); +assertEq(view[1412], 0, "1412th value should be 0"); +assertEq(view[1413], 0, "1413th value should be 0"); +assertEq(view[1414], 0, "1414th value should be 0"); +assertEq(view[1415], 255, "1415th value should be 255"); +assertEq(view[1416], 52, "1416th value should be 52"); +assertEq(view[1417], 255, "1417th value should be 255"); +assertEq(view[1418], 203, "1418th value should be 203"); +assertEq(view[1419], 255, "1419th value should be 255"); +assertEq(view[1420], 128, "1420th value should be 128"); +assertEq(view[1421], 127, "1421th value should be 127"); +assertEq(view[1422], 127, "1422th value should be 127"); +assertEq(view[1423], 255, "1423th value should be 255"); +assertEq(view[1424], 128, "1424th value should be 128"); +assertEq(view[1425], 127, "1425th value should be 127"); +assertEq(view[1426], 127, "1426th value should be 127"); +assertEq(view[1427], 255, "1427th value should be 255"); +assertEq(view[1428], 205, "1428th value should be 205"); +assertEq(view[1429], 255, "1429th value should be 255"); +assertEq(view[1430], 50, "1430th value should be 50"); +assertEq(view[1431], 255, "1431th value should be 255"); +assertEq(view[1432], 205, "1432th value should be 205"); +assertEq(view[1433], 255, "1433th value should be 255"); +assertEq(view[1434], 50, "1434th value should be 50"); +assertEq(view[1435], 255, "1435th value should be 255"); +assertEq(view[1436], 230, "1436th value should be 230"); +assertEq(view[1437], 127, "1437th value should be 127"); +assertEq(view[1438], 25, "1438th value should be 25"); +assertEq(view[1439], 255, "1439th value should be 255"); +assertEq(view[1440], 0, "1440th value should be 0"); +assertEq(view[1441], 0, "1441th value should be 0"); +assertEq(view[1442], 0, "1442th value should be 0"); +assertEq(view[1443], 255, "1443th value should be 255"); +assertEq(view[1444], 230, "1444th value should be 230"); +assertEq(view[1445], 127, "1445th value should be 127"); +assertEq(view[1446], 25, "1446th value should be 25"); +assertEq(view[1447], 255, "1447th value should be 255"); +assertEq(view[1448], 205, "1448th value should be 205"); +assertEq(view[1449], 255, "1449th value should be 255"); +assertEq(view[1450], 50, "1450th value should be 50"); +assertEq(view[1451], 255, "1451th value should be 255"); +assertEq(view[1452], 205, "1452th value should be 205"); +assertEq(view[1453], 255, "1453th value should be 255"); +assertEq(view[1454], 50, "1454th value should be 50"); +assertEq(view[1455], 255, "1455th value should be 255"); +assertEq(view[1456], 205, "1456th value should be 205"); +assertEq(view[1457], 255, "1457th value should be 255"); +assertEq(view[1458], 50, "1458th value should be 50"); +assertEq(view[1459], 255, "1459th value should be 255"); +assertEq(view[1460], 205, "1460th value should be 205"); +assertEq(view[1461], 255, "1461th value should be 255"); +assertEq(view[1462], 50, "1462th value should be 50"); +assertEq(view[1463], 255, "1463th value should be 255"); +assertEq(view[1464], 205, "1464th value should be 205"); +assertEq(view[1465], 255, "1465th value should be 255"); +assertEq(view[1466], 50, "1466th value should be 50"); +assertEq(view[1467], 255, "1467th value should be 255"); +assertEq(view[1468], 179, "1468th value should be 179"); +assertEq(view[1469], 127, "1469th value should be 127"); +assertEq(view[1470], 76, "1470th value should be 76"); +assertEq(view[1471], 255, "1471th value should be 255"); +assertEq(view[1472], 179, "1472th value should be 179"); +assertEq(view[1473], 127, "1473th value should be 127"); +assertEq(view[1474], 76, "1474th value should be 76"); +assertEq(view[1475], 255, "1475th value should be 255"); +assertEq(view[1476], 179, "1476th value should be 179"); +assertEq(view[1477], 127, "1477th value should be 127"); +assertEq(view[1478], 76, "1478th value should be 76"); +assertEq(view[1479], 255, "1479th value should be 255"); +assertEq(view[1480], 128, "1480th value should be 128"); +assertEq(view[1481], 127, "1481th value should be 127"); +assertEq(view[1482], 127, "1482th value should be 127"); +assertEq(view[1483], 255, "1483th value should be 255"); +assertEq(view[1484], 103, "1484th value should be 103"); +assertEq(view[1485], 255, "1485th value should be 255"); +assertEq(view[1486], 152, "1486th value should be 152"); +assertEq(view[1487], 255, "1487th value should be 255"); +assertEq(view[1488], 0, "1488th value should be 0"); +assertEq(view[1489], 0, "1489th value should be 0"); +assertEq(view[1490], 0, "1490th value should be 0"); +assertEq(view[1491], 255, "1491th value should be 255"); +assertEq(view[1492], 0, "1492th value should be 0"); +assertEq(view[1493], 0, "1493th value should be 0"); +assertEq(view[1494], 0, "1494th value should be 0"); +assertEq(view[1495], 255, "1495th value should be 255"); +assertEq(view[1496], 128, "1496th value should be 128"); +assertEq(view[1497], 127, "1497th value should be 127"); +assertEq(view[1498], 127, "1498th value should be 127"); +assertEq(view[1499], 255, "1499th value should be 255"); +assertEq(view[1500], 154, "1500th value should be 154"); +assertEq(view[1501], 255, "1501th value should be 255"); +assertEq(view[1502], 101, "1502th value should be 101"); +assertEq(view[1503], 255, "1503th value should be 255"); +assertEq(view[1504], 179, "1504th value should be 179"); +assertEq(view[1505], 127, "1505th value should be 127"); +assertEq(view[1506], 76, "1506th value should be 76"); +assertEq(view[1507], 255, "1507th value should be 255"); +assertEq(view[1508], 205, "1508th value should be 205"); +assertEq(view[1509], 255, "1509th value should be 255"); +assertEq(view[1510], 50, "1510th value should be 50"); +assertEq(view[1511], 255, "1511th value should be 255"); +assertEq(view[1512], 205, "1512th value should be 205"); +assertEq(view[1513], 255, "1513th value should be 255"); +assertEq(view[1514], 50, "1514th value should be 50"); +assertEq(view[1515], 255, "1515th value should be 255"); +assertEq(view[1516], 230, "1516th value should be 230"); +assertEq(view[1517], 127, "1517th value should be 127"); +assertEq(view[1518], 25, "1518th value should be 25"); +assertEq(view[1519], 255, "1519th value should be 255"); +assertEq(view[1520], 0, "1520th value should be 0"); +assertEq(view[1521], 0, "1521th value should be 0"); +assertEq(view[1522], 0, "1522th value should be 0"); +assertEq(view[1523], 255, "1523th value should be 255"); +assertEq(view[1524], 230, "1524th value should be 230"); +assertEq(view[1525], 127, "1525th value should be 127"); +assertEq(view[1526], 25, "1526th value should be 25"); +assertEq(view[1527], 255, "1527th value should be 255"); +assertEq(view[1528], 230, "1528th value should be 230"); +assertEq(view[1529], 127, "1529th value should be 127"); +assertEq(view[1530], 25, "1530th value should be 25"); +assertEq(view[1531], 255, "1531th value should be 255"); +assertEq(view[1532], 205, "1532th value should be 205"); +assertEq(view[1533], 255, "1533th value should be 255"); +assertEq(view[1534], 50, "1534th value should be 50"); +assertEq(view[1535], 255, "1535th value should be 255"); +assertEq(view[1536], 205, "1536th value should be 205"); +assertEq(view[1537], 255, "1537th value should be 255"); +assertEq(view[1538], 50, "1538th value should be 50"); +assertEq(view[1539], 255, "1539th value should be 255"); +assertEq(view[1540], 205, "1540th value should be 205"); +assertEq(view[1541], 255, "1541th value should be 255"); +assertEq(view[1542], 50, "1542th value should be 50"); +assertEq(view[1543], 255, "1543th value should be 255"); +assertEq(view[1544], 205, "1544th value should be 205"); +assertEq(view[1545], 255, "1545th value should be 255"); +assertEq(view[1546], 50, "1546th value should be 50"); +assertEq(view[1547], 255, "1547th value should be 255"); +assertEq(view[1548], 205, "1548th value should be 205"); +assertEq(view[1549], 255, "1549th value should be 255"); +assertEq(view[1550], 50, "1550th value should be 50"); +assertEq(view[1551], 255, "1551th value should be 255"); +assertEq(view[1552], 179, "1552th value should be 179"); +assertEq(view[1553], 127, "1553th value should be 127"); +assertEq(view[1554], 76, "1554th value should be 76"); +assertEq(view[1555], 255, "1555th value should be 255"); +assertEq(view[1556], 179, "1556th value should be 179"); +assertEq(view[1557], 127, "1557th value should be 127"); +assertEq(view[1558], 76, "1558th value should be 76"); +assertEq(view[1559], 255, "1559th value should be 255"); +assertEq(view[1560], 179, "1560th value should be 179"); +assertEq(view[1561], 127, "1561th value should be 127"); +assertEq(view[1562], 76, "1562th value should be 76"); +assertEq(view[1563], 255, "1563th value should be 255"); +assertEq(view[1564], 154, "1564th value should be 154"); +assertEq(view[1565], 255, "1565th value should be 255"); +assertEq(view[1566], 101, "1566th value should be 101"); +assertEq(view[1567], 255, "1567th value should be 255"); +assertEq(view[1568], 26, "1568th value should be 26"); +assertEq(view[1569], 127, "1569th value should be 127"); +assertEq(view[1570], 229, "1570th value should be 229"); +assertEq(view[1571], 255, "1571th value should be 255"); +assertEq(view[1572], 0, "1572th value should be 0"); +assertEq(view[1573], 0, "1573th value should be 0"); +assertEq(view[1574], 0, "1574th value should be 0"); +assertEq(view[1575], 255, "1575th value should be 255"); +assertEq(view[1576], 154, "1576th value should be 154"); +assertEq(view[1577], 255, "1577th value should be 255"); +assertEq(view[1578], 101, "1578th value should be 101"); +assertEq(view[1579], 255, "1579th value should be 255"); +assertEq(view[1580], 179, "1580th value should be 179"); +assertEq(view[1581], 127, "1581th value should be 127"); +assertEq(view[1582], 76, "1582th value should be 76"); +assertEq(view[1583], 255, "1583th value should be 255"); +assertEq(view[1584], 205, "1584th value should be 205"); +assertEq(view[1585], 255, "1585th value should be 255"); +assertEq(view[1586], 50, "1586th value should be 50"); +assertEq(view[1587], 255, "1587th value should be 255"); +assertEq(view[1588], 205, "1588th value should be 205"); +assertEq(view[1589], 255, "1589th value should be 255"); +assertEq(view[1590], 50, "1590th value should be 50"); +assertEq(view[1591], 255, "1591th value should be 255"); +assertEq(view[1592], 230, "1592th value should be 230"); +assertEq(view[1593], 127, "1593th value should be 127"); +assertEq(view[1594], 25, "1594th value should be 25"); +assertEq(view[1595], 255, "1595th value should be 255"); +assertEq(view[1596], 230, "1596th value should be 230"); +assertEq(view[1597], 127, "1597th value should be 127"); +assertEq(view[1598], 25, "1598th value should be 25"); +assertEq(view[1599], 255, "1599th value should be 255"); + +// Code used to generate the assertEq list above. +function generateAssertList() { + function template(i, x) { + return 'assertEq(view[' + i + '], ' + x + ', "' + i + 'th value should be ' + x + '");\n'; + } + var buf = '' + for (var i = 0; i < LIMIT_SHOW; i++) + buf += template(i, view[i]); + print(buf); +} +//generateAssertList(); diff --git a/js/src/jit-test/tests/asm.js/sta-transition.js b/js/src/jit-test/tests/asm.js/sta-transition.js new file mode 100644 index 000000000..9c33da5e2 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/sta-transition.js @@ -0,0 +1,63 @@ +// Test the inference of shared memory in asm.js. +// +// These should not be run with --no-asmjs, the guard below checks this. + +load(libdir + "asm.js"); + +if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable()) + quit(0); + +setJitCompilerOption('asmjs.atomics.enable', 1); + +////////////////////////////////////////////////////////////////////// +// +// Int8Array can be used on SharedArrayBuffer, if atomics are present + +var m1 = asmCompile("stdlib", "ffi", "heap", ` + "use asm"; + + var i8 = new stdlib.Int8Array(heap); + var add = stdlib.Atomics.add; + + function f() { + add(i8, 0, 1); + return 37; + } + + return { f:f } +`); + +assertEq(isAsmJSModule(m1), true); + +var { f } = m1(this, {}, new SharedArrayBuffer(65536)); +assertEq(f(), 37); + +////////////////////////////////////////////////////////////////////// +// +// Int8Array cannot be used on SharedArrayBuffer if atomics are not imported. +// One argument for the restriction is that there are some optimizations +// that are legal if the memory is known not to be shared that are illegal +// when it is shared. + +var m4 = asmCompile("stdlib", "ffi", "heap", ` + "use asm"; + + var i8 = new stdlib.Int8Array(heap); + + function i() { + return i8[0]|0; + } + + return { i:i } +`); + +assertEq(isAsmJSModule(m4), true); + +// An error is not actually thrown because the link failure drops us +// back to JS execution and then the Int8Array constructor will copy data +// from the SharedArrayBuffer. +// +// Running the shell with -w you should see an error here. + +var { i } = m4(this, {}, new SharedArrayBuffer(65536)); +assertEq(isAsmJSFunction(i), false); diff --git a/js/src/jit-test/tests/asm.js/testAddressErrors.js b/js/src/jit-test/tests/asm.js/testAddressErrors.js new file mode 100644 index 000000000..063939f43 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testAddressErrors.js @@ -0,0 +1,47 @@ +load(libdir + "asm.js"); + +setIonCheckGraphCoherency(false); +setCachingEnabled(false); + +// constants +var buf = new ArrayBuffer(BUF_MIN); + +// An unshifted literal constant byte index in the range 0 to 2^31-1 inclusive should give a link failure. +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x7fffffff]|0 } return f'), this, null, buf); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x1fffffff]|0 } return f'), this, null, buf); + + +// An unshifted literal constant byte index outside the range 0 to 2^31-1 inclusive should cause an error compiling. +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x20000000]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x3fffffff]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x40000000]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x7fffffff]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x80000000]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x8fffffff]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0xffffffff]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x100000000]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x80000000]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0xffffffff]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x100000000]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int16Array(b); function f() {return arr[-1]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[-2]|0 } return f'); + +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[10-12]|0 } return f'); + +// An intish shifted literal constant index should not fail to compile or link. +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x3fffffff>>0]|0 } return f'), this, null, buf)(), 0); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x3fffffff>>2]|0 } return f'), this, null, buf)(), 0); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0xffffffff>>0]|0 } return f'), this, null, buf)(), 0); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0xffffffff>>2]|0 } return f'), this, null, buf)(), 0); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[-1>>0]|0 } return f'), this, null, buf)(), 0); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[-1>>2]|0 } return f'), this, null, buf)(), 0); +// Unsigned (intish) folded constant index. +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0xffffffff>>>0]|0 } return f'), this, null, buf)(), 0); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {arr[0] = 1; return arr[(0xffffffff+1)>>>0]|0 } return f'), this, null, buf)(), 1); + +// A non-intish shifted literal constant index should cause an error compiling. +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x100000000>>0]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x100000000>>2]|0 } return f'); + +// Folded non-intish constant expressions should cause an error compiling. +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0xffffffff+1]|0 } return f'); diff --git a/js/src/jit-test/tests/asm.js/testAsmJSWasmMixing.js b/js/src/jit-test/tests/asm.js/testAsmJSWasmMixing.js new file mode 100644 index 000000000..e82b3e417 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testAsmJSWasmMixing.js @@ -0,0 +1,25 @@ +load(libdir + "asm.js"); +load(libdir + "wasm.js"); + +const Module = WebAssembly.Module; +const Instance = WebAssembly.Instance; +const Memory = WebAssembly.Memory; + +var asmJS = asmCompile('stdlib', 'ffis', 'buf', USE_ASM + 'var i32 = new stdlib.Int32Array(buf); return {}'); + +var asmJSBuf = new ArrayBuffer(BUF_MIN); +asmLink(asmJS, this, null, asmJSBuf); + +var wasmMem = wasmEvalText('(module (memory 1 1) (export "mem" memory))').exports.mem; +assertAsmLinkFail(asmJS, this, null, wasmMem.buffer); + +if (!getBuildConfiguration().x64 && isSimdAvailable() && this["SIMD"]) { + var simdJS = asmCompile('stdlib', 'ffis', 'buf', USE_ASM + 'var i32 = new stdlib.Int32Array(buf); var i32x4 = stdlib.SIMD.Int32x4; return {}'); + assertAsmLinkFail(simdJS, this, null, asmJSBuf); + assertAsmLinkFail(simdJS, this, null, wasmMem.buffer); + + var simdJSBuf = new ArrayBuffer(BUF_MIN); + asmLink(simdJS, this, null, simdJSBuf); + asmLink(simdJS, this, null, simdJSBuf); // multiple SIMD.js instantiations succeed + assertAsmLinkFail(asmJS, this, null, simdJSBuf); // but not asm.js +} diff --git a/js/src/jit-test/tests/asm.js/testAtomic-effect.js b/js/src/jit-test/tests/asm.js/testAtomic-effect.js new file mode 100644 index 000000000..8db4b1fb9 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testAtomic-effect.js @@ -0,0 +1,49 @@ +if (!this.Atomics) + quit(); + +load(libdir + "asm.js"); +setJitCompilerOption('asmjs.atomics.enable', 1); + +var code = ` + "use asm"; + + var HEAP32 = new stdlib.Int32Array(heap); + var add = stdlib.Atomics.add; + var load = stdlib.Atomics.load; + var _emscripten_asm_const_int=ffi._emscripten_asm_const_int; + + // Regression test for bug 1154858 - Atomics.add for effect did + // not get compiled properly because of an assembler bug. This + // kernel is derived from the large test case in that bug. + + function add_sharedEv(i1) { + i1 = i1 | 0; + var i2 = 0; + var xx = 0; + i2 = i1 + 4 | 0; + i1 = load(HEAP32, i2 >> 2) | 0; + _emscripten_asm_const_int(7, i2 | 0, i1 | 0) | 0; + add(HEAP32, i2 >> 2, 1) | 0; + _emscripten_asm_const_int(8, i2 | 0, load(HEAP32, i2 >> 2) | 0, i1 + 1 | 0) | 0; + return xx|0; + } + + return {add_sharedEv:add_sharedEv}; +`; + +var x; + +var sab = new SharedArrayBuffer(65536); +var ffi = + { _emscripten_asm_const_int: + function (...rest) { + //print("OUT: " + rest.join(" ")); + if (rest[0] == 8) + x = rest[2]; + } + }; +var m = asmCompile('stdlib', 'ffi', 'heap', code); +var {add_sharedEv} = asmLink(m, this, ffi, sab); +add_sharedEv(13812); + +assertEq(x, 1); diff --git a/js/src/jit-test/tests/asm.js/testAtomics.js b/js/src/jit-test/tests/asm.js/testAtomics.js new file mode 100644 index 000000000..5b30fb622 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testAtomics.js @@ -0,0 +1,1886 @@ +if (!this.SharedArrayBuffer || !this.Atomics || !isAsmJSCompilationAvailable()) + quit(); + +// The code duplication below is very far from elegant but provides +// flexibility that comes in handy several places. + +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +setJitCompilerOption('asmjs.atomics.enable', 1); + +const RuntimeError = WebAssembly.RuntimeError; +const outOfBounds = /index out of bounds/; + +var loadModule_int32_code = + USE_ASM + ` + var atomic_load = stdlib.Atomics.load; + var atomic_store = stdlib.Atomics.store; + var atomic_cmpxchg = stdlib.Atomics.compareExchange; + var atomic_exchange = stdlib.Atomics.exchange; + var atomic_add = stdlib.Atomics.add; + var atomic_sub = stdlib.Atomics.sub; + var atomic_and = stdlib.Atomics.and; + var atomic_or = stdlib.Atomics.or; + var atomic_xor = stdlib.Atomics.xor; + + var i32a = new stdlib.Int32Array(heap); + + // Load element 0 + function do_load() { + var v = 0; + v = atomic_load(i32a, 0); + return v|0; + } + + // Load element i + function do_load_i(i) { + i = i|0; + var v = 0; + v = atomic_load(i32a, i>>2); + return v|0; + } + + // Store 37 in element 0 + function do_store() { + var v = 0; + v = atomic_store(i32a, 0, 37); + return v|0; + } + + // Store 37 in element i + function do_store_i(i) { + i = i|0; + var v = 0; + v = atomic_store(i32a, i>>2, 37); + return v|0; + } + + // Exchange 37 into element 200 + function do_xchg() { + var v = 0; + v = atomic_exchange(i32a, 200, 37); + return v|0; + } + + // Exchange 42 into element i + function do_xchg_i(i) { + i = i|0; + var v = 0; + v = atomic_exchange(i32a, i>>2, 42); + return v|0; + } + + // Exchange 1+2 into element 200. This is not called; all we're + // checking is that the compilation succeeds, since 1+2 has type + // "intish" (asm.js spec "AdditiveExpression") and this should be + // allowed. + function do_xchg_intish() { + var v = 0; + v = atomic_exchange(i32a, 200, 1+2); + return v|0; + } + + // Add 37 to element 10 + function do_add() { + var v = 0; + v = atomic_add(i32a, 10, 37); + return v|0; + } + + // Add 37 to element i + function do_add_i(i) { + i = i|0; + var v = 0; + v = atomic_add(i32a, i>>2, 37); + return v|0; + } + + // As for do_xchg_intish, above. Given the structure of the + // compiler, this covers all the binops. + function do_add_intish() { + var v = 0; + v = atomic_add(i32a, 10, 1+2); + return v|0; + } + + // Subtract 148 from element 20 + function do_sub() { + var v = 0; + v = atomic_sub(i32a, 20, 148); + return v|0; + } + + // Subtract 148 from element i + function do_sub_i(i) { + i = i|0; + var v = 0; + v = atomic_sub(i32a, i>>2, 148); + return v|0; + } + + // AND 0x33333333 into element 30 + function do_and() { + var v = 0; + v = atomic_and(i32a, 30, 0x33333333); + return v|0; + } + + // AND 0x33333333 into element i + function do_and_i(i) { + i = i|0; + var v = 0; + v = atomic_and(i32a, i>>2, 0x33333333); + return v|0; + } + + // OR 0x33333333 into element 40 + function do_or() { + var v = 0; + v = atomic_or(i32a, 40, 0x33333333); + return v|0; + } + + // OR 0x33333333 into element i + function do_or_i(i) { + i = i|0; + var v = 0; + v = atomic_or(i32a, i>>2, 0x33333333); + return v|0; + } + + // XOR 0x33333333 into element 50 + function do_xor() { + var v = 0; + v = atomic_xor(i32a, 50, 0x33333333); + return v|0; + } + + // XOR 0x33333333 into element i + function do_xor_i(i) { + i = i|0; + var v = 0; + v = atomic_xor(i32a, i>>2, 0x33333333); + return v|0; + } + + // CAS element 100: 0 -> -1 + function do_cas1() { + var v = 0; + v = atomic_cmpxchg(i32a, 100, 0, -1); + return v|0; + } + + // As for do_xchg_intish, above. Will not be called, is here just + // to test that the compiler allows intish arguments. + function do_cas_intish() { + var v = 0; + v = atomic_cmpxchg(i32a, 100, 1+2, 2+3); + return v|0; + } + + // CAS element 100: -1 -> 0x5A5A5A5A + function do_cas2() { + var v = 0; + v = atomic_cmpxchg(i32a, 100, -1, 0x5A5A5A5A); + return v|0; + } + + // CAS element i: 0 -> -1 + function do_cas1_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i32a, i>>2, 0, -1); + return v|0; + } + + // CAS element i: -1 -> 0x5A5A5A5A + function do_cas2_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i32a, i>>2, -1, 0x5A5A5A5A); + return v|0; + } + + return { load: do_load, + load_i: do_load_i, + store: do_store, + store_i: do_store_i, + xchg: do_xchg, + xchg_i: do_xchg_i, + xchg_intish: do_xchg_intish, + add: do_add, + add_i: do_add_i, + add_intish: do_add_intish, + sub: do_sub, + sub_i: do_sub_i, + and: do_and, + and_i: do_and_i, + or: do_or, + or_i: do_or_i, + xor: do_xor, + xor_i: do_xor_i, + cas1: do_cas1, + cas2: do_cas2, + cas_intish: do_cas_intish, + cas1_i: do_cas1_i, + cas2_i: do_cas2_i }; +`; + +var loadModule_int32 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int32_code); + +function test_int32(heap) { + var i32a = new Int32Array(heap); + var i32m = asmLink(loadModule_int32, this, {}, heap); + + var size = Int32Array.BYTES_PER_ELEMENT; + + i32a[0] = 12345; + assertEq(i32m.load(), 12345); + assertEq(i32m.load_i(size*0), 12345); + + assertEq(i32m.store(), 37); + assertEq(i32a[0], 37); + assertEq(i32m.store_i(size*0), 37); + + i32a[200] = 78; + assertEq(i32m.xchg(), 78); // 37 into #200 + assertEq(i32a[0], 37); + assertEq(i32m.xchg_i(size*200), 37); // 42 into #200 + assertEq(i32a[200], 42); + + i32a[10] = 18; + assertEq(i32m.add(), 18); + assertEq(i32a[10], 18+37); + assertEq(i32m.add_i(size*10), 18+37); + assertEq(i32a[10], 18+37+37); + + i32a[20] = 4972; + assertEq(i32m.sub(), 4972); + assertEq(i32a[20], 4972 - 148); + assertEq(i32m.sub_i(size*20), 4972 - 148); + assertEq(i32a[20], 4972 - 148 - 148); + + i32a[30] = 0x66666666; + assertEq(i32m.and(), 0x66666666); + assertEq(i32a[30], 0x22222222); + i32a[30] = 0x66666666; + assertEq(i32m.and_i(size*30), 0x66666666); + assertEq(i32a[30], 0x22222222); + + i32a[40] = 0x22222222; + assertEq(i32m.or(), 0x22222222); + assertEq(i32a[40], 0x33333333); + i32a[40] = 0x22222222; + assertEq(i32m.or_i(size*40), 0x22222222); + assertEq(i32a[40], 0x33333333); + + i32a[50] = 0x22222222; + assertEq(i32m.xor(), 0x22222222); + assertEq(i32a[50], 0x11111111); + i32a[50] = 0x22222222; + assertEq(i32m.xor_i(size*50), 0x22222222); + assertEq(i32a[50], 0x11111111); + + i32a[100] = 0; + assertEq(i32m.cas1(), 0); + assertEq(i32m.cas2(), -1); + assertEq(i32a[100], 0x5A5A5A5A); + + i32a[100] = 0; + assertEq(i32m.cas1_i(size*100), 0); + assertEq(i32m.cas2_i(size*100), -1); + assertEq(i32a[100], 0x5A5A5A5A); + + // Out-of-bounds accesses. + + var oob = (heap.byteLength * 2) & ~7; + + assertErrorMessage(() => i32m.cas1_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.cas2_i(oob), RuntimeError, outOfBounds); + + assertErrorMessage(() => i32m.or_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.xor_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.and_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.add_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.sub_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.load_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.store_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.xchg_i(oob), RuntimeError, outOfBounds); + + // Edge cases + const INT32_MAX = Math.pow(2, 31); + const UINT32_MAX = Math.pow(2, 32); + for (var i of [i32a.length*4, INT32_MAX - 4, INT32_MAX, UINT32_MAX - 4]) { + assertErrorMessage(() => i32m.load_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.store_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.add_i(i), RuntimeError, outOfBounds); + } + + i32a[i32a.length-1] = 88; + assertEq(i32m.load_i((i32a.length-1)*4), 88); + assertEq(i32m.store_i((i32a.length-1)*4), 37); + assertEq(i32m.add_i((i32a.length-1)*4), 37); + assertEq(i32m.load_i((i32a.length-1)*4), 37+37); + i32a[i32a.length-1] = 0; +} + +var loadModule_uint32_code = + USE_ASM + ` + var atomic_load = stdlib.Atomics.load; + var atomic_store = stdlib.Atomics.store; + var atomic_cmpxchg = stdlib.Atomics.compareExchange; + var atomic_exchange = stdlib.Atomics.exchange; + var atomic_add = stdlib.Atomics.add; + var atomic_sub = stdlib.Atomics.sub; + var atomic_and = stdlib.Atomics.and; + var atomic_or = stdlib.Atomics.or; + var atomic_xor = stdlib.Atomics.xor; + + var i32a = new stdlib.Uint32Array(heap); + + // Load element 0 + function do_load() { + var v = 0; + v = atomic_load(i32a, 0); + return +(v>>>0); + } + + // Load element i + function do_load_i(i) { + i = i|0; + var v = 0; + v = atomic_load(i32a, i>>2); + return +(v>>>0); + } + + // Store 37 in element 0 + function do_store() { + var v = 0; + v = atomic_store(i32a, 0, 37); + return +(v>>>0); + } + + // Store 37 in element i + function do_store_i(i) { + i = i|0; + var v = 0; + v = atomic_store(i32a, i>>2, 37); + return +(v>>>0); + } + + // Exchange 37 into element 200 + function do_xchg() { + var v = 0; + v = atomic_exchange(i32a, 200, 37); + return v|0; + } + + // Exchange 42 into element i + function do_xchg_i(i) { + i = i|0; + var v = 0; + v = atomic_exchange(i32a, i>>2, 42); + return v|0; + } + + // Add 37 to element 10 + function do_add() { + var v = 0; + v = atomic_add(i32a, 10, 37); + return +(v>>>0); + } + + // Add 37 to element i + function do_add_i(i) { + i = i|0; + var v = 0; + v = atomic_add(i32a, i>>2, 37); + return +(v>>>0); + } + + // Subtract 148 from element 20 + function do_sub() { + var v = 0; + v = atomic_sub(i32a, 20, 148); + return +(v>>>0); + } + + // Subtract 148 from element i + function do_sub_i(i) { + i = i|0; + var v = 0; + v = atomic_sub(i32a, i>>2, 148); + return +(v>>>0); + } + + // AND 0x33333333 into element 30 + function do_and() { + var v = 0; + v = atomic_and(i32a, 30, 0x33333333); + return +(v>>>0); + } + + // AND 0x33333333 into element i + function do_and_i(i) { + i = i|0; + var v = 0; + v = atomic_and(i32a, i>>2, 0x33333333); + return +(v>>>0); + } + + // OR 0x33333333 into element 40 + function do_or() { + var v = 0; + v = atomic_or(i32a, 40, 0x33333333); + return +(v>>>0); + } + + // OR 0x33333333 into element i + function do_or_i(i) { + i = i|0; + var v = 0; + v = atomic_or(i32a, i>>2, 0x33333333); + return +(v>>>0); + } + + // XOR 0x33333333 into element 50 + function do_xor() { + var v = 0; + v = atomic_xor(i32a, 50, 0x33333333); + return +(v>>>0); + } + + // XOR 0x33333333 into element i + function do_xor_i(i) { + i = i|0; + var v = 0; + v = atomic_xor(i32a, i>>2, 0x33333333); + return +(v>>>0); + } + + // CAS element 100: 0 -> -1 + function do_cas1() { + var v = 0; + v = atomic_cmpxchg(i32a, 100, 0, -1); + return +(v>>>0); + } + + // CAS element 100: -1 -> 0x5A5A5A5A + function do_cas2() { + var v = 0; + v = atomic_cmpxchg(i32a, 100, -1, 0x5A5A5A5A); + return +(v>>>0); + } + + // CAS element i: 0 -> -1 + function do_cas1_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i32a, i>>2, 0, -1); + return +(v>>>0); + } + + // CAS element i: -1 -> 0x5A5A5A5A + function do_cas2_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i32a, i>>2, -1, 0x5A5A5A5A); + return +(v>>>0); + } + + return { load: do_load, + load_i: do_load_i, + store: do_store, + store_i: do_store_i, + xchg: do_xchg, + xchg_i: do_xchg_i, + add: do_add, + add_i: do_add_i, + sub: do_sub, + sub_i: do_sub_i, + and: do_and, + and_i: do_and_i, + or: do_or, + or_i: do_or_i, + xor: do_xor, + xor_i: do_xor_i, + cas1: do_cas1, + cas2: do_cas2, + cas1_i: do_cas1_i, + cas2_i: do_cas2_i }; +`; + +var loadModule_uint32 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint32_code); + +function test_uint32(heap) { + var i32a = new Uint32Array(heap); + var i32m = loadModule_uint32(this, {}, heap); + + var size = Uint32Array.BYTES_PER_ELEMENT; + + i32a[0] = 12345; + assertEq(i32m.load(), 12345); + assertEq(i32m.load_i(size*0), 12345); + + assertEq(i32m.store(), 37); + assertEq(i32a[0], 37); + assertEq(i32m.store_i(size*0), 37); + + i32a[200] = 78; + assertEq(i32m.xchg(), 78); // 37 into #200 + assertEq(i32a[0], 37); + assertEq(i32m.xchg_i(size*200), 37); // 42 into #200 + assertEq(i32a[200], 42); + + i32a[10] = 18; + assertEq(i32m.add(), 18); + assertEq(i32a[10], 18+37); + assertEq(i32m.add_i(size*10), 18+37); + assertEq(i32a[10], 18+37+37); + + i32a[20] = 4972; + assertEq(i32m.sub(), 4972); + assertEq(i32a[20], 4972 - 148); + assertEq(i32m.sub_i(size*20), 4972 - 148); + assertEq(i32a[20], 4972 - 148 - 148); + + i32a[30] = 0x66666666; + assertEq(i32m.and(), 0x66666666); + assertEq(i32a[30], 0x22222222); + i32a[30] = 0x66666666; + assertEq(i32m.and_i(size*30), 0x66666666); + assertEq(i32a[30], 0x22222222); + + i32a[40] = 0x22222222; + assertEq(i32m.or(), 0x22222222); + assertEq(i32a[40], 0x33333333); + i32a[40] = 0x22222222; + assertEq(i32m.or_i(size*40), 0x22222222); + assertEq(i32a[40], 0x33333333); + + i32a[50] = 0x22222222; + assertEq(i32m.xor(), 0x22222222); + assertEq(i32a[50], 0x11111111); + i32a[50] = 0x22222222; + assertEq(i32m.xor_i(size*50), 0x22222222); + assertEq(i32a[50], 0x11111111); + + i32a[100] = 0; + assertEq(i32m.cas1(), 0); + assertEq(i32m.cas2(), 0xFFFFFFFF); + assertEq(i32a[100], 0x5A5A5A5A); + + i32a[100] = 0; + assertEq(i32m.cas1_i(size*100), 0); + assertEq(i32m.cas2_i(size*100), 0xFFFFFFFF); + assertEq(i32a[100], 0x5A5A5A5A); + + // Out-of-bounds accesses. + + var oob = (heap.byteLength * 2) & ~7; + + assertErrorMessage(() => i32m.cas1_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.cas2_i(oob), RuntimeError, outOfBounds); + + assertErrorMessage(() => i32m.or_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.xor_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.and_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.add_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.sub_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.load_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.store_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.xchg_i(oob), RuntimeError, outOfBounds); + + // Edge cases + const INT32_MAX = Math.pow(2, 31); + const UINT32_MAX = Math.pow(2, 32); + for (var i of [i32a.length*4, INT32_MAX - 4, INT32_MAX, UINT32_MAX - 4]) { + assertErrorMessage(() => i32m.load_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.store_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i32m.add_i(i), RuntimeError, outOfBounds); + } + + i32a[i32a.length-1] = 88; + assertEq(i32m.load_i((i32a.length-1)*4), 88); + assertEq(i32m.store_i((i32a.length-1)*4), 37); + assertEq(i32m.add_i((i32a.length-1)*4), 37); + assertEq(i32m.load_i((i32a.length-1)*4), 37+37); + i32a[i32a.length-1] = 0; +} + +var loadModule_int16_code = + USE_ASM + ` + var atomic_load = stdlib.Atomics.load; + var atomic_store = stdlib.Atomics.store; + var atomic_cmpxchg = stdlib.Atomics.compareExchange; + var atomic_exchange = stdlib.Atomics.exchange; + var atomic_add = stdlib.Atomics.add; + var atomic_sub = stdlib.Atomics.sub; + var atomic_and = stdlib.Atomics.and; + var atomic_or = stdlib.Atomics.or; + var atomic_xor = stdlib.Atomics.xor; + + var i16a = new stdlib.Int16Array(heap); + + // Load element 0 + function do_load() { + var v = 0; + v = atomic_load(i16a, 0); + return v|0; + } + + // Load element i + function do_load_i(i) { + i = i|0; + var v = 0; + v = atomic_load(i16a, i>>1); + return v|0; + } + + // Store 37 in element 0 + function do_store() { + var v = 0; + v = atomic_store(i16a, 0, 37); + return v|0; + } + + // Store 37 in element i + function do_store_i(i) { + i = i|0; + var v = 0; + v = atomic_store(i16a, i>>1, 37); + return v|0; + } + + // Exchange 37 into element 200 + function do_xchg() { + var v = 0; + v = atomic_exchange(i16a, 200, 37); + return v|0; + } + + // Exchange 42 into element i + function do_xchg_i(i) { + i = i|0; + var v = 0; + v = atomic_exchange(i16a, i>>1, 42); + return v|0; + } + + // Add 37 to element 10 + function do_add() { + var v = 0; + v = atomic_add(i16a, 10, 37); + return v|0; + } + + // Add 37 to element i + function do_add_i(i) { + i = i|0; + var v = 0; + v = atomic_add(i16a, i>>1, 37); + return v|0; + } + + // Subtract 148 from element 20 + function do_sub() { + var v = 0; + v = atomic_sub(i16a, 20, 148); + return v|0; + } + + // Subtract 148 from element i + function do_sub_i(i) { + i = i|0; + var v = 0; + v = atomic_sub(i16a, i>>1, 148); + return v|0; + } + + // AND 0x3333 into element 30 + function do_and() { + var v = 0; + v = atomic_and(i16a, 30, 0x3333); + return v|0; + } + + // AND 0x3333 into element i + function do_and_i(i) { + i = i|0; + var v = 0; + v = atomic_and(i16a, i>>1, 0x3333); + return v|0; + } + + // OR 0x3333 into element 40 + function do_or() { + var v = 0; + v = atomic_or(i16a, 40, 0x3333); + return v|0; + } + + // OR 0x3333 into element i + function do_or_i(i) { + i = i|0; + var v = 0; + v = atomic_or(i16a, i>>1, 0x3333); + return v|0; + } + + // XOR 0x3333 into element 50 + function do_xor() { + var v = 0; + v = atomic_xor(i16a, 50, 0x3333); + return v|0; + } + + // XOR 0x3333 into element i + function do_xor_i(i) { + i = i|0; + var v = 0; + v = atomic_xor(i16a, i>>1, 0x3333); + return v|0; + } + + // CAS element 100: 0 -> -1 + function do_cas1() { + var v = 0; + v = atomic_cmpxchg(i16a, 100, 0, -1); + return v|0; + } + + // CAS element 100: -1 -> 0x5A5A + function do_cas2() { + var v = 0; + v = atomic_cmpxchg(i16a, 100, -1, 0x5A5A); + return v|0; + } + + // CAS element i: 0 -> -1 + function do_cas1_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i16a, i>>1, 0, -1); + return v|0; + } + + // CAS element i: -1 -> 0x5A5A + function do_cas2_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i16a, i>>1, -1, 0x5A5A); + return v|0; + } + + return { load: do_load, + load_i: do_load_i, + store: do_store, + store_i: do_store_i, + xchg: do_xchg, + xchg_i: do_xchg_i, + add: do_add, + add_i: do_add_i, + sub: do_sub, + sub_i: do_sub_i, + and: do_and, + and_i: do_and_i, + or: do_or, + or_i: do_or_i, + xor: do_xor, + xor_i: do_xor_i, + cas1: do_cas1, + cas2: do_cas2, + cas1_i: do_cas1_i, + cas2_i: do_cas2_i }; +` + +var loadModule_int16 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int16_code); + +function test_int16(heap) { + var i16a = new Int16Array(heap); + var i16m = loadModule_int16(this, {}, heap); + + var size = Int16Array.BYTES_PER_ELEMENT; + + i16a[0] = 12345; + assertEq(i16m.load(), 12345); + assertEq(i16m.load_i(size*0), 12345); + + i16a[0] = -38; + assertEq(i16m.load(), -38); + assertEq(i16m.load_i(size*0), -38); + + assertEq(i16m.store(), 37); + assertEq(i16a[0], 37); + assertEq(i16m.store_i(size*0), 37); + + i16a[200] = 78; + assertEq(i16m.xchg(), 78); // 37 into #200 + assertEq(i16a[0], 37); + assertEq(i16m.xchg_i(size*200), 37); // 42 into #200 + assertEq(i16a[200], 42); + + i16a[10] = 18; + assertEq(i16m.add(), 18); + assertEq(i16a[10], 18+37); + assertEq(i16m.add_i(size*10), 18+37); + assertEq(i16a[10], 18+37+37); + + i16a[10] = -38; + assertEq(i16m.add(), -38); + assertEq(i16a[10], -38+37); + assertEq(i16m.add_i(size*10), -38+37); + assertEq(i16a[10], -38+37+37); + + i16a[20] = 4972; + assertEq(i16m.sub(), 4972); + assertEq(i16a[20], 4972 - 148); + assertEq(i16m.sub_i(size*20), 4972 - 148); + assertEq(i16a[20], 4972 - 148 - 148); + + i16a[30] = 0x6666; + assertEq(i16m.and(), 0x6666); + assertEq(i16a[30], 0x2222); + i16a[30] = 0x6666; + assertEq(i16m.and_i(size*30), 0x6666); + assertEq(i16a[30], 0x2222); + + i16a[40] = 0x2222; + assertEq(i16m.or(), 0x2222); + assertEq(i16a[40], 0x3333); + i16a[40] = 0x2222; + assertEq(i16m.or_i(size*40), 0x2222); + assertEq(i16a[40], 0x3333); + + i16a[50] = 0x2222; + assertEq(i16m.xor(), 0x2222); + assertEq(i16a[50], 0x1111); + i16a[50] = 0x2222; + assertEq(i16m.xor_i(size*50), 0x2222); + assertEq(i16a[50], 0x1111); + + i16a[100] = 0; + assertEq(i16m.cas1(), 0); + assertEq(i16m.cas2(), -1); + assertEq(i16a[100], 0x5A5A); + + i16a[100] = 0; + assertEq(i16m.cas1_i(size*100), 0); + assertEq(i16m.cas2_i(size*100), -1); + assertEq(i16a[100], 0x5A5A); + + var oob = (heap.byteLength * 2) & ~7; + + assertErrorMessage(() => i16m.cas1_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.cas2_i(oob), RuntimeError, outOfBounds); + + assertErrorMessage(() => i16m.or_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.xor_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.and_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.add_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.sub_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.load_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.store_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.xchg_i(oob), RuntimeError, outOfBounds); + + // Edge cases + const INT32_MAX = Math.pow(2, 31); + const UINT32_MAX = Math.pow(2, 32); + for (var i of [i16a.length*2, INT32_MAX - 2, INT32_MAX, UINT32_MAX - 2]) { + assertErrorMessage(() => i16m.load_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.store_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.add_i(i), RuntimeError, outOfBounds); + } + + i16a[i16a.length-1] = 88; + assertEq(i16m.load_i((i16a.length-1)*2), 88); + assertEq(i16m.store_i((i16a.length-1)*2), 37); + assertEq(i16m.add_i((i16a.length-1)*2), 37); + assertEq(i16m.load_i((i16a.length-1)*2), 37+37); + i16a[i16a.length-1] = 0; +} + +var loadModule_uint16_code = + USE_ASM + ` + var atomic_load = stdlib.Atomics.load; + var atomic_store = stdlib.Atomics.store; + var atomic_cmpxchg = stdlib.Atomics.compareExchange; + var atomic_exchange = stdlib.Atomics.exchange; + var atomic_add = stdlib.Atomics.add; + var atomic_sub = stdlib.Atomics.sub; + var atomic_and = stdlib.Atomics.and; + var atomic_or = stdlib.Atomics.or; + var atomic_xor = stdlib.Atomics.xor; + + var i16a = new stdlib.Uint16Array(heap); + + // Load element 0 + function do_load() { + var v = 0; + v = atomic_load(i16a, 0); + return v|0; + } + + // Load element i + function do_load_i(i) { + i = i|0; + var v = 0; + v = atomic_load(i16a, i>>1); + return v|0; + } + + // Store 37 in element 0 + function do_store() { + var v = 0; + v = atomic_store(i16a, 0, 37); + return v|0; + } + + // Store 37 in element i + function do_store_i(i) { + i = i|0; + var v = 0; + v = atomic_store(i16a, i>>1, 37); + return v|0; + } + + // Exchange 37 into element 200 + function do_xchg() { + var v = 0; + v = atomic_exchange(i16a, 200, 37); + return v|0; + } + + // Exchange 42 into element i + function do_xchg_i(i) { + i = i|0; + var v = 0; + v = atomic_exchange(i16a, i>>1, 42); + return v|0; + } + + // Add 37 to element 10 + function do_add() { + var v = 0; + v = atomic_add(i16a, 10, 37); + return v|0; + } + + // Add 37 to element i + function do_add_i(i) { + i = i|0; + var v = 0; + v = atomic_add(i16a, i>>1, 37); + return v|0; + } + + // Subtract 148 from element 20 + function do_sub() { + var v = 0; + v = atomic_sub(i16a, 20, 148); + return v|0; + } + + // Subtract 148 from element i + function do_sub_i(i) { + i = i|0; + var v = 0; + v = atomic_sub(i16a, i>>1, 148); + return v|0; + } + + // AND 0x3333 into element 30 + function do_and() { + var v = 0; + v = atomic_and(i16a, 30, 0x3333); + return v|0; + } + + // AND 0x3333 into element i + function do_and_i(i) { + i = i|0; + var v = 0; + v = atomic_and(i16a, i>>1, 0x3333); + return v|0; + } + + // OR 0x3333 into element 40 + function do_or() { + var v = 0; + v = atomic_or(i16a, 40, 0x3333); + return v|0; + } + + // OR 0x3333 into element i + function do_or_i(i) { + i = i|0; + var v = 0; + v = atomic_or(i16a, i>>1, 0x3333); + return v|0; + } + + // XOR 0x3333 into element 50 + function do_xor() { + var v = 0; + v = atomic_xor(i16a, 50, 0x3333); + return v|0; + } + + // XOR 0x3333 into element i + function do_xor_i(i) { + i = i|0; + var v = 0; + v = atomic_xor(i16a, i>>1, 0x3333); + return v|0; + } + + // CAS element 100: 0 -> -1 + function do_cas1() { + var v = 0; + v = atomic_cmpxchg(i16a, 100, 0, -1); + return v|0; + } + + // CAS element 100: -1 -> 0x5A5A + function do_cas2() { + var v = 0; + v = atomic_cmpxchg(i16a, 100, -1, 0x5A5A); + return v|0; + } + + // CAS element i: 0 -> -1 + function do_cas1_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i16a, i>>1, 0, -1); + return v|0; + } + + // CAS element i: -1 -> 0x5A5A + function do_cas2_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i16a, i>>1, -1, 0x5A5A); + return v|0; + } + + return { load: do_load, + load_i: do_load_i, + store: do_store, + store_i: do_store_i, + xchg: do_xchg, + xchg_i: do_xchg_i, + add: do_add, + add_i: do_add_i, + sub: do_sub, + sub_i: do_sub_i, + and: do_and, + and_i: do_and_i, + or: do_or, + or_i: do_or_i, + xor: do_xor, + xor_i: do_xor_i, + cas1: do_cas1, + cas2: do_cas2, + cas1_i: do_cas1_i, + cas2_i: do_cas2_i }; +` + +var loadModule_uint16 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint16_code); + +function test_uint16(heap) { + var i16a = new Uint16Array(heap); + var i16m = loadModule_uint16(this, {}, heap); + + var size = Uint16Array.BYTES_PER_ELEMENT; + + i16a[0] = 12345; + assertEq(i16m.load(), 12345); + assertEq(i16m.load_i(size*0), 12345); + + i16a[0] = -38; + assertEq(i16m.load(), (0x10000-38)); + assertEq(i16m.load_i(size*0), (0x10000-38)); + + assertEq(i16m.store(), 37); + assertEq(i16a[0], 37); + assertEq(i16m.store_i(size*0), 37); + + i16a[200] = 78; + assertEq(i16m.xchg(), 78); // 37 into #200 + assertEq(i16a[0], 37); + assertEq(i16m.xchg_i(size*200), 37); // 42 into #200 + assertEq(i16a[200], 42); + + i16a[10] = 18; + assertEq(i16m.add(), 18); + assertEq(i16a[10], 18+37); + assertEq(i16m.add_i(size*10), 18+37); + assertEq(i16a[10], 18+37+37); + + i16a[10] = -38; + assertEq(i16m.add(), (0x10000-38)); + assertEq(i16a[10], (0x10000-38)+37); + assertEq(i16m.add_i(size*10), (0x10000-38)+37); + assertEq(i16a[10], ((0x10000-38)+37+37) & 0xFFFF); + + i16a[20] = 4972; + assertEq(i16m.sub(), 4972); + assertEq(i16a[20], 4972 - 148); + assertEq(i16m.sub_i(size*20), 4972 - 148); + assertEq(i16a[20], 4972 - 148 - 148); + + i16a[30] = 0x6666; + assertEq(i16m.and(), 0x6666); + assertEq(i16a[30], 0x2222); + i16a[30] = 0x6666; + assertEq(i16m.and_i(size*30), 0x6666); + assertEq(i16a[30], 0x2222); + + i16a[40] = 0x2222; + assertEq(i16m.or(), 0x2222); + assertEq(i16a[40], 0x3333); + i16a[40] = 0x2222; + assertEq(i16m.or_i(size*40), 0x2222); + assertEq(i16a[40], 0x3333); + + i16a[50] = 0x2222; + assertEq(i16m.xor(), 0x2222); + assertEq(i16a[50], 0x1111); + i16a[50] = 0x2222; + assertEq(i16m.xor_i(size*50), 0x2222); + assertEq(i16a[50], 0x1111); + + i16a[100] = 0; + assertEq(i16m.cas1(), 0); + assertEq(i16m.cas2(), -1 & 0xFFFF); + assertEq(i16a[100], 0x5A5A); + + i16a[100] = 0; + assertEq(i16m.cas1_i(size*100), 0); + assertEq(i16m.cas2_i(size*100), -1 & 0xFFFF); + assertEq(i16a[100], 0x5A5A); + + var oob = (heap.byteLength * 2) & ~7; + + assertErrorMessage(() => i16m.cas1_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.cas2_i(oob), RuntimeError, outOfBounds); + + assertErrorMessage(() => i16m.or_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.xor_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.and_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.add_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.sub_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.load_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.store_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.xchg_i(oob), RuntimeError, outOfBounds); + + // Edge cases + const INT32_MAX = Math.pow(2, 31); + const UINT32_MAX = Math.pow(2, 32); + for (var i of [i16a.length*2, INT32_MAX - 2, INT32_MAX, UINT32_MAX - 2]) { + assertErrorMessage(() => i16m.load_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.store_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i16m.add_i(i), RuntimeError, outOfBounds); + } + + i16a[i16a.length-1] = 88; + assertEq(i16m.load_i((i16a.length-1)*2), 88); + assertEq(i16m.store_i((i16a.length-1)*2), 37); + assertEq(i16m.add_i((i16a.length-1)*2), 37); + assertEq(i16m.load_i((i16a.length-1)*2), 37+37); + i16a[i16a.length-1] = 0; +} + +var loadModule_int8_code = + USE_ASM + ` + var atomic_load = stdlib.Atomics.load; + var atomic_store = stdlib.Atomics.store; + var atomic_cmpxchg = stdlib.Atomics.compareExchange; + var atomic_exchange = stdlib.Atomics.exchange; + var atomic_add = stdlib.Atomics.add; + var atomic_sub = stdlib.Atomics.sub; + var atomic_and = stdlib.Atomics.and; + var atomic_or = stdlib.Atomics.or; + var atomic_xor = stdlib.Atomics.xor; + + var i8a = new stdlib.Int8Array(heap); + + // Load element 0 + function do_load() { + var v = 0; + v = atomic_load(i8a, 0); + return v|0; + } + + // Load element i + function do_load_i(i) { + i = i|0; + var v = 0; + v = atomic_load(i8a, i); + return v|0; + } + + // Store 37 in element 0 + function do_store() { + var v = 0; + v = atomic_store(i8a, 0, 37); + return v|0; + } + + // Store 37 in element i + function do_store_i(i) { + i = i|0; + var v = 0; + v = atomic_store(i8a, i, 37); + return v|0; + } + + // Exchange 37 into element 200 + function do_xchg() { + var v = 0; + v = atomic_exchange(i8a, 200, 37); + return v|0; + } + + // Exchange 42 into element i + function do_xchg_i(i) { + i = i|0; + var v = 0; + v = atomic_exchange(i8a, i, 42); + return v|0; + } + + // Add 37 to element 10 + function do_add() { + var v = 0; + v = atomic_add(i8a, 10, 37); + return v|0; + } + + // Add 37 to element i + function do_add_i(i) { + i = i|0; + var v = 0; + v = atomic_add(i8a, i, 37); + return v|0; + } + + // Subtract 108 from element 20 + function do_sub() { + var v = 0; + v = atomic_sub(i8a, 20, 108); + return v|0; + } + + // Subtract 108 from element i + function do_sub_i(i) { + i = i|0; + var v = 0; + v = atomic_sub(i8a, i, 108); + return v|0; + } + + // AND 0x33 into element 30 + function do_and() { + var v = 0; + v = atomic_and(i8a, 30, 0x33); + return v|0; + } + + // AND 0x33 into element i + function do_and_i(i) { + i = i|0; + var v = 0; + v = atomic_and(i8a, i, 0x33); + return v|0; + } + + // OR 0x33 into element 40 + function do_or() { + var v = 0; + v = atomic_or(i8a, 40, 0x33); + return v|0; + } + + // OR 0x33 into element i + function do_or_i(i) { + i = i|0; + var v = 0; + v = atomic_or(i8a, i, 0x33); + return v|0; + } + + // XOR 0x33 into element 50 + function do_xor() { + var v = 0; + v = atomic_xor(i8a, 50, 0x33); + return v|0; + } + + // XOR 0x33 into element i + function do_xor_i(i) { + i = i|0; + var v = 0; + v = atomic_xor(i8a, i, 0x33); + return v|0; + } + + // CAS element 100: 0 -> -1 + function do_cas1() { + var v = 0; + v = atomic_cmpxchg(i8a, 100, 0, -1); + return v|0; + } + + // CAS element 100: -1 -> 0x5A + function do_cas2() { + var v = 0; + v = atomic_cmpxchg(i8a, 100, -1, 0x5A); + return v|0; + } + + // CAS element i: 0 -> -1 + function do_cas1_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i8a, i, 0, -1); + return v|0; + } + + // CAS element i: -1 -> 0x5A + function do_cas2_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i8a, i, -1, 0x5A); + return v|0; + } + + return { load: do_load, + load_i: do_load_i, + store: do_store, + store_i: do_store_i, + xchg: do_xchg, + xchg_i: do_xchg_i, + add: do_add, + add_i: do_add_i, + sub: do_sub, + sub_i: do_sub_i, + and: do_and, + and_i: do_and_i, + or: do_or, + or_i: do_or_i, + xor: do_xor, + xor_i: do_xor_i, + cas1: do_cas1, + cas2: do_cas2, + cas1_i: do_cas1_i, + cas2_i: do_cas2_i }; +` + +var loadModule_int8 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int8_code); + +function test_int8(heap) { + var i8a = new Int8Array(heap); + var i8m = loadModule_int8(this, {}, heap); + + for ( var i=0 ; i < i8a.length ; i++ ) + i8a[i] = 0; + + var size = Int8Array.BYTES_PER_ELEMENT; + + i8a[0] = 123; + assertEq(i8m.load(), 123); + assertEq(i8m.load_i(0), 123); + + assertEq(i8m.store(), 37); + assertEq(i8a[0], 37); + assertEq(i8m.store_i(0), 37); + + i8a[200] = 78; + assertEq(i8m.xchg(), 78); // 37 into #200 + assertEq(i8a[0], 37); + assertEq(i8m.xchg_i(size*200), 37); // 42 into #200 + assertEq(i8a[200], 42); + + i8a[10] = 18; + assertEq(i8m.add(), 18); + assertEq(i8a[10], 18+37); + assertEq(i8m.add_i(10), 18+37); + assertEq(i8a[10], 18+37+37); + + i8a[20] = 49; + assertEq(i8m.sub(), 49); + assertEq(i8a[20], 49 - 108); + assertEq(i8m.sub_i(20), 49 - 108); + assertEq(i8a[20], ((49 - 108 - 108) << 24) >> 24); // Byte, sign extended + + i8a[30] = 0x66; + assertEq(i8m.and(), 0x66); + assertEq(i8a[30], 0x22); + i8a[30] = 0x66; + assertEq(i8m.and_i(30), 0x66); + assertEq(i8a[30], 0x22); + + i8a[40] = 0x22; + assertEq(i8m.or(), 0x22); + assertEq(i8a[40], 0x33); + i8a[40] = 0x22; + assertEq(i8m.or_i(40), 0x22); + assertEq(i8a[40], 0x33); + + i8a[50] = 0x22; + assertEq(i8m.xor(), 0x22); + assertEq(i8a[50], 0x11); + i8a[50] = 0x22; + assertEq(i8m.xor_i(50), 0x22); + assertEq(i8a[50], 0x11); + + i8a[100] = 0; + assertEq(i8m.cas1(), 0); + assertEq(i8m.cas2(), -1); + assertEq(i8a[100], 0x5A); + + i8a[100] = 0; + assertEq(i8m.cas1_i(100), 0); + assertEq(i8m.cas2_i(100), -1); + assertEq(i8a[100], 0x5A); + + var oob = (heap.byteLength * 2) & ~7; + + assertErrorMessage(() => i8m.cas1_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.cas2_i(oob), RuntimeError, outOfBounds); + + assertErrorMessage(() => i8m.or_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.xor_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.and_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.add_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.sub_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.load_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.store_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.xchg_i(oob), RuntimeError, outOfBounds); + + // Edge cases + const INT32_MAX = Math.pow(2, 31); + const UINT32_MAX = Math.pow(2, 32); + for (var i of [i8a.length, INT32_MAX - 1, INT32_MAX, UINT32_MAX - 1]) { + assertErrorMessage(() => i8m.load_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.store_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.add_i(i), RuntimeError, outOfBounds); + } + + i8a[i8a.length-1] = 88; + assertEq(i8m.load_i(i8a.length-1), 88); + assertEq(i8m.store_i(i8a.length-1), 37); + assertEq(i8m.add_i(i8a.length-1), 37); + assertEq(i8m.load_i(i8a.length-1), 37+37); + i8a[i8a.length-1] = 0; +} + +var loadModule_uint8_code = + USE_ASM + ` + var atomic_load = stdlib.Atomics.load; + var atomic_store = stdlib.Atomics.store; + var atomic_cmpxchg = stdlib.Atomics.compareExchange; + var atomic_exchange = stdlib.Atomics.exchange; + var atomic_add = stdlib.Atomics.add; + var atomic_sub = stdlib.Atomics.sub; + var atomic_and = stdlib.Atomics.and; + var atomic_or = stdlib.Atomics.or; + var atomic_xor = stdlib.Atomics.xor; + + var i8a = new stdlib.Uint8Array(heap); + + // Load element 0 + function do_load() { + var v = 0; + v = atomic_load(i8a, 0); + return v|0; + } + + // Load element i + function do_load_i(i) { + i = i|0; + var v = 0; + v = atomic_load(i8a, i); + return v|0; + } + + // Store 37 in element 0 + function do_store() { + var v = 0; + v = atomic_store(i8a, 0, 37); + return v|0; + } + + // Store 37 in element i + function do_store_i(i) { + i = i|0; + var v = 0; + v = atomic_store(i8a, i, 37); + return v|0; + } + + // Exchange 37 into element 200 + function do_xchg() { + var v = 0; + v = atomic_exchange(i8a, 200, 37); + return v|0; + } + + // Exchange 42 into element i + function do_xchg_i(i) { + i = i|0; + var v = 0; + v = atomic_exchange(i8a, i, 42); + return v|0; + } + + // Add 37 to element 10 + function do_add() { + var v = 0; + v = atomic_add(i8a, 10, 37); + return v|0; + } + + // Add 37 to element i + function do_add_i(i) { + i = i|0; + var v = 0; + v = atomic_add(i8a, i, 37); + return v|0; + } + + // Subtract 108 from element 20 + function do_sub() { + var v = 0; + v = atomic_sub(i8a, 20, 108); + return v|0; + } + + // Subtract 108 from element i + function do_sub_i(i) { + i = i|0; + var v = 0; + v = atomic_sub(i8a, i, 108); + return v|0; + } + + // AND 0x33 into element 30 + function do_and() { + var v = 0; + v = atomic_and(i8a, 30, 0x33); + return v|0; + } + + // AND 0x33 into element i + function do_and_i(i) { + i = i|0; + var v = 0; + v = atomic_and(i8a, i, 0x33); + return v|0; + } + + // OR 0x33 into element 40 + function do_or() { + var v = 0; + v = atomic_or(i8a, 40, 0x33); + return v|0; + } + + // OR 0x33 into element i + function do_or_i(i) { + i = i|0; + var v = 0; + v = atomic_or(i8a, i, 0x33); + return v|0; + } + + // XOR 0x33 into element 50 + function do_xor() { + var v = 0; + v = atomic_xor(i8a, 50, 0x33); + return v|0; + } + + // XOR 0x33 into element i + function do_xor_i(i) { + i = i|0; + var v = 0; + v = atomic_xor(i8a, i, 0x33); + return v|0; + } + + // CAS element 100: 0 -> -1 + function do_cas1() { + var v = 0; + v = atomic_cmpxchg(i8a, 100, 0, -1); + return v|0; + } + + // CAS element 100: -1 -> 0x5A + function do_cas2() { + var v = 0; + v = atomic_cmpxchg(i8a, 100, -1, 0x5A); + return v|0; + } + + // CAS element i: 0 -> -1 + function do_cas1_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i8a, i, 0, -1); + return v|0; + } + + // CAS element i: -1 -> 0x5A + function do_cas2_i(i) { + i = i|0; + var v = 0; + v = atomic_cmpxchg(i8a, i, -1, 0x5A); + return v|0; + } + + return { load: do_load, + load_i: do_load_i, + store: do_store, + store_i: do_store_i, + xchg: do_xchg, + xchg_i: do_xchg_i, + add: do_add, + add_i: do_add_i, + sub: do_sub, + sub_i: do_sub_i, + and: do_and, + and_i: do_and_i, + or: do_or, + or_i: do_or_i, + xor: do_xor, + xor_i: do_xor_i, + cas1: do_cas1, + cas2: do_cas2, + cas1_i: do_cas1_i, + cas2_i: do_cas2_i }; +` + +var loadModule_uint8 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint8_code); + +function test_uint8(heap) { + var i8a = new Uint8Array(heap); + var i8m = loadModule_uint8(this, {}, heap); + + for ( var i=0 ; i < i8a.length ; i++ ) + i8a[i] = 0; + + var size = Uint8Array.BYTES_PER_ELEMENT; + + i8a[0] = 123; + assertEq(i8m.load(), 123); + assertEq(i8m.load_i(0), 123); + + i8a[0] = -38; + assertEq(i8m.load(), (0x100-38)); + assertEq(i8m.load_i(size*0), (0x100-38)); + + assertEq(i8m.store(), 37); + assertEq(i8a[0], 37); + assertEq(i8m.store_i(0), 37); + + i8a[200] = 78; + assertEq(i8m.xchg(), 78); // 37 into #200 + assertEq(i8a[0], 37); + assertEq(i8m.xchg_i(size*200), 37); // 42 into #200 + assertEq(i8a[200], 42); + + i8a[10] = 18; + assertEq(i8m.add(), 18); + assertEq(i8a[10], 18+37); + assertEq(i8m.add_i(10), 18+37); + assertEq(i8a[10], 18+37+37); + + i8a[10] = -38; + assertEq(i8m.add(), (0x100-38)); + assertEq(i8a[10], (0x100-38)+37); + assertEq(i8m.add_i(size*10), (0x100-38)+37); + assertEq(i8a[10], ((0x100-38)+37+37) & 0xFF); + + i8a[20] = 49; + assertEq(i8m.sub(), 49); + assertEq(i8a[20], (49 - 108) & 255); + assertEq(i8m.sub_i(20), (49 - 108) & 255); + assertEq(i8a[20], (49 - 108 - 108) & 255); // Byte, zero extended + + i8a[30] = 0x66; + assertEq(i8m.and(), 0x66); + assertEq(i8a[30], 0x22); + i8a[30] = 0x66; + assertEq(i8m.and_i(30), 0x66); + assertEq(i8a[30], 0x22); + + i8a[40] = 0x22; + assertEq(i8m.or(), 0x22); + assertEq(i8a[40], 0x33); + i8a[40] = 0x22; + assertEq(i8m.or_i(40), 0x22); + assertEq(i8a[40], 0x33); + + i8a[50] = 0x22; + assertEq(i8m.xor(), 0x22); + assertEq(i8a[50], 0x11); + i8a[50] = 0x22; + assertEq(i8m.xor_i(50), 0x22); + assertEq(i8a[50], 0x11); + + i8a[100] = 0; + assertEq(i8m.cas1(), 0); + assertEq(i8m.cas2(), 255); + assertEq(i8a[100], 0x5A); + + i8a[100] = 0; + assertEq(i8m.cas1_i(100), 0); + assertEq(i8m.cas2_i(100), 255); + assertEq(i8a[100], 0x5A); + + var oob = (heap.byteLength * 2) & ~7; + + assertErrorMessage(() => i8m.cas1_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.cas2_i(oob), RuntimeError, outOfBounds); + + assertErrorMessage(() => i8m.or_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.xor_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.and_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.add_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.sub_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.load_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.store_i(oob), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.xchg_i(oob), RuntimeError, outOfBounds); + + // Edge cases + const INT32_MAX = Math.pow(2, 31); + const UINT32_MAX = Math.pow(2, 32); + for (var i of [i8a.length, INT32_MAX - 1, INT32_MAX, UINT32_MAX - 1]) { + assertErrorMessage(() => i8m.load_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.store_i(i), RuntimeError, outOfBounds); + assertErrorMessage(() => i8m.add_i(i), RuntimeError, outOfBounds); + } + + i8a[i8a.length-1] = 88; + assertEq(i8m.load_i(i8a.length-1), 88); + assertEq(i8m.store_i(i8a.length-1), 37); + assertEq(i8m.add_i(i8a.length-1), 37); + assertEq(i8m.load_i(i8a.length-1), 37+37); + i8a[i8a.length-1] = 0; +} + +var loadModule_misc_code = + USE_ASM + ` + var atomic_isLockFree = stdlib.Atomics.isLockFree; + + function ilf1() { + return atomic_isLockFree(1)|0; + } + + function ilf2() { + return atomic_isLockFree(2)|0; + } + + function ilf3() { + return atomic_isLockFree(3)|0; + } + + function ilf4() { + return atomic_isLockFree(4)|0; + } + + function ilf5() { + return atomic_isLockFree(5)|0; + } + + function ilf6() { + return atomic_isLockFree(6)|0; + } + + function ilf7() { + return atomic_isLockFree(7)|0; + } + + function ilf8() { + return atomic_isLockFree(8)|0; + } + + function ilf9() { + return atomic_isLockFree(9)|0; + } + + return { ilf1: ilf1, + ilf2: ilf2, + ilf3: ilf3, + ilf4: ilf4, + ilf5: ilf5, + ilf6: ilf6, + ilf7: ilf7, + ilf8: ilf8, + ilf9: ilf9 }; +` + +var loadModule_misc = asmCompile('stdlib', 'foreign', 'heap', loadModule_misc_code); + +function test_misc(heap) { + var misc = loadModule_misc(this, {}, heap); + + assertEq(misc.ilf1(), 1); // Guaranteed by SpiderMonkey, not spec + assertEq(misc.ilf2(), 1); // Guaranteed by SpiderMonkey, not spec + assertEq(misc.ilf3(), 0); + assertEq(misc.ilf4(), 1); // Guaranteed by SpiderMonkey, not spec + assertEq(misc.ilf5(), 0); + assertEq(misc.ilf6(), 0); + assertEq(misc.ilf7(), 0); + assertEq(misc.ilf8(), 0); // Required by spec, for now + assertEq(misc.ilf9(), 0); +} + +// Shared-memory Uint8ClampedArray is not supported for asm.js. + +var heap = new SharedArrayBuffer(65536); + +test_int8(heap); +test_uint8(heap); +test_int16(heap); +test_uint16(heap); +test_int32(heap); +test_uint32(heap); +test_misc(heap); + +// Bug 1254167: Effective Address Analysis should be void on atomics accesses, +var code = ` + "use asm"; + var HEAP32 = new stdlib.Int32Array(heap); + var load = stdlib.Atomics.load; + function f() { + var i2 = 0; + i2 = 305002 | 0; + return load(HEAP32, i2 >> 2) | 0; + } + return f; +`; +var f = asmLink(asmCompile('stdlib', 'ffi', 'heap', code), this, {}, new SharedArrayBuffer(0x10000)); +assertErrorMessage(f, RuntimeError, outOfBounds); + +// Test that ARM callouts compile. +setARMHwCapFlags('vfp'); + +asmCompile('stdlib', 'ffi', 'heap', + USE_ASM + ` + var atomic_exchange = stdlib.Atomics.exchange; + var i8a = new stdlib.Int8Array(heap); + + function do_xchg() { + var v = 0; + v = atomic_exchange(i8a, 200, 37); + return v|0; + } + + return { xchg: do_xchg } +`); + diff --git a/js/src/jit-test/tests/asm.js/testBasic.js b/js/src/jit-test/tests/asm.js/testBasic.js new file mode 100644 index 000000000..f47a837f3 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBasic.js @@ -0,0 +1,176 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +assertAsmTypeFail(USE_ASM); +assertAsmTypeFail(USE_ASM + 'return'); +assertAsmTypeFail(USE_ASM + 'function f() 0'); +assertAsmTypeFail(USE_ASM + 'function f(){}'); +assertAsmTypeFail(USE_ASM + 'function f(){} return 0'); +assertAsmTypeFail(USE_ASM + 'function f() 0; return 0'); +assertAsmTypeFail(USE_ASM + 'function f(){} return g'); +assertAsmTypeFail(USE_ASM + 'function f(){} function f(){} return f'); +assertAsmTypeFail(USE_ASM + 'function f(){}; function g(){}; return {f, g}'); +assertAsmTypeFail(USE_ASM + 'var f = f;'); +assertAsmTypeFail(USE_ASM + 'var f=0; function f(){} return f'); +assertAsmTypeFail(USE_ASM + 'var f=glob.Math.imul; return {}'); +assertAsmTypeFail('glob', USE_ASM + 'var f=glob.Math.imul; function f(){} return f'); +assertAsmTypeFail('glob','foreign', USE_ASM + 'var f=foreign.foo; function f(){} return f'); +assertAsmTypeFail(USE_ASM + 'function f(){} var f=[f,f]; return f'); +assertAsmTypeFail(USE_ASM + 'function f() 0; return f'); +assertAsmTypeFail('"use strict";' + USE_ASM + 'function f() {} return f'); +assertAsmTypeFail(USE_ASM + '"use strict"; function f() {} return f'); +assertAsmTypeFail(USE_ASM + '"use foopy" + 1; function f() {} return f'); +assertAsmTypeFail(USE_ASM + 'function f() { "use strict"; } return f'); +assertEq(asmLink(asmCompile(USE_ASM + '"use asm"; function f() {} return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + '"use foopy"; function f() {} return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + '"use foopy"; "use blarg"; function f() {} return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use asm"; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use foopy"; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use foopy"; "use blarg"; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { "use foopy"; i=i|0; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { "use foopy"; "use asm"; i=i|0; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + '"use warm"; function f(i) { "use cold"; i=i|0 } function g() { "use hot"; return 0 } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + '"use warm"; function f(i) { "use cold"; i=i|0 } function g() { "use asm"; return 0 } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(){} return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(){;} return f'))(), undefined); +assertAsmTypeFail(USE_ASM + 'function f(i,j){;} return f'); +assertEq(asmLink(asmCompile('"use asm";; function f(){};;; return f;;'))(), undefined); +assertAsmTypeFail(USE_ASM + 'function f(x){} return f'); +assertAsmTypeFail(USE_ASM + 'function f(){if (0) return; return 1} return f'); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0} return f'))(42), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0; return x|0} return f'))(42), 42); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0; return x|0;;;} return f'))(42), 42); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(x,y){x=x|0;y=y|0; return (x+y)|0} return f'))(44, -2), 42); +assertAsmTypeFail('a', USE_ASM + 'function a(){} return a'); +assertAsmTypeFail('a','b','c', USE_ASM + 'var c'); +assertAsmTypeFail('a','b','c', USE_ASM + 'var c=0'); +assertAsmTypeFail(USE_ASM + 'c=0;return {}'); +assertAsmTypeFail('x','x', USE_ASM + 'function a(){} return a'); +assertAsmTypeFail('x','y','x', USE_ASM + 'function a(){} return a'); +assertEq(asmLink(asmCompile('x', USE_ASM + 'function a(){} return a'))(), undefined); +assertEq(asmLink(asmCompile('x','y', USE_ASM + 'function a(){} return a'))(), undefined); +assertEq(asmLink(asmCompile('x','y','z', USE_ASM + 'function a(){} return a'))(), undefined); +assertAsmTypeFail('x','y', USE_ASM + 'function y(){} return f'); +assertEq(asmLink(asmCompile('x', USE_ASM + 'function f(){} return f'), 1, 2, 3)(), undefined); +assertEq(asmLink(asmCompile('x', USE_ASM + 'function f(){} return f'), 1)(), undefined); +assertEq(asmLink(asmCompile('x','y', USE_ASM + 'function f(){} return f'), 1, 2)(), undefined); + +assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) {i=i|0} return f'))(42), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() {var i=0;; var j=1;} return f'))(), undefined); // bug 877965 second part +assertAsmTypeFail(USE_ASM + 'function f(i) {i=i|0;var i} return f'); +assertAsmTypeFail(USE_ASM + 'function f(i) {i=i|0;var i=0} return f'); + +assertAsmTypeFail('glob', USE_ASM + 'var im=glob.imul; function f() {} return f'); +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), null); +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), {}); +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), {imul:Math.imul}); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), {Math:{imul:Math.imul}})(2,3), 6); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), this)(8,4), 32); + +var module = asmCompile('glob','i','b', USE_ASM + 'var i32=new glob.Int32Array(b); function f(){} return f'); +assertAsmLinkAlwaysFail(module, null, null); +assertAsmLinkAlwaysFail(module, this, null, null); +assertAsmLinkAlwaysFail(module, this, null, null); +assertAsmLinkAlwaysFail(module, this, null, new ArrayBuffer(1)); +assertAsmLinkFail(module, this, null, new ArrayBuffer(4)); +assertAsmLinkFail(module, this, null, new ArrayBuffer(100)); +assertAsmLinkFail(module, this, null, new ArrayBuffer(4092)); +assertAsmLinkFail(module, this, null, new ArrayBuffer(64000)); +assertAsmLinkFail(module, this, null, new ArrayBuffer(BUF_MIN+4)); +assertAsmLinkDeprecated(module, this, null, new ArrayBuffer(4096)); +assertAsmLinkDeprecated(module, this, null, new ArrayBuffer(2*4096)); +assertAsmLinkDeprecated(module, this, null, new ArrayBuffer(4*4096)); +assertAsmLinkDeprecated(module, this, null, new ArrayBuffer(32*1024)); +assertEq(asmLink(module, this, null, new ArrayBuffer(BUF_MIN))(), undefined); + +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i]|0; return i|0}; return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>1]|0; return i|0}; return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>1]|0; return i|0}; return f'); +assertAsmLinkAlwaysFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>2]|0; return i|0}; return f'), this, null, new ArrayBuffer(BUF_MIN-1)); +assertEq(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>2]|0; return i|0}; return f')(this, null, new ArrayBuffer(BUF_MIN))(), 0); + +var exp = asmLink(asmCompile(USE_ASM + "return {}")); +assertEq(Object.keys(exp).length, 0); + +var exp = asmLink(asmCompile(USE_ASM + "function f() { return 3 } return {f:f,f:f}")); +assertEq(exp.f(), 3); +assertEq(Object.keys(exp).join(), 'f'); + +var exp = asmLink(asmCompile(USE_ASM + "function f() { return 4 } return {f1:f,f2:f}")); +assertEq(exp.f1(), 4); +assertEq(exp.f2(), 4); +assertEq(Object.keys(exp).sort().join(), 'f1,f2'); +assertEq(exp.f1, exp.f2); + +assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {1:f}"); +assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {__proto__:f}"); +assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {get x() {} }"); + +var exp = asmLink(asmCompile(USE_ASM + 'function internal() { return ((g()|0)+2)|0 } function f() { return 1 } function g() { return 2 } function h() { return internal()|0 } return {f:f,g1:g,h1:h}')); +assertEq(exp.f(), 1); +assertEq(exp.g1(), 2); +assertEq(exp.h1(), 4); +assertEq(Object.keys(exp).join(), 'f,g1,h1'); + +// can't test destructuring args with Function constructor +function assertTypeFailInEval(str) +{ + if (!isAsmJSCompilationAvailable()) + return; + + var caught = false; + var oldOpts = options("werror"); + assertEq(oldOpts.indexOf("werror"), -1); + try { + eval(str); + } catch (e) { + assertEq((''+e).indexOf(ASM_TYPE_FAIL_STRING) == -1, false); + caught = true; + } + assertEq(caught, true); + options("werror"); +} +assertTypeFailInEval('function f({}) { "use asm"; function g() {} return g }'); +assertTypeFailInEval('function f({global}) { "use asm"; function g() {} return g }'); +assertTypeFailInEval('function f(global, {imports}) { "use asm"; function g() {} return g }'); +assertTypeFailInEval('function f(g = 2) { "use asm"; function g() {} return g }'); +assertTypeFailInEval('function *f() { "use asm"; function g() {} return g }'); +assertTypeFailInEval('f => { "use asm"; function g() {} return g }'); +assertTypeFailInEval('var f = { method() {"use asm"; return {}} }'); +assertAsmTypeFail(USE_ASM + 'return {m() {}};'); +assertTypeFailInEval('class f { constructor() {"use asm"; return {}} }'); +assertAsmTypeFail(USE_ASM + 'class c { constructor() {}}; return c;'); + +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'var)') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'return)') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'var z=-2w') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'var z=-2w;') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f(') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f()') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f() {') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f() {} var') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f() {} var TBL=-2w; return f') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f() {} var TBL=-2w return f') }, SyntaxError); +assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function () {}') }, SyntaxError); +assertNoWarning(function() { parse("function f() { 'use asm'; function g() {} return g }") }); + +// Test asm.js->asm.js, wasm->asm.js, asm.js->wasm imports: + +var f = asmLink(asmCompile(USE_ASM + 'function f() {} return f')); +var g = asmLink(asmCompile('glob', 'ffis', USE_ASM + 'var f = ffis.f; function g() { return f(1)|0; } return g'), null, {f}); +assertEq(g(), 0); + +if (wasmIsSupported()) { + var h = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`(module + (import $f "imp" "f" (param i32) (result i32)) + (func $h (result i32) (call $f (i32.const 1))) + (export "h" $h) + )`)), {imp:{f}}).exports.h; + assertEq(h(), 0); + + var i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`(module (func $i) (export "i" $i))`))).exports.i + var j = asmLink(asmCompile('glob', 'ffis', USE_ASM + 'var i = ffis.i; function j() { return i(1)|0; } return j'), null, {i}); + assertEq(j(), 0); +} diff --git a/js/src/jit-test/tests/asm.js/testBug1046688.js b/js/src/jit-test/tests/asm.js/testBug1046688.js new file mode 100644 index 000000000..692747f02 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1046688.js @@ -0,0 +1,11 @@ +enableSPSProfiling(); +for (var j = 0; j < 1000; ++j) { + (function(stdlib) { + "use asm"; + var pow = stdlib.Math.pow; + function f() { + return +pow(.0, .0) + } + return f; +})(this)() +} diff --git a/js/src/jit-test/tests/asm.js/testBug1057248.js b/js/src/jit-test/tests/asm.js/testBug1057248.js new file mode 100644 index 000000000..96197e04c --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1057248.js @@ -0,0 +1,134 @@ +if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable()) + quit(); + +Random = { + weighted: function(wa) { + var a = []; + for (var i = 0; i < wa.length; ++i) { + for (var j = 0; j < wa[i]; ++j) {} + } + } +} +s = (function() { + Random.weighted([{ + n() {} + }, { + n() {} + }, { + n() {} + }, { + w: 5, + n() {} + } + ]) +})() +var builtinObjectNames = []; +(function() { + function exploreDeeper(a, a) { + var s = Object.getOwnPropertyNames(a) + for (var j = 0; j < s.length; ++j) { + if (typeof h == "" && n != "") {} + } + builtinObjectNames.push() + } + exploreDeeper(Math, "") +})(this, false) +r = autoExpr(Random.weighted([])); +r = autoExpr(Random.weighted([])); +(Random.weighted([])); +r = (Random.weighted([])) +v = autoExpr(Random.weighted([]), true); +r = autoExpr(Random.weighted([{ + n() {} + } +]), true) +function autoExpr() {} +function makeStatement() {} +s = Random.weighted([{ + n() {} + } +]) +a = Random.weighted([{}, {}, {}, {}, {}, { + n() {} + } +]) +a = Random.weighted([{ + n() {} + }, {}, {} +]) +var recursiveFunctions = [{ + text: "(function(){{}})" + }, { + text: "(function(){if(0){}(1)})", + n() {} + }, { + text: "(function(){t:[]()})", + n() {} + }, { + text: "(function(){g()})", + n() {} + } +]; +(function s() { + for (var i = 0; i < recursiveFunctions.length; ++i) { + a = recursiveFunctions[i]; + var text = a.text + a = eval(text.replace(/@/, "")) + } + function g() {} + s = Random.weighted([{ + w: 1, + n() {} + }, { + n() {} + }, // + { + n() {} + }, // + { + n() {} + }, { + w: 0, + n() {} + }, { + n() {} + }, { + n() {} + }, { + w: 1, + n() {} + }, { + w: makeStatement + }, { + w: 5 + } + ]) + t = function() {} + function c() {} +})() +function testMathyFunction(f, inputs) { + var r = []; + for (var j = 0; j < inputs.length; ++j) { + for (var k = 0; k < inputs.length; ++k) { + try { + f(inputs[j]) + } catch (e) {} + } + } + uneval([]) +} +mathy2 = (function(stdlib, foreign, heap) { + "use asm"; + var Float32ArrayView = new stdlib.Float32Array(heap) + function f(i0) { + i0 = i0 | 0; + (Float32ArrayView[-i0 >> 2]) = 1. + } + return f +})(this, { +}, new SharedArrayBuffer(4096)) +testMathyFunction(mathy2, [-0]) +mathy5 = (function(y) { + ((function() {})(mathy2(y)())) +}) +testMathyFunction(mathy5, [Math.PI]) diff --git a/js/src/jit-test/tests/asm.js/testBug1099216.js b/js/src/jit-test/tests/asm.js/testBug1099216.js new file mode 100644 index 000000000..3514f307d --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1099216.js @@ -0,0 +1,61 @@ +if (typeof SIMD === 'undefined' || !isSimdAvailable()) { + print("won't run tests as simd extensions aren't activated yet"); + quit(0); +} + +(function(global) { + "use asm"; + var frd = global.Math.fround; + var fx4 = global.SIMD.Float32x4; + var fc4 = fx4.check; + var fsp = fx4.splat; + function s(){} + function d(x){x=fc4(x);} + function e() { + var x = frd(0); + x = frd(x / x); + s(); + d(fsp(x)); + } + return e; +})(this)(); + +(function(m) { + "use asm" + var k = m.SIMD.Bool32x4 + var g = m.SIMD.Int32x4 + var gc = g.check; + var h = g.select + function f() { + var x = k(0, 0, 0, 0) + var y = g(1, 2, 3, 4) + return gc(h(x, y, y)) + } + return f; +})(this)(); + +t = (function(global) { + "use asm" + var toF = global.Math.fround + var f4 = global.SIMD.Float32x4 + var f4c = f4.check + function p(x, y, width, value, max_iterations) { + x = x | 0 + y = y | 0 + width = width | 0 + value = value | 0 + max_iterations = max_iterations | 0 + } + function m(xf, yf, yd, max_iterations) { + xf = toF(xf) + yf = toF(yf) + yd = toF(yd) + max_iterations = max_iterations | 0 + var _ = f4(0, 0, 0, 0), c_im4 = f4(0, 0, 0, 0) + c_im4 = f4(yf, yd, yd, yf) + return f4c(c_im4); + } + return {p:p,m:m}; +})(this) +t.p(); +t.m(); diff --git a/js/src/jit-test/tests/asm.js/testBug1111327.js b/js/src/jit-test/tests/asm.js/testBug1111327.js new file mode 100644 index 000000000..dc1ff6c51 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1111327.js @@ -0,0 +1,11 @@ +load(libdir + "asm.js"); + +// Single-step profiling currently only works in the ARM simulator +if (!getBuildConfiguration()["arm-simulator"]) + quit(); + +enableSPSProfiling(); +enableSingleStepProfiling(); +var m = asmCompile(USE_ASM + 'function f() {} return f'); +asmLink(m)(); +asmLink(m)(); diff --git a/js/src/jit-test/tests/asm.js/testBug1117235.js b/js/src/jit-test/tests/asm.js/testBug1117235.js new file mode 100644 index 000000000..80cac617b --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1117235.js @@ -0,0 +1,8 @@ +load(libdir + "asserts.js"); + +if (helperThreadCount() === 0) + quit(0); + +options('werror'); +offThreadCompileScript("function f() {'use asm'}"); +assertThrowsInstanceOf(()=>runOffThreadScript(), TypeError); diff --git a/js/src/jit-test/tests/asm.js/testBug1117255.js b/js/src/jit-test/tests/asm.js/testBug1117255.js new file mode 100644 index 000000000..0cda6f359 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1117255.js @@ -0,0 +1,14 @@ +function f(stdlib, foreign, buffer) { + "use asm"; + var i32 = new stdlib.Int32Array(buffer); + function g(i) { + i=i|0; + var j=0; + for (; (j>>>0) < 100000; j=(j+1)|0) + i32[i>>2] = j; + } + return g +} +var g = f(this, null, new ArrayBuffer(1<<16)); +timeout(.1, function cb() { return true }); +g(1<<16); diff --git a/js/src/jit-test/tests/asm.js/testBug1125561.js b/js/src/jit-test/tests/asm.js/testBug1125561.js new file mode 100644 index 000000000..9d0d99ca4 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1125561.js @@ -0,0 +1,47 @@ +load(libdir + "asm.js"); + +setJitCompilerOption("ion.warmup.trigger", 0); +setJitCompilerOption("baseline.warmup.trigger", 0); +setJitCompilerOption("offthread-compilation.enable", 0); + +function ffi1() { assertJitStackInvariants() } +function ffi2() { return { valueOf() { assertJitStackInvariants() } } } + +// FFI with no coercion +var m = asmCompile('stdlib', 'foreign', ` + "use asm"; + var ffi = foreign.ffi; + function f() { ffi(); } + return f +`); +var f = asmLink(m, null, {ffi:ffi1}); +f(); +f(); + +// FFI with ToInt32 coercion +var m = asmCompile('stdlib', 'foreign', ` + "use asm"; + var ffi = foreign.ffi; + function f() { ffi() | 0; } + return f +`); +var f = asmLink(m, null, {ffi:ffi1}); +f(); +f(); +var f = asmLink(m, null, {ffi:ffi2}); +f(); +f(); + +// FFI with ToNumber coercion +var m = asmCompile('stdlib', 'foreign', ` + "use asm"; + var ffi = foreign.ffi; + function f() { +ffi(); } + return f +`); +var f = asmLink(m, this, {ffi:ffi1}); +f(); +f(); +var f = asmLink(m, this, {ffi:ffi2}); +f(); +f(); diff --git a/js/src/jit-test/tests/asm.js/testBug1147144.js b/js/src/jit-test/tests/asm.js/testBug1147144.js new file mode 100644 index 000000000..fbdf3a396 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1147144.js @@ -0,0 +1,20 @@ +load(libdir + 'asm.js'); +load(libdir + 'asserts.js'); + +if (!isAsmJSCompilationAvailable()) + quit(); + +setDiscardSource(true) +assertEq(eval(`(function asmModule() { "use asm"; function asmFun() {} return asmFun })`).toString(), "function asmModule() {\n [sourceless code]\n}"); +assertEq(eval(`(function asmModule() { "use asm"; function asmFun() {} return asmFun })`).toSource(), "(function asmModule() {\n [sourceless code]\n})"); +assertEq(eval(`(function asmModule() { "use asm"; function asmFun() {} return asmFun })`)().toString(), "function asmFun() {\n [sourceless code]\n}"); +assertEq(eval(`(function asmModule() { "use asm"; function asmFun() {} return asmFun })`)().toSource(), "function asmFun() {\n [sourceless code]\n}"); +assertEq((evaluate(`function asmModule1() { "use asm"; function asmFun() {} return asmFun }`), asmModule1).toString(), "function asmModule1() {\n [sourceless code]\n}"); +assertEq((evaluate(`function asmModule2() { "use asm"; function asmFun() {} return asmFun }`), asmModule2).toSource(), "function asmModule2() {\n [sourceless code]\n}"); +assertEq((evaluate(`function asmModule3() { "use asm"; function asmFun() {} return asmFun }`), asmModule3)().toString(), "function asmFun() {\n [sourceless code]\n}"); +assertEq((evaluate(`function asmModule4() { "use asm"; function asmFun() {} return asmFun }`), asmModule4)().toSource(), "function asmFun() {\n [sourceless code]\n}"); +assertEq(asmCompile(USE_ASM + `function asmFun() {} return asmFun`).toString(), "function anonymous() {\n [sourceless code]\n}"); +assertEq(asmCompile(USE_ASM + `function asmFun() {} return asmFun`).toSource(), "(function anonymous() {\n [sourceless code]\n})"); +assertEq(asmCompile(USE_ASM + `function asmFun() {} return asmFun`)().toString(), "function asmFun() {\n [sourceless code]\n}"); +assertEq(asmCompile(USE_ASM + `function asmFun() {} return asmFun`)().toSource(), "function asmFun() {\n [sourceless code]\n}"); +assertThrowsInstanceOf(()=>asmCompile('stdlib',USE_ASM + "var sin=stdlib.Math.sin;return {}")({Math:{}}), Error); diff --git a/js/src/jit-test/tests/asm.js/testBug1155176.js b/js/src/jit-test/tests/asm.js/testBug1155176.js new file mode 100644 index 000000000..80c6f6314 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1155176.js @@ -0,0 +1,52 @@ +if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable()) + quit(0); + +load(libdir + "asm.js"); +setJitCompilerOption('asmjs.atomics.enable', 1); + +// The way this is constructed, either the first module does not +// verify as asm.js (if the >>>0 is left off, which was legal prior to +// bug 1155176), or the results of the two modules have to be equal. + +var m = asmCompile("stdlib", "ffi", "heap", ` + "use asm"; + + var view = new stdlib.Uint32Array(heap); + var cas = stdlib.Atomics.compareExchange; + var hi = ffi.hi; + + function run() { + hi(+(cas(view, 37, 0, 0)>>>0)); + } + + return run; +`); + +assertEq(isAsmJSModule(m), true); + +function nonm(stdlib, ffi, heap) { + + var view = new stdlib.Uint32Array(heap); + var cas = stdlib.Atomics.compareExchange; + var hi = ffi.hi; + + function run() { + hi(+cas(view, 37, 0, 0)); + } + + return run; +} + +var sab = new SharedArrayBuffer(65536); +var ua = new Uint32Array(sab); +var results = []; +var mrun = m(this, {hi: function (x) { results.push(x) }}, sab); +var nonmrun = nonm(this, {hi: function (x) { results.push(x) }}, sab); + +ua[37] = 0x80000001; + +mrun(); +nonmrun(); + +assertEq(results[0], ua[37]); +assertEq(results[0], results[1]); diff --git a/js/src/jit-test/tests/asm.js/testBug1164391.js b/js/src/jit-test/tests/asm.js/testBug1164391.js new file mode 100644 index 000000000..80ec8659c --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1164391.js @@ -0,0 +1,27 @@ +if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable()) + quit(0); + +load(libdir + "asm.js"); +load(libdir + "asserts.js"); +setJitCompilerOption('asmjs.atomics.enable', 1); + +var m = asmCompile("stdlib", "ffi", "heap", ` + "use asm"; + var HEAP32 = new stdlib.Int32Array(heap); + var add = stdlib.Atomics.add; + var load = stdlib.Atomics.load; + function add_sharedEv(i1) { + i1 = i1 | 0; + load(HEAP32, i1 >> 2); + add(HEAP32, i1 >> 2, 1); + load(HEAP32, i1 >> 2); + } + return {add_sharedEv:add_sharedEv}; +`); + +if (isAsmJSCompilationAvailable()) + assertEq(isAsmJSModule(m), true); + +var sab = new SharedArrayBuffer(65536); +var {add_sharedEv} = m(this, {}, sab); +assertErrorMessage(() => add_sharedEv(sab.byteLength), WebAssembly.RuntimeError, /index out of bounds/); diff --git a/js/src/jit-test/tests/asm.js/testBug1183060.js b/js/src/jit-test/tests/asm.js/testBug1183060.js new file mode 100644 index 000000000..af2e9cf1b --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1183060.js @@ -0,0 +1,55 @@ +if (!this.SharedArrayBuffer) + quit(0); + +function loadModule_uint16(stdlib, foreign, heap) { + "use asm"; + var atomic_add = stdlib.Atomics.add; + var atomic_sub = stdlib.Atomics.sub; + var atomic_and = stdlib.Atomics.and; + var atomic_or = stdlib.Atomics.or; + var atomic_xor = stdlib.Atomics.xor; + var i16a = new stdlib.Uint16Array(heap); + function do_add_i(i) { + i = i|0; + var v = 0; + v = atomic_add(i16a, i>>1, 0x3333)|0; + } + function do_sub_i(i) { + i = i|0; + var v = 0; + v = atomic_sub(i16a, i>>1, 0x3333)|0; + } + function do_and_i(i) { + i = i|0; + var v = 0; + v = atomic_and(i16a, i>>1, 0x3333)|0; + } + function do_or_i(i) { + i = i|0; + var v = 0; + v = atomic_or(i16a, i>>1, 0x3333)|0; + } + function do_xor_i(i) { + i = i|0; + var v = 0; + v = atomic_xor(i16a, i>>1, 0x3333)|0; + } + return { add_i: do_add_i, + sub_i: do_sub_i, + and_i: do_and_i, + or_i: do_or_i, + xor_i: do_xor_i }; +} + +function test_uint16(heap) { + var i16m = loadModule_uint16(this, {}, heap); + var size = Uint16Array.BYTES_PER_ELEMENT; + i16m.add_i(size*40) + i16m.sub_i(size*40) + i16m.and_i(size*40) + i16m.or_i(size*40) + i16m.xor_i(size*40) +} + +var heap = new SharedArrayBuffer(65536); +test_uint16(heap); diff --git a/js/src/jit-test/tests/asm.js/testBug1219098.js b/js/src/jit-test/tests/asm.js/testBug1219098.js new file mode 100644 index 000000000..1573ec460 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1219098.js @@ -0,0 +1,14 @@ +load(libdir + "asm.js"); + +var bigScript = ` + function wee() { return 42 } + function asmModule() { 'use asm'; function f() { return 43 } return f} +` + ' '.repeat(10 * 1024 * 1024); + +eval(bigScript); + +if (isAsmJSCompilationAvailable()) + assertEq(isAsmJSModule(asmModule), true); + +assertEq(wee(), 42); +assertEq(eval('(' + wee.toSource() + ')')(), 42); diff --git a/js/src/jit-test/tests/asm.js/testBug1236484.js b/js/src/jit-test/tests/asm.js/testBug1236484.js new file mode 100644 index 000000000..61a8b49dc --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1236484.js @@ -0,0 +1,10 @@ +var lfcode = new Array(); +lfcode.push("gczeal(2, 1);"); +lfcode.push(` +function test(stdlib, foreign) { + "use asm" + function f(y) {} + return f +}`); +for (var i = 0; i < 2; ++i) + evaluate(lfcode.shift()); diff --git a/js/src/jit-test/tests/asm.js/testBug1236541.js b/js/src/jit-test/tests/asm.js/testBug1236541.js new file mode 100644 index 000000000..7f6d54999 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1236541.js @@ -0,0 +1,15 @@ +enableSPSProfiling(); + +function mod() { + "use asm"; + function f(i0) { + i0 = i0 | 0 + switch (0) { + case 0: + } + } + return f; +} + +mod()(); +mod()(); diff --git a/js/src/jit-test/tests/asm.js/testBug1236552.js b/js/src/jit-test/tests/asm.js/testBug1236552.js new file mode 100644 index 000000000..2a47ba7ec --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1236552.js @@ -0,0 +1,3 @@ +g = newGlobal(); +Debugger(g).memory.trackingAllocationSites = true; +evaluate("function h() { 'use asm'; return {}}", { global: g }); diff --git a/js/src/jit-test/tests/asm.js/testBug1255954.js b/js/src/jit-test/tests/asm.js/testBug1255954.js new file mode 100644 index 000000000..5529d950e --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1255954.js @@ -0,0 +1,14 @@ +// |jit-test| slow + +const USE_ASM = '"use asm";'; +if (!('oomTest' in this)) + quit(); +function asmCompile() { + var f = Function.apply(null, arguments); +} +oomTest(() => { + try { + function f(b) {} + } catch (exc0) {} + f(asmCompile(USE_ASM + "function f() { var i=42; return i|0; for(;1;) {} return 0 } return f")); +}); diff --git a/js/src/jit-test/tests/asm.js/testBug1291887.js b/js/src/jit-test/tests/asm.js/testBug1291887.js new file mode 100644 index 000000000..7632f0bf3 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1291887.js @@ -0,0 +1,13 @@ +(function(stdlib) { + "use asm" + var log = stdlib.Math.log + + function f(x) { + x = +x + var y = 3. + return 0, y + return +log(x) + y + } + + return f +})(this) diff --git a/js/src/jit-test/tests/asm.js/testBug1301191.js b/js/src/jit-test/tests/asm.js/testBug1301191.js new file mode 100644 index 000000000..46426bc46 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1301191.js @@ -0,0 +1,24 @@ +// |jit-test| exitstatus:6 +timeout(1); +// Adapted from randomly chosen test: js/src/jit-test/tests/asm.js/testBug975182.js +(function() { + g = (function(t, foreign) { + "use asm"; + var ff = foreign.ff; + function f() { + ff() + } + return f + })(this, { + ff: arguments.callee + }) +})() +function m(f) { + var i = 0; + while (true) { + f(); + if ((i++ % 1000) === 0) + gc(); + } +} +m(g); diff --git a/js/src/jit-test/tests/asm.js/testBug1302407.js b/js/src/jit-test/tests/asm.js/testBug1302407.js new file mode 100644 index 000000000..545d6d6b2 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug1302407.js @@ -0,0 +1,6 @@ +if (!this['SharedArrayBuffer']) + quit(); + +setJitCompilerOption('asmjs.atomics.enable', 1); +new SharedArrayBuffer(65536); +setJitCompilerOption('asmjs.atomics.enable', 0) diff --git a/js/src/jit-test/tests/asm.js/testBug855442.js b/js/src/jit-test/tests/asm.js/testBug855442.js new file mode 100644 index 000000000..cd95449f0 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug855442.js @@ -0,0 +1,8 @@ +gczeal(2,4); +function asmModule(g, foreign, heap) { + "use asm"; + var HEAP8 = new g.Int8Array(heap); + function f() {} + return {f: f}; +} +asmModule(this, 2, new ArrayBuffer(2048)); diff --git a/js/src/jit-test/tests/asm.js/testBug863867.js b/js/src/jit-test/tests/asm.js/testBug863867.js new file mode 100644 index 000000000..4d5a2dce1 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug863867.js @@ -0,0 +1,34 @@ +assertEq((function() { + 'use asm'; + function _main() { + var $1=0, $2=0, $3=0, $4=0, $5=0, $6=0, $7=0, $8=0, $9=0, $10=0, label=0; + label = 1; + while (1) { + switch (label | 0) { + case 1: + $2 = $1 + 14 | 0; + $3 = $1; + label = 20; + break; + case 20: + $5 = $2; + $4 = $3; + label = 24; + break; + case 24: + $7 = $5 + 1 | 0; + $8 = $4 + 1 | 0; + return $8|0; + case 49: + $9 = $6 + 1 | 0; + if ($10) { + $6 = $9; + break; + } + return 0; + } + } + return 0; + } + return _main; +})()(), 1); diff --git a/js/src/jit-test/tests/asm.js/testBug878435.js b/js/src/jit-test/tests/asm.js/testBug878435.js new file mode 100644 index 000000000..965b28002 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug878435.js @@ -0,0 +1,11 @@ +function g() +{ + "use asm"; + function f() + { + return (0 > (0x80000000 | 0)) | 0; + } + return f; +} + +assertEq(g()(), (0 > (0x80000000 | 0)) | 0); diff --git a/js/src/jit-test/tests/asm.js/testBug878495.js b/js/src/jit-test/tests/asm.js/testBug878495.js new file mode 100644 index 000000000..a4c01f4d4 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug878495.js @@ -0,0 +1,10 @@ +var disassemble = disassemble || false; +if (disassemble) +{ + disassemble("-r", (function() { + (function() { + "use asm" + return {} + })() + })) +} diff --git a/js/src/jit-test/tests/asm.js/testBug878520.js b/js/src/jit-test/tests/asm.js/testBug878520.js new file mode 100644 index 000000000..fbc335872 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug878520.js @@ -0,0 +1,9 @@ +function surprise(depth) { + arguments.callee.caller(depth); +} + +(function(depth) { + function foo() { function asmModule() { 'use asm'; return {} } }; + if (depth) + surprise(depth - 1); +})(2); diff --git a/js/src/jit-test/tests/asm.js/testBug892291.js b/js/src/jit-test/tests/asm.js/testBug892291.js new file mode 100644 index 000000000..9e0ae9761 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug892291.js @@ -0,0 +1,10 @@ +function a(stdlib) { + "use asm"; + var imul = stdlib.Math.imul; + function f() { + return ((imul(-800, 0xf8ba1243)|0) % -1)|0; + } + return f; +} +var f = a(this); +assertEq(f(), 0); diff --git a/js/src/jit-test/tests/asm.js/testBug893364.js b/js/src/jit-test/tests/asm.js/testBug893364.js new file mode 100644 index 000000000..8a0eadd35 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug893364.js @@ -0,0 +1,14 @@ +function m() +{ + "use asm"; + function f() + { + var x = 0; + var y = 0; + x = (((0x77777777 - 0xcccccccc) | 0) % -1) | 0; + y = (((0x7FFFFFFF + 0x7FFFFFFF) | 0) % -1) | 0; + return (x+y)|0; + } + return f; +} +assertEq(m()(), 0) diff --git a/js/src/jit-test/tests/asm.js/testBug893368.js b/js/src/jit-test/tests/asm.js/testBug893368.js new file mode 100644 index 000000000..b149390e7 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug893368.js @@ -0,0 +1,13 @@ +function m(stdlib) +{ + "use asm"; + var abs = stdlib.Math.abs; + function f(p) + { + p = p|0; + return ((abs(p|0)|0) % 3)|0; + } + return f; +} +var f = m(this); +assertEq(f(0x80000000), -2); diff --git a/js/src/jit-test/tests/asm.js/testBug893519.js b/js/src/jit-test/tests/asm.js/testBug893519.js new file mode 100644 index 000000000..8995c6e87 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug893519.js @@ -0,0 +1,11 @@ +// |jit-test| error:Error + +if (!isAsmJSCompilationAvailable()) { + throw new Error('this test expects an error to be thrown, here it is'); + quit(); +} + +var g = newGlobal(); +evaluate("function h() { function f() { 'use asm'; function g() { return 42 } return g } return f }", { global:g}); +var h = clone(g.h); +assertEq(h()()(), 42); diff --git a/js/src/jit-test/tests/asm.js/testBug907085.js b/js/src/jit-test/tests/asm.js/testBug907085.js new file mode 100644 index 000000000..fb35331df --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug907085.js @@ -0,0 +1,22 @@ +try { + s.e +} catch (e) {} +o = o = s2 = /x/ +for (let e in []); +x = s2 +schedulegc(21) +eval("x.e=x.t") +try { + (function() { + this.eval("\ + (function(stdlib,fgn,heap) {\ + \"use asm\";\ + var Vie = new stdlib.Float64Array(heap);\ + var Iew = new stdlib.Int8Array(heap);\ + function f(){\ + ent\ + }\ + })()\ + ") + })() +} catch (e) {} diff --git a/js/src/jit-test/tests/asm.js/testBug952022.js b/js/src/jit-test/tests/asm.js/testBug952022.js new file mode 100644 index 000000000..12f5d71f8 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug952022.js @@ -0,0 +1,57 @@ +function g(f) { + for (var j = 0; j < 9; ++j) { + try { + f() + } catch (e) {} + } +} +function h(code) { + Function(code)(); +} +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +g([]); +h("\ + m = (function(stdlib, foreign) { \ + \"use asm\";\ + var ff=foreign.ff;\ + function f(){\ + ff(0);\ + } \ + return f \ + })(this , { \ + ff: arguments.callee.caller\ + });\ + g(m , []);\ +"); +h("\ + m = undefined;\ + gc();\ +") diff --git a/js/src/jit-test/tests/asm.js/testBug965767.js b/js/src/jit-test/tests/asm.js/testBug965767.js new file mode 100644 index 000000000..95ddc6522 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug965767.js @@ -0,0 +1,2098 @@ +var buffer = new ArrayBuffer(4096); + +function testmod (glob, env, b) { + 'use asm'; + var f32=new glob.Float32Array(b) + function fn1() { + f32[0 >> 2]=2.0 + f32[4 >> 2]=2.125 + f32[8 >> 2]=2.25 + f32[12 >> 2]=2.375 + f32[16 >> 2]=2.5 + f32[20 >> 2]=2.625 + f32[24 >> 2]=2.75 + f32[28 >> 2]=2.875 + f32[32 >> 2]=3.0 + f32[36 >> 2]=3.125 + f32[40 >> 2]=3.25 + f32[44 >> 2]=3.375 + f32[48 >> 2]=3.5 + f32[52 >> 2]=3.625 + f32[56 >> 2]=3.75 + f32[60 >> 2]=3.875 + f32[64 >> 2]=4.0 + f32[68 >> 2]=4.25 + f32[72 >> 2]=4.5 + f32[76 >> 2]=4.75 + f32[80 >> 2]=5.0 + f32[84 >> 2]=5.25 + f32[88 >> 2]=5.5 + f32[92 >> 2]=5.75 + f32[96 >> 2]=6.0 + f32[100 >> 2]=6.25 + f32[104 >> 2]=6.5 + f32[108 >> 2]=6.75 + f32[112 >> 2]=7.0 + f32[116 >> 2]=7.25 + f32[120 >> 2]=7.5 + f32[124 >> 2]=7.75 + f32[128 >> 2]=8.0 + f32[132 >> 2]=8.5 + f32[136 >> 2]=9.0 + f32[140 >> 2]=9.5 + f32[144 >> 2]=10.0 + f32[148 >> 2]=10.5 + f32[152 >> 2]=11.0 + f32[156 >> 2]=11.5 + f32[160 >> 2]=12.0 + f32[164 >> 2]=12.5 + f32[168 >> 2]=13.0 + f32[172 >> 2]=13.5 + f32[176 >> 2]=14.0 + f32[180 >> 2]=14.5 + f32[184 >> 2]=15.0 + f32[188 >> 2]=15.5 + f32[192 >> 2]=16.0 + f32[196 >> 2]=17.0 + f32[200 >> 2]=18.0 + f32[204 >> 2]=19.0 + f32[208 >> 2]=20.0 + f32[212 >> 2]=21.0 + f32[216 >> 2]=22.0 + f32[220 >> 2]=23.0 + f32[224 >> 2]=24.0 + f32[228 >> 2]=25.0 + f32[232 >> 2]=26.0 + f32[236 >> 2]=27.0 + f32[240 >> 2]=28.0 + f32[244 >> 2]=29.0 + f32[248 >> 2]=30.0 + f32[252 >> 2]=31.0 + f32[256 >> 2]=0.125 + f32[260 >> 2]=0.1328125 + f32[264 >> 2]=0.140625 + f32[268 >> 2]=0.1484375 + f32[272 >> 2]=0.15625 + f32[276 >> 2]=0.1640625 + f32[280 >> 2]=0.171875 + f32[284 >> 2]=0.1796875 + f32[288 >> 2]=0.1875 + f32[292 >> 2]=0.1953125 + f32[296 >> 2]=0.203125 + f32[300 >> 2]=0.2109375 + f32[304 >> 2]=0.21875 + f32[308 >> 2]=0.2265625 + f32[312 >> 2]=0.234375 + f32[316 >> 2]=0.2421875 + f32[320 >> 2]=0.25 + f32[324 >> 2]=0.265625 + f32[328 >> 2]=0.28125 + f32[332 >> 2]=0.296875 + f32[336 >> 2]=0.3125 + f32[340 >> 2]=0.328125 + f32[344 >> 2]=0.34375 + f32[348 >> 2]=0.359375 + f32[352 >> 2]=0.375 + f32[356 >> 2]=0.390625 + f32[360 >> 2]=0.40625 + f32[364 >> 2]=0.421875 + f32[368 >> 2]=0.4375 + f32[368 >> 2]=0.4375 + f32[372 >> 2]=0.453125 + f32[376 >> 2]=0.46875 + f32[380 >> 2]=0.484375 + f32[384 >> 2]=0.5 + f32[388 >> 2]=0.53125 + f32[392 >> 2]=0.5625 + f32[396 >> 2]=0.59375 + f32[400 >> 2]=0.625 + f32[404 >> 2]=0.65625 + f32[408 >> 2]=0.6875 + f32[412 >> 2]=0.71875 + f32[416 >> 2]=0.75 + f32[420 >> 2]=0.78125 + f32[424 >> 2]=0.8125 + f32[428 >> 2]=0.84375 + f32[432 >> 2]=0.875 + f32[436 >> 2]=0.90625 + f32[440 >> 2]=0.9375 + f32[444 >> 2]=0.96875 + f32[448 >> 2]=1.0 + f32[452 >> 2]=1.0625 + f32[456 >> 2]=1.125 + f32[460 >> 2]=1.1875 + f32[464 >> 2]=1.25 + f32[468 >> 2]=1.3125 + f32[472 >> 2]=1.375 + f32[476 >> 2]=1.4375 + f32[480 >> 2]=1.5 + f32[484 >> 2]=1.5625 + f32[488 >> 2]=1.625 + f32[492 >> 2]=1.6875 + f32[496 >> 2]=1.75 + f32[500 >> 2]=1.8125 + f32[504 >> 2]=1.875 + f32[508 >> 2]=1.9375 + f32[512 >> 2]=-2.0 + f32[516 >> 2]=-2.125 + f32[520 >> 2]=-2.25 + f32[524 >> 2]=-2.375 + f32[528 >> 2]=-2.5 + f32[532 >> 2]=-2.625 + f32[536 >> 2]=-2.75 + f32[540 >> 2]=-2.875 + f32[544 >> 2]=-3.0 + f32[548 >> 2]=-3.125 + f32[552 >> 2]=-3.25 + f32[556 >> 2]=-3.375 + f32[560 >> 2]=-3.5 + f32[564 >> 2]=-3.625 + f32[568 >> 2]=-3.75 + f32[572 >> 2]=-3.875 + f32[576 >> 2]=-4.0 + f32[580 >> 2]=-4.25 + f32[584 >> 2]=-4.5 + f32[588 >> 2]=-4.75 + f32[592 >> 2]=-5.0 + f32[596 >> 2]=-5.25 + f32[600 >> 2]=-5.5 + f32[604 >> 2]=-5.75 + f32[608 >> 2]=-6.0 + f32[612 >> 2]=-6.25 + f32[616 >> 2]=-6.5 + f32[620 >> 2]=-6.75 + f32[624 >> 2]=-7.0 + f32[628 >> 2]=-7.25 + f32[632 >> 2]=-7.5 + f32[636 >> 2]=-7.75 + f32[640 >> 2]=-8.0 + f32[644 >> 2]=-8.5 + f32[648 >> 2]=-9.0 + f32[652 >> 2]=-9.5 + f32[656 >> 2]=-10.0 + f32[660 >> 2]=-10.5 + f32[664 >> 2]=-11.0 + f32[668 >> 2]=-11.5 + f32[672 >> 2]=-12.0 + f32[676 >> 2]=-12.5 + f32[680 >> 2]=-13.0 + f32[684 >> 2]=-13.5 + f32[688 >> 2]=-14.0 + f32[692 >> 2]=-14.5 + f32[696 >> 2]=-15.0 + f32[700 >> 2]=-15.5 + f32[704 >> 2]=-16.0 + f32[708 >> 2]=-17.0 + f32[712 >> 2]=-18.0 + f32[716 >> 2]=-19.0 + f32[720 >> 2]=-20.0 + f32[724 >> 2]=-21.0 + f32[728 >> 2]=-22.0 + f32[732 >> 2]=-23.0 + f32[736 >> 2]=-24.0 + f32[740 >> 2]=-25.0 + f32[744 >> 2]=-26.0 + f32[748 >> 2]=-27.0 + f32[752 >> 2]=-28.0 + f32[756 >> 2]=-29.0 + f32[760 >> 2]=-30.0 + f32[764 >> 2]=-31.0 + f32[768 >> 2]=-0.125 + f32[768 >> 2]=-0.125 + f32[772 >> 2]=-0.1328125 + f32[776 >> 2]=-0.140625 + f32[780 >> 2]=-0.1484375 + f32[784 >> 2]=-0.15625 + f32[788 >> 2]=-0.1640625 + f32[792 >> 2]=-0.171875 + f32[796 >> 2]=-0.1796875 + f32[800 >> 2]=-0.1875 + f32[804 >> 2]=-0.1953125 + f32[808 >> 2]=-0.203125 + f32[812 >> 2]=-0.2109375 + f32[816 >> 2]=-0.21875 + f32[820 >> 2]=-0.2265625 + f32[824 >> 2]=-0.234375 + f32[828 >> 2]=-0.2421875 + f32[832 >> 2]=-0.25 + f32[836 >> 2]=-0.265625 + f32[840 >> 2]=-0.28125 + f32[844 >> 2]=-0.296875 + f32[848 >> 2]=-0.3125 + f32[852 >> 2]=-0.328125 + f32[856 >> 2]=-0.34375 + f32[860 >> 2]=-0.359375 + f32[864 >> 2]=-0.375 + f32[868 >> 2]=-0.390625 + f32[872 >> 2]=-0.40625 + f32[876 >> 2]=-0.421875 + f32[880 >> 2]=-0.4375 + f32[884 >> 2]=-0.453125 + f32[888 >> 2]=-0.46875 + f32[892 >> 2]=-0.484375 + f32[896 >> 2]=-0.5 + f32[900 >> 2]=-0.53125 + f32[904 >> 2]=-0.5625 + f32[908 >> 2]=-0.59375 + f32[912 >> 2]=-0.625 + f32[916 >> 2]=-0.65625 + f32[920 >> 2]=-0.6875 + f32[924 >> 2]=-0.71875 + f32[928 >> 2]=-0.75 + f32[932 >> 2]=-0.78125 + f32[936 >> 2]=-0.8125 + f32[940 >> 2]=-0.84375 + f32[944 >> 2]=-0.875 + f32[948 >> 2]=-0.90625 + f32[952 >> 2]=-0.9375 + f32[956 >> 2]=-0.96875 + f32[960 >> 2]=-1.0 + f32[964 >> 2]=-1.0625 + f32[968 >> 2]=-1.125 + f32[972 >> 2]=-1.1875 + f32[976 >> 2]=-1.25 + f32[980 >> 2]=-1.3125 + f32[984 >> 2]=-1.375 + f32[988 >> 2]=-1.4375 + f32[992 >> 2]=-1.5 + f32[996 >> 2]=-1.5625 + f32[1000 >> 2]=-1.625 + f32[1004 >> 2]=-1.6875 + f32[1008 >> 2]=-1.75 + f32[1012 >> 2]=-1.8125 + f32[1016 >> 2]=-1.875 + f32[1020 >> 2]=-1.9375 + + // Some cases that should not be encoded as an immediate on the ARM. + + // All the low zero bits set. + f32[1024 >> 2]=2.1249998 + f32[1028 >> 2]=2.2499998 + f32[1032 >> 2]=2.3749998 + f32[1036 >> 2]=2.4999998 + f32[1040 >> 2]=2.6249998 + f32[1044 >> 2]=2.7499998 + f32[1048 >> 2]=2.8749998 + f32[1052 >> 2]=2.9999998 + f32[1056 >> 2]=3.1249998 + f32[1060 >> 2]=3.2499998 + f32[1064 >> 2]=3.3749998 + f32[1068 >> 2]=3.4999998 + f32[1072 >> 2]=3.6249998 + f32[1076 >> 2]=3.7499998 + f32[1080 >> 2]=3.8749998 + f32[1084 >> 2]=3.9999998 + f32[1088 >> 2]=4.2499995 + f32[1092 >> 2]=4.4999995 + f32[1096 >> 2]=4.7499995 + f32[1100 >> 2]=4.9999995 + f32[1104 >> 2]=5.2499995 + f32[1108 >> 2]=5.4999995 + f32[1112 >> 2]=5.7499995 + f32[1116 >> 2]=5.9999995 + f32[1120 >> 2]=6.2499995 + f32[1124 >> 2]=6.4999995 + f32[1128 >> 2]=6.7499995 + f32[1132 >> 2]=6.9999995 + f32[1136 >> 2]=7.2499995 + f32[1140 >> 2]=7.4999995 + f32[1144 >> 2]=7.7499995 + f32[1148 >> 2]=7.9999995 + f32[1152 >> 2]=8.499999 + f32[1156 >> 2]=8.999999 + f32[1160 >> 2]=9.499999 + f32[1164 >> 2]=9.999999 + f32[1168 >> 2]=10.499999 + f32[1172 >> 2]=10.999999 + f32[1176 >> 2]=11.499999 + f32[1180 >> 2]=11.999999 + f32[1184 >> 2]=12.499999 + f32[1188 >> 2]=12.999999 + f32[1192 >> 2]=13.499999 + f32[1196 >> 2]=13.999999 + f32[1200 >> 2]=14.499999 + f32[1204 >> 2]=14.999999 + f32[1208 >> 2]=15.499999 + f32[1212 >> 2]=15.999999 + f32[1216 >> 2]=16.999998 + f32[1220 >> 2]=17.999998 + f32[1224 >> 2]=18.999998 + f32[1228 >> 2]=19.999998 + f32[1232 >> 2]=20.999998 + f32[1236 >> 2]=21.999998 + f32[1240 >> 2]=22.999998 + f32[1244 >> 2]=23.999998 + f32[1248 >> 2]=24.999998 + f32[1252 >> 2]=25.999998 + f32[1256 >> 2]=26.999998 + f32[1260 >> 2]=27.999998 + f32[1264 >> 2]=28.999998 + f32[1268 >> 2]=29.999998 + f32[1272 >> 2]=30.999998 + f32[1276 >> 2]=31.999998 + f32[1280 >> 2]=0.13281249 + f32[1284 >> 2]=0.14062499 + f32[1288 >> 2]=0.14843749 + f32[1292 >> 2]=0.15624999 + f32[1296 >> 2]=0.16406249 + f32[1300 >> 2]=0.17187499 + f32[1304 >> 2]=0.17968749 + f32[1308 >> 2]=0.18749999 + f32[1312 >> 2]=0.19531249 + f32[1316 >> 2]=0.20312499 + f32[1320 >> 2]=0.21093749 + f32[1324 >> 2]=0.21874999 + f32[1328 >> 2]=0.22656249 + f32[1332 >> 2]=0.23437499 + f32[1336 >> 2]=0.24218749 + f32[1340 >> 2]=0.24999999 + f32[1344 >> 2]=0.26562497 + f32[1348 >> 2]=0.28124997 + f32[1352 >> 2]=0.29687497 + f32[1356 >> 2]=0.31249997 + f32[1360 >> 2]=0.32812497 + f32[1364 >> 2]=0.34374997 + f32[1368 >> 2]=0.35937497 + f32[1372 >> 2]=0.37499997 + f32[1376 >> 2]=0.39062497 + f32[1380 >> 2]=0.40624997 + f32[1384 >> 2]=0.42187497 + f32[1388 >> 2]=0.43749997 + f32[1392 >> 2]=0.45312497 + f32[1396 >> 2]=0.46874997 + f32[1400 >> 2]=0.48437497 + f32[1404 >> 2]=0.49999997 + f32[1408 >> 2]=0.53124994 + f32[1412 >> 2]=0.56249994 + f32[1416 >> 2]=0.59374994 + f32[1420 >> 2]=0.62499994 + f32[1424 >> 2]=0.65624994 + f32[1428 >> 2]=0.68749994 + f32[1432 >> 2]=0.71874994 + f32[1436 >> 2]=0.74999994 + f32[1440 >> 2]=0.78124994 + f32[1444 >> 2]=0.81249994 + f32[1448 >> 2]=0.84374994 + f32[1452 >> 2]=0.87499994 + f32[1456 >> 2]=0.90624994 + f32[1460 >> 2]=0.93749994 + f32[1464 >> 2]=0.96874994 + f32[1468 >> 2]=0.99999994 + f32[1472 >> 2]=1.0624999 + f32[1476 >> 2]=1.1249999 + f32[1480 >> 2]=1.1874999 + f32[1484 >> 2]=1.2499999 + f32[1488 >> 2]=1.3124999 + f32[1488 >> 2]=1.3124999 + f32[1492 >> 2]=1.3749999 + f32[1496 >> 2]=1.4374999 + f32[1500 >> 2]=1.4999999 + f32[1504 >> 2]=1.5624999 + f32[1508 >> 2]=1.6249999 + f32[1512 >> 2]=1.6874999 + f32[1516 >> 2]=1.7499999 + f32[1520 >> 2]=1.8124999 + f32[1524 >> 2]=1.8749999 + f32[1528 >> 2]=1.9374999 + f32[1532 >> 2]=1.9999999 + f32[1536 >> 2]=-2.1249998 + f32[1540 >> 2]=-2.2499998 + f32[1544 >> 2]=-2.3749998 + f32[1548 >> 2]=-2.4999998 + f32[1552 >> 2]=-2.6249998 + f32[1556 >> 2]=-2.7499998 + f32[1560 >> 2]=-2.8749998 + f32[1564 >> 2]=-2.9999998 + f32[1568 >> 2]=-3.1249998 + f32[1572 >> 2]=-3.2499998 + f32[1576 >> 2]=-3.3749998 + f32[1580 >> 2]=-3.4999998 + f32[1584 >> 2]=-3.6249998 + f32[1588 >> 2]=-3.7499998 + f32[1592 >> 2]=-3.8749998 + f32[1596 >> 2]=-3.9999998 + f32[1600 >> 2]=-4.2499995 + f32[1604 >> 2]=-4.4999995 + f32[1608 >> 2]=-4.7499995 + f32[1612 >> 2]=-4.9999995 + f32[1616 >> 2]=-5.2499995 + f32[1620 >> 2]=-5.4999995 + f32[1624 >> 2]=-5.7499995 + f32[1628 >> 2]=-5.9999995 + f32[1632 >> 2]=-6.2499995 + f32[1636 >> 2]=-6.4999995 + f32[1640 >> 2]=-6.7499995 + f32[1644 >> 2]=-6.9999995 + f32[1648 >> 2]=-7.2499995 + f32[1652 >> 2]=-7.4999995 + f32[1656 >> 2]=-7.7499995 + f32[1660 >> 2]=-7.9999995 + f32[1664 >> 2]=-8.499999 + f32[1668 >> 2]=-8.999999 + f32[1672 >> 2]=-9.499999 + f32[1676 >> 2]=-9.999999 + f32[1680 >> 2]=-10.499999 + f32[1684 >> 2]=-10.999999 + f32[1688 >> 2]=-11.499999 + f32[1692 >> 2]=-11.999999 + f32[1696 >> 2]=-12.499999 + f32[1700 >> 2]=-12.999999 + f32[1704 >> 2]=-13.499999 + f32[1708 >> 2]=-13.999999 + f32[1712 >> 2]=-14.499999 + f32[1716 >> 2]=-14.999999 + f32[1720 >> 2]=-15.499999 + f32[1724 >> 2]=-15.999999 + f32[1728 >> 2]=-16.999998 + f32[1732 >> 2]=-17.999998 + f32[1736 >> 2]=-18.999998 + f32[1740 >> 2]=-19.999998 + f32[1744 >> 2]=-20.999998 + f32[1748 >> 2]=-21.999998 + f32[1752 >> 2]=-22.999998 + f32[1756 >> 2]=-23.999998 + f32[1760 >> 2]=-24.999998 + f32[1764 >> 2]=-25.999998 + f32[1768 >> 2]=-26.999998 + f32[1772 >> 2]=-27.999998 + f32[1776 >> 2]=-28.999998 + f32[1780 >> 2]=-29.999998 + f32[1784 >> 2]=-30.999998 + f32[1788 >> 2]=-31.999998 + f32[1792 >> 2]=-0.13281249 + f32[1796 >> 2]=-0.14062499 + f32[1800 >> 2]=-0.14843749 + f32[1804 >> 2]=-0.15624999 + f32[1808 >> 2]=-0.16406249 + f32[1812 >> 2]=-0.17187499 + f32[1816 >> 2]=-0.17968749 + f32[1820 >> 2]=-0.18749999 + f32[1824 >> 2]=-0.19531249 + f32[1828 >> 2]=-0.20312499 + f32[1832 >> 2]=-0.21093749 + f32[1836 >> 2]=-0.21874999 + f32[1840 >> 2]=-0.22656249 + f32[1844 >> 2]=-0.23437499 + f32[1848 >> 2]=-0.24218749 + f32[1852 >> 2]=-0.24999999 + f32[1856 >> 2]=-0.26562497 + f32[1860 >> 2]=-0.28124997 + f32[1864 >> 2]=-0.29687497 + f32[1868 >> 2]=-0.31249997 + f32[1872 >> 2]=-0.32812497 + f32[1876 >> 2]=-0.34374997 + f32[1880 >> 2]=-0.35937497 + f32[1884 >> 2]=-0.37499997 + f32[1888 >> 2]=-0.39062497 + f32[1888 >> 2]=-0.39062497 + f32[1892 >> 2]=-0.40624997 + f32[1896 >> 2]=-0.42187497 + f32[1900 >> 2]=-0.43749997 + f32[1904 >> 2]=-0.45312497 + f32[1908 >> 2]=-0.46874997 + f32[1912 >> 2]=-0.48437497 + f32[1916 >> 2]=-0.49999997 + f32[1920 >> 2]=-0.53124994 + f32[1924 >> 2]=-0.56249994 + f32[1928 >> 2]=-0.59374994 + f32[1932 >> 2]=-0.62499994 + f32[1936 >> 2]=-0.65624994 + f32[1940 >> 2]=-0.68749994 + f32[1944 >> 2]=-0.71874994 + f32[1948 >> 2]=-0.74999994 + f32[1952 >> 2]=-0.78124994 + f32[1956 >> 2]=-0.81249994 + f32[1960 >> 2]=-0.84374994 + f32[1964 >> 2]=-0.87499994 + f32[1968 >> 2]=-0.90624994 + f32[1972 >> 2]=-0.93749994 + f32[1976 >> 2]=-0.96874994 + f32[1980 >> 2]=-0.99999994 + f32[1984 >> 2]=-1.0624999 + f32[1988 >> 2]=-1.1249999 + f32[1992 >> 2]=-1.1874999 + f32[1996 >> 2]=-1.2499999 + f32[2000 >> 2]=-1.3124999 + f32[2004 >> 2]=-1.3749999 + f32[2008 >> 2]=-1.4374999 + f32[2012 >> 2]=-1.4999999 + f32[2016 >> 2]=-1.5624999 + f32[2020 >> 2]=-1.6249999 + f32[2024 >> 2]=-1.6874999 + f32[2028 >> 2]=-1.7499999 + f32[2032 >> 2]=-1.8124999 + f32[2036 >> 2]=-1.8749999 + f32[2040 >> 2]=-1.9374999 + f32[2044 >> 2]=-1.9999999 + + // Just the lowest zero bit set. + f32[2048 >> 2]=2.0000002 + f32[2052 >> 2]=2.1250002 + f32[2056 >> 2]=2.2500002 + f32[2060 >> 2]=2.3750002 + f32[2064 >> 2]=2.5000002 + f32[2068 >> 2]=2.6250002 + f32[2072 >> 2]=2.7500002 + f32[2076 >> 2]=2.8750002 + f32[2080 >> 2]=3.0000002 + f32[2084 >> 2]=3.1250002 + f32[2088 >> 2]=3.2500002 + f32[2092 >> 2]=3.3750002 + f32[2096 >> 2]=3.5000002 + f32[2100 >> 2]=3.6250002 + f32[2104 >> 2]=3.7500002 + f32[2108 >> 2]=3.8750002 + f32[2112 >> 2]=4.0000005 + f32[2116 >> 2]=4.2500005 + f32[2120 >> 2]=4.5000005 + f32[2124 >> 2]=4.7500005 + f32[2128 >> 2]=5.0000005 + f32[2132 >> 2]=5.2500005 + f32[2136 >> 2]=5.5000005 + f32[2140 >> 2]=5.7500005 + f32[2140 >> 2]=5.7500005 + f32[2144 >> 2]=6.0000005 + f32[2148 >> 2]=6.2500005 + f32[2152 >> 2]=6.5000005 + f32[2156 >> 2]=6.7500005 + f32[2160 >> 2]=7.0000005 + f32[2164 >> 2]=7.2500005 + f32[2168 >> 2]=7.5000005 + f32[2172 >> 2]=7.7500005 + f32[2176 >> 2]=8.000001 + f32[2180 >> 2]=8.500001 + f32[2184 >> 2]=9.000001 + f32[2188 >> 2]=9.500001 + f32[2192 >> 2]=10.000001 + f32[2196 >> 2]=10.500001 + f32[2200 >> 2]=11.000001 + f32[2204 >> 2]=11.500001 + f32[2208 >> 2]=12.000001 + f32[2212 >> 2]=12.500001 + f32[2216 >> 2]=13.000001 + f32[2220 >> 2]=13.500001 + f32[2224 >> 2]=14.000001 + f32[2228 >> 2]=14.500001 + f32[2232 >> 2]=15.000001 + f32[2236 >> 2]=15.500001 + f32[2240 >> 2]=16.000002 + f32[2244 >> 2]=17.000002 + f32[2248 >> 2]=18.000002 + f32[2252 >> 2]=19.000002 + f32[2256 >> 2]=20.000002 + f32[2260 >> 2]=21.000002 + f32[2264 >> 2]=22.000002 + f32[2268 >> 2]=23.000002 + f32[2272 >> 2]=24.000002 + f32[2276 >> 2]=25.000002 + f32[2280 >> 2]=26.000002 + f32[2284 >> 2]=27.000002 + f32[2288 >> 2]=28.000002 + f32[2292 >> 2]=29.000002 + f32[2296 >> 2]=30.000002 + f32[2300 >> 2]=31.000002 + f32[2304 >> 2]=0.12500001 + f32[2308 >> 2]=0.13281251 + f32[2312 >> 2]=0.14062501 + f32[2316 >> 2]=0.14843751 + f32[2320 >> 2]=0.15625001 + f32[2324 >> 2]=0.16406251 + f32[2328 >> 2]=0.17187501 + f32[2332 >> 2]=0.17968751 + f32[2336 >> 2]=0.18750001 + f32[2340 >> 2]=0.19531251 + f32[2344 >> 2]=0.20312501 + f32[2348 >> 2]=0.21093751 + f32[2352 >> 2]=0.21875001 + f32[2356 >> 2]=0.22656251 + f32[2360 >> 2]=0.23437501 + f32[2364 >> 2]=0.24218751 + f32[2368 >> 2]=0.25000003 + f32[2372 >> 2]=0.26562503 + f32[2376 >> 2]=0.28125003 + f32[2380 >> 2]=0.29687503 + f32[2384 >> 2]=0.31250003 + f32[2388 >> 2]=0.32812503 + f32[2392 >> 2]=0.34375003 + f32[2396 >> 2]=0.35937503 + f32[2400 >> 2]=0.37500003 + f32[2404 >> 2]=0.39062503 + f32[2408 >> 2]=0.40625003 + f32[2412 >> 2]=0.42187503 + f32[2416 >> 2]=0.43750003 + f32[2420 >> 2]=0.45312503 + f32[2424 >> 2]=0.46875003 + f32[2428 >> 2]=0.48437503 + f32[2432 >> 2]=0.50000006 + f32[2436 >> 2]=0.53125006 + f32[2440 >> 2]=0.56250006 + f32[2444 >> 2]=0.59375006 + f32[2448 >> 2]=0.62500006 + f32[2452 >> 2]=0.65625006 + f32[2456 >> 2]=0.68750006 + f32[2460 >> 2]=0.71875006 + f32[2464 >> 2]=0.75000006 + f32[2468 >> 2]=0.78125006 + f32[2472 >> 2]=0.81250006 + f32[2476 >> 2]=0.84375006 + f32[2480 >> 2]=0.87500006 + f32[2484 >> 2]=0.90625006 + f32[2488 >> 2]=0.93750006 + f32[2492 >> 2]=0.96875006 + f32[2496 >> 2]=1.0000001 + f32[2500 >> 2]=1.0625001 + f32[2504 >> 2]=1.1250001 + f32[2508 >> 2]=1.1875001 + f32[2512 >> 2]=1.2500001 + f32[2516 >> 2]=1.3125001 + f32[2520 >> 2]=1.3750001 + f32[2524 >> 2]=1.4375001 + f32[2528 >> 2]=1.5000001 + f32[2532 >> 2]=1.5625001 + f32[2536 >> 2]=1.6250001 + f32[2540 >> 2]=1.6875001 + f32[2540 >> 2]=1.6875001 + f32[2544 >> 2]=1.7500001 + f32[2548 >> 2]=1.8125001 + f32[2552 >> 2]=1.8750001 + f32[2556 >> 2]=1.9375001 + f32[2560 >> 2]=-2.0000002 + f32[2564 >> 2]=-2.1250002 + f32[2568 >> 2]=-2.2500002 + f32[2572 >> 2]=-2.3750002 + f32[2576 >> 2]=-2.5000002 + f32[2580 >> 2]=-2.6250002 + f32[2584 >> 2]=-2.7500002 + f32[2588 >> 2]=-2.8750002 + f32[2592 >> 2]=-3.0000002 + f32[2596 >> 2]=-3.1250002 + f32[2600 >> 2]=-3.2500002 + f32[2604 >> 2]=-3.3750002 + f32[2608 >> 2]=-3.5000002 + f32[2612 >> 2]=-3.6250002 + f32[2616 >> 2]=-3.7500002 + f32[2620 >> 2]=-3.8750002 + f32[2624 >> 2]=-4.0000005 + f32[2628 >> 2]=-4.2500005 + f32[2632 >> 2]=-4.5000005 + f32[2636 >> 2]=-4.7500005 + f32[2640 >> 2]=-5.0000005 + f32[2644 >> 2]=-5.2500005 + f32[2648 >> 2]=-5.5000005 + f32[2652 >> 2]=-5.7500005 + f32[2656 >> 2]=-6.0000005 + f32[2660 >> 2]=-6.2500005 + f32[2664 >> 2]=-6.5000005 + f32[2668 >> 2]=-6.7500005 + f32[2672 >> 2]=-7.0000005 + f32[2676 >> 2]=-7.2500005 + f32[2680 >> 2]=-7.5000005 + f32[2684 >> 2]=-7.7500005 + f32[2688 >> 2]=-8.000001 + f32[2692 >> 2]=-8.500001 + f32[2696 >> 2]=-9.000001 + f32[2700 >> 2]=-9.500001 + f32[2704 >> 2]=-10.000001 + f32[2708 >> 2]=-10.500001 + f32[2712 >> 2]=-11.000001 + f32[2716 >> 2]=-11.500001 + f32[2720 >> 2]=-12.000001 + f32[2724 >> 2]=-12.500001 + f32[2728 >> 2]=-13.000001 + f32[2732 >> 2]=-13.500001 + f32[2736 >> 2]=-14.000001 + f32[2740 >> 2]=-14.500001 + f32[2744 >> 2]=-15.000001 + f32[2748 >> 2]=-15.500001 + f32[2752 >> 2]=-16.000002 + f32[2756 >> 2]=-17.000002 + f32[2760 >> 2]=-18.000002 + f32[2764 >> 2]=-19.000002 + f32[2768 >> 2]=-20.000002 + f32[2772 >> 2]=-21.000002 + f32[2776 >> 2]=-22.000002 + f32[2780 >> 2]=-23.000002 + f32[2784 >> 2]=-24.000002 + f32[2788 >> 2]=-25.000002 + f32[2792 >> 2]=-26.000002 + f32[2796 >> 2]=-27.000002 + f32[2800 >> 2]=-28.000002 + f32[2804 >> 2]=-29.000002 + f32[2808 >> 2]=-30.000002 + f32[2812 >> 2]=-31.000002 + f32[2816 >> 2]=-0.12500001 + f32[2820 >> 2]=-0.13281251 + f32[2824 >> 2]=-0.14062501 + f32[2828 >> 2]=-0.14843751 + f32[2832 >> 2]=-0.15625001 + f32[2836 >> 2]=-0.16406251 + f32[2840 >> 2]=-0.17187501 + f32[2844 >> 2]=-0.17968751 + f32[2848 >> 2]=-0.18750001 + f32[2852 >> 2]=-0.19531251 + f32[2856 >> 2]=-0.20312501 + f32[2860 >> 2]=-0.21093751 + f32[2864 >> 2]=-0.21875001 + f32[2868 >> 2]=-0.22656251 + f32[2872 >> 2]=-0.23437501 + f32[2876 >> 2]=-0.24218751 + f32[2880 >> 2]=-0.25000003 + f32[2884 >> 2]=-0.26562503 + f32[2888 >> 2]=-0.28125003 + f32[2892 >> 2]=-0.29687503 + f32[2896 >> 2]=-0.31250003 + f32[2900 >> 2]=-0.32812503 + f32[2904 >> 2]=-0.34375003 + f32[2908 >> 2]=-0.35937503 + f32[2912 >> 2]=-0.37500003 + f32[2916 >> 2]=-0.39062503 + f32[2920 >> 2]=-0.40625003 + f32[2924 >> 2]=-0.42187503 + f32[2928 >> 2]=-0.43750003 + f32[2932 >> 2]=-0.45312503 + f32[2936 >> 2]=-0.46875003 + f32[2940 >> 2]=-0.48437503 + f32[2940 >> 2]=-0.48437503 + f32[2944 >> 2]=-0.50000006 + f32[2948 >> 2]=-0.53125006 + f32[2952 >> 2]=-0.56250006 + f32[2956 >> 2]=-0.59375006 + f32[2960 >> 2]=-0.62500006 + f32[2964 >> 2]=-0.65625006 + f32[2968 >> 2]=-0.68750006 + f32[2972 >> 2]=-0.71875006 + f32[2976 >> 2]=-0.75000006 + f32[2980 >> 2]=-0.78125006 + f32[2984 >> 2]=-0.81250006 + f32[2988 >> 2]=-0.84375006 + f32[2992 >> 2]=-0.87500006 + f32[2996 >> 2]=-0.90625006 + f32[3000 >> 2]=-0.93750006 + f32[3004 >> 2]=-0.96875006 + f32[3008 >> 2]=-1.0000001 + f32[3012 >> 2]=-1.0625001 + f32[3016 >> 2]=-1.1250001 + f32[3020 >> 2]=-1.1875001 + f32[3024 >> 2]=-1.2500001 + f32[3028 >> 2]=-1.3125001 + f32[3032 >> 2]=-1.3750001 + f32[3036 >> 2]=-1.4375001 + f32[3040 >> 2]=-1.5000001 + f32[3044 >> 2]=-1.5625001 + f32[3048 >> 2]=-1.6250001 + f32[3052 >> 2]=-1.6875001 + f32[3056 >> 2]=-1.7500001 + f32[3060 >> 2]=-1.8125001 + f32[3064 >> 2]=-1.8750001 + f32[3068 >> 2]=-1.9375001 + + // Just the highest zero bit set. + f32[3073 >> 2]=2.0625 + f32[3073 >> 2]=2.0625 + f32[3077 >> 2]=2.1875 + f32[3081 >> 2]=2.3125 + f32[3085 >> 2]=2.4375 + f32[3089 >> 2]=2.5625 + f32[3093 >> 2]=2.6875 + f32[3097 >> 2]=2.8125 + f32[3101 >> 2]=2.9375 + f32[3105 >> 2]=3.0625 + f32[3109 >> 2]=3.1875 + f32[3113 >> 2]=3.3125 + f32[3117 >> 2]=3.4375 + f32[3121 >> 2]=3.5625 + f32[3125 >> 2]=3.6875 + f32[3129 >> 2]=3.8125 + f32[3133 >> 2]=3.9375 + f32[3137 >> 2]=4.125 + f32[3141 >> 2]=4.375 + f32[3145 >> 2]=4.625 + f32[3149 >> 2]=4.875 + f32[3153 >> 2]=5.125 + f32[3157 >> 2]=5.375 + f32[3161 >> 2]=5.625 + f32[3165 >> 2]=5.875 + f32[3169 >> 2]=6.125 + f32[3173 >> 2]=6.375 + f32[3177 >> 2]=6.625 + f32[3181 >> 2]=6.875 + f32[3185 >> 2]=7.125 + f32[3189 >> 2]=7.375 + f32[3193 >> 2]=7.625 + f32[3197 >> 2]=7.875 + f32[3201 >> 2]=8.25 + f32[3205 >> 2]=8.75 + f32[3209 >> 2]=9.25 + f32[3213 >> 2]=9.75 + f32[3217 >> 2]=10.25 + f32[3221 >> 2]=10.75 + f32[3225 >> 2]=11.25 + f32[3229 >> 2]=11.75 + f32[3233 >> 2]=12.25 + f32[3237 >> 2]=12.75 + f32[3241 >> 2]=13.25 + f32[3245 >> 2]=13.75 + f32[3249 >> 2]=14.25 + f32[3253 >> 2]=14.75 + f32[3257 >> 2]=15.25 + f32[3261 >> 2]=15.75 + f32[3265 >> 2]=16.5 + f32[3269 >> 2]=17.5 + f32[3273 >> 2]=18.5 + f32[3277 >> 2]=19.5 + f32[3281 >> 2]=20.5 + f32[3285 >> 2]=21.5 + f32[3289 >> 2]=22.5 + f32[3293 >> 2]=23.5 + f32[3297 >> 2]=24.5 + f32[3301 >> 2]=25.5 + f32[3305 >> 2]=26.5 + f32[3309 >> 2]=27.5 + f32[3313 >> 2]=28.5 + f32[3317 >> 2]=29.5 + f32[3321 >> 2]=30.5 + f32[3325 >> 2]=31.5 + f32[3329 >> 2]=0.12890625 + f32[3333 >> 2]=0.13671875 + f32[3337 >> 2]=0.14453125 + f32[3341 >> 2]=0.15234375 + f32[3345 >> 2]=0.16015625 + f32[3349 >> 2]=0.16796875 + f32[3353 >> 2]=0.17578125 + f32[3357 >> 2]=0.18359375 + f32[3361 >> 2]=0.19140625 + f32[3365 >> 2]=0.19921875 + f32[3369 >> 2]=0.20703125 + f32[3373 >> 2]=0.21484375 + f32[3377 >> 2]=0.22265625 + f32[3381 >> 2]=0.23046875 + f32[3385 >> 2]=0.23828125 + f32[3389 >> 2]=0.24609375 + f32[3393 >> 2]=0.2578125 + f32[3397 >> 2]=0.2734375 + f32[3401 >> 2]=0.2890625 + f32[3405 >> 2]=0.3046875 + f32[3409 >> 2]=0.3203125 + f32[3413 >> 2]=0.3359375 + f32[3417 >> 2]=0.3515625 + f32[3421 >> 2]=0.3671875 + f32[3425 >> 2]=0.3828125 + f32[3429 >> 2]=0.3984375 + f32[3433 >> 2]=0.4140625 + f32[3437 >> 2]=0.4296875 + f32[3441 >> 2]=0.4453125 + f32[3445 >> 2]=0.4609375 + f32[3449 >> 2]=0.4765625 + f32[3453 >> 2]=0.4921875 + f32[3457 >> 2]=0.515625 + f32[3461 >> 2]=0.546875 + f32[3465 >> 2]=0.578125 + f32[3469 >> 2]=0.609375 + f32[3473 >> 2]=0.640625 + f32[3473 >> 2]=0.640625 + f32[3477 >> 2]=0.671875 + f32[3481 >> 2]=0.703125 + f32[3485 >> 2]=0.734375 + f32[3489 >> 2]=0.765625 + f32[3493 >> 2]=0.796875 + f32[3497 >> 2]=0.828125 + f32[3501 >> 2]=0.859375 + f32[3505 >> 2]=0.890625 + f32[3509 >> 2]=0.921875 + f32[3513 >> 2]=0.953125 + f32[3517 >> 2]=0.984375 + f32[3521 >> 2]=1.03125 + f32[3525 >> 2]=1.09375 + f32[3529 >> 2]=1.15625 + f32[3533 >> 2]=1.21875 + f32[3537 >> 2]=1.28125 + f32[3541 >> 2]=1.34375 + f32[3545 >> 2]=1.40625 + f32[3549 >> 2]=1.46875 + f32[3553 >> 2]=1.53125 + f32[3557 >> 2]=1.59375 + f32[3561 >> 2]=1.65625 + f32[3565 >> 2]=1.71875 + f32[3569 >> 2]=1.78125 + f32[3573 >> 2]=1.84375 + f32[3577 >> 2]=1.90625 + f32[3581 >> 2]=1.96875 + f32[3585 >> 2]=-2.0625 + f32[3589 >> 2]=-2.1875 + f32[3593 >> 2]=-2.3125 + f32[3597 >> 2]=-2.4375 + f32[3601 >> 2]=-2.5625 + f32[3605 >> 2]=-2.6875 + f32[3609 >> 2]=-2.8125 + f32[3613 >> 2]=-2.9375 + f32[3617 >> 2]=-3.0625 + f32[3621 >> 2]=-3.1875 + f32[3625 >> 2]=-3.3125 + f32[3629 >> 2]=-3.4375 + f32[3633 >> 2]=-3.5625 + f32[3637 >> 2]=-3.6875 + f32[3641 >> 2]=-3.8125 + f32[3645 >> 2]=-3.9375 + f32[3649 >> 2]=-4.125 + f32[3653 >> 2]=-4.375 + f32[3657 >> 2]=-4.625 + f32[3661 >> 2]=-4.875 + f32[3665 >> 2]=-5.125 + f32[3669 >> 2]=-5.375 + f32[3673 >> 2]=-5.625 + f32[3677 >> 2]=-5.875 + f32[3681 >> 2]=-6.125 + f32[3685 >> 2]=-6.375 + f32[3689 >> 2]=-6.625 + f32[3693 >> 2]=-6.875 + f32[3697 >> 2]=-7.125 + f32[3701 >> 2]=-7.375 + f32[3705 >> 2]=-7.625 + f32[3709 >> 2]=-7.875 + f32[3713 >> 2]=-8.25 + f32[3717 >> 2]=-8.75 + f32[3721 >> 2]=-9.25 + f32[3725 >> 2]=-9.75 + f32[3729 >> 2]=-10.25 + f32[3733 >> 2]=-10.75 + f32[3737 >> 2]=-11.25 + f32[3741 >> 2]=-11.75 + f32[3745 >> 2]=-12.25 + f32[3749 >> 2]=-12.75 + f32[3753 >> 2]=-13.25 + f32[3757 >> 2]=-13.75 + f32[3761 >> 2]=-14.25 + f32[3765 >> 2]=-14.75 + f32[3769 >> 2]=-15.25 + f32[3773 >> 2]=-15.75 + f32[3777 >> 2]=-16.5 + f32[3781 >> 2]=-17.5 + f32[3785 >> 2]=-18.5 + f32[3789 >> 2]=-19.5 + f32[3793 >> 2]=-20.5 + f32[3797 >> 2]=-21.5 + f32[3801 >> 2]=-22.5 + f32[3805 >> 2]=-23.5 + f32[3809 >> 2]=-24.5 + f32[3813 >> 2]=-25.5 + f32[3817 >> 2]=-26.5 + f32[3821 >> 2]=-27.5 + f32[3825 >> 2]=-28.5 + f32[3829 >> 2]=-29.5 + f32[3833 >> 2]=-30.5 + f32[3837 >> 2]=-31.5 + f32[3841 >> 2]=-0.12890625 + f32[3845 >> 2]=-0.13671875 + f32[3849 >> 2]=-0.14453125 + f32[3853 >> 2]=-0.15234375 + f32[3857 >> 2]=-0.16015625 + f32[3861 >> 2]=-0.16796875 + f32[3865 >> 2]=-0.17578125 + f32[3869 >> 2]=-0.18359375 + f32[3873 >> 2]=-0.19140625 + f32[3873 >> 2]=-0.19140625 + f32[3877 >> 2]=-0.19921875 + f32[3881 >> 2]=-0.20703125 + f32[3885 >> 2]=-0.21484375 + f32[3889 >> 2]=-0.22265625 + f32[3893 >> 2]=-0.23046875 + f32[3897 >> 2]=-0.23828125 + f32[3901 >> 2]=-0.24609375 + f32[3905 >> 2]=-0.2578125 + f32[3909 >> 2]=-0.2734375 + f32[3913 >> 2]=-0.2890625 + f32[3917 >> 2]=-0.3046875 + f32[3921 >> 2]=-0.3203125 + f32[3925 >> 2]=-0.3359375 + f32[3929 >> 2]=-0.3515625 + f32[3933 >> 2]=-0.3671875 + f32[3937 >> 2]=-0.3828125 + f32[3941 >> 2]=-0.3984375 + f32[3945 >> 2]=-0.4140625 + f32[3949 >> 2]=-0.4296875 + f32[3953 >> 2]=-0.4453125 + f32[3957 >> 2]=-0.4609375 + f32[3961 >> 2]=-0.4765625 + f32[3965 >> 2]=-0.4921875 + f32[3969 >> 2]=-0.515625 + f32[3973 >> 2]=-0.546875 + f32[3977 >> 2]=-0.578125 + f32[3981 >> 2]=-0.609375 + f32[3985 >> 2]=-0.640625 + f32[3989 >> 2]=-0.671875 + f32[3993 >> 2]=-0.703125 + f32[3997 >> 2]=-0.734375 + f32[4001 >> 2]=-0.765625 + f32[4005 >> 2]=-0.796875 + f32[4009 >> 2]=-0.828125 + f32[4013 >> 2]=-0.859375 + f32[4017 >> 2]=-0.890625 + f32[4021 >> 2]=-0.921875 + f32[4025 >> 2]=-0.953125 + f32[4029 >> 2]=-0.984375 + f32[4033 >> 2]=-1.03125 + f32[4037 >> 2]=-1.09375 + f32[4041 >> 2]=-1.15625 + f32[4045 >> 2]=-1.21875 + f32[4049 >> 2]=-1.28125 + f32[4053 >> 2]=-1.34375 + f32[4057 >> 2]=-1.40625 + f32[4061 >> 2]=-1.46875 + f32[4065 >> 2]=-1.53125 + f32[4069 >> 2]=-1.59375 + f32[4073 >> 2]=-1.65625 + f32[4077 >> 2]=-1.71875 + f32[4081 >> 2]=-1.78125 + f32[4085 >> 2]=-1.84375 + f32[4089 >> 2]=-1.90625 + f32[4093 >> 2]=-1.96875 + }; + + return { + fn1: fn1 + }; +}; + +var asm = testmod(this, {}, buffer); + +asm.fn1() + +var f32=new Float32Array(buffer); +assertEq(f32[0 >> 2], 2.0) +assertEq(f32[4 >> 2], 2.125) +assertEq(f32[8 >> 2], 2.25) +assertEq(f32[12 >> 2], 2.375) +assertEq(f32[16 >> 2], 2.5) +assertEq(f32[20 >> 2], 2.625) +assertEq(f32[24 >> 2], 2.75) +assertEq(f32[28 >> 2], 2.875) +assertEq(f32[32 >> 2], 3.0) +assertEq(f32[36 >> 2], 3.125) +assertEq(f32[40 >> 2], 3.25) +assertEq(f32[44 >> 2], 3.375) +assertEq(f32[48 >> 2], 3.5) +assertEq(f32[52 >> 2], 3.625) +assertEq(f32[56 >> 2], 3.75) +assertEq(f32[60 >> 2], 3.875) +assertEq(f32[64 >> 2], 4.0) +assertEq(f32[68 >> 2], 4.25) +assertEq(f32[72 >> 2], 4.5) +assertEq(f32[76 >> 2], 4.75) +assertEq(f32[80 >> 2], 5.0) +assertEq(f32[84 >> 2], 5.25) +assertEq(f32[88 >> 2], 5.5) +assertEq(f32[92 >> 2], 5.75) +assertEq(f32[96 >> 2], 6.0) +assertEq(f32[100 >> 2], 6.25) +assertEq(f32[104 >> 2], 6.5) +assertEq(f32[108 >> 2], 6.75) +assertEq(f32[112 >> 2], 7.0) +assertEq(f32[116 >> 2], 7.25) +assertEq(f32[120 >> 2], 7.5) +assertEq(f32[124 >> 2], 7.75) +assertEq(f32[128 >> 2], 8.0) +assertEq(f32[132 >> 2], 8.5) +assertEq(f32[136 >> 2], 9.0) +assertEq(f32[140 >> 2], 9.5) +assertEq(f32[144 >> 2], 10.0) +assertEq(f32[148 >> 2], 10.5) +assertEq(f32[152 >> 2], 11.0) +assertEq(f32[156 >> 2], 11.5) +assertEq(f32[160 >> 2], 12.0) +assertEq(f32[164 >> 2], 12.5) +assertEq(f32[168 >> 2], 13.0) +assertEq(f32[172 >> 2], 13.5) +assertEq(f32[176 >> 2], 14.0) +assertEq(f32[180 >> 2], 14.5) +assertEq(f32[184 >> 2], 15.0) +assertEq(f32[188 >> 2], 15.5) +assertEq(f32[192 >> 2], 16.0) +assertEq(f32[196 >> 2], 17.0) +assertEq(f32[200 >> 2], 18.0) +assertEq(f32[204 >> 2], 19.0) +assertEq(f32[208 >> 2], 20.0) +assertEq(f32[212 >> 2], 21.0) +assertEq(f32[216 >> 2], 22.0) +assertEq(f32[220 >> 2], 23.0) +assertEq(f32[224 >> 2], 24.0) +assertEq(f32[228 >> 2], 25.0) +assertEq(f32[232 >> 2], 26.0) +assertEq(f32[236 >> 2], 27.0) +assertEq(f32[240 >> 2], 28.0) +assertEq(f32[244 >> 2], 29.0) +assertEq(f32[248 >> 2], 30.0) +assertEq(f32[252 >> 2], 31.0) +assertEq(f32[256 >> 2], 0.125) +assertEq(f32[260 >> 2], 0.1328125) +assertEq(f32[264 >> 2], 0.140625) +assertEq(f32[268 >> 2], 0.1484375) +assertEq(f32[272 >> 2], 0.15625) +assertEq(f32[276 >> 2], 0.1640625) +assertEq(f32[280 >> 2], 0.171875) +assertEq(f32[284 >> 2], 0.1796875) +assertEq(f32[288 >> 2], 0.1875) +assertEq(f32[292 >> 2], 0.1953125) +assertEq(f32[296 >> 2], 0.203125) +assertEq(f32[300 >> 2], 0.2109375) +assertEq(f32[304 >> 2], 0.21875) +assertEq(f32[308 >> 2], 0.2265625) +assertEq(f32[312 >> 2], 0.234375) +assertEq(f32[316 >> 2], 0.2421875) +assertEq(f32[320 >> 2], 0.25) +assertEq(f32[324 >> 2], 0.265625) +assertEq(f32[328 >> 2], 0.28125) +assertEq(f32[332 >> 2], 0.296875) +assertEq(f32[336 >> 2], 0.3125) +assertEq(f32[340 >> 2], 0.328125) +assertEq(f32[344 >> 2], 0.34375) +assertEq(f32[348 >> 2], 0.359375) +assertEq(f32[348 >> 2], 0.359375) +assertEq(f32[352 >> 2], 0.375) +assertEq(f32[356 >> 2], 0.390625) +assertEq(f32[360 >> 2], 0.40625) +assertEq(f32[364 >> 2], 0.421875) +assertEq(f32[368 >> 2], 0.4375) +assertEq(f32[372 >> 2], 0.453125) +assertEq(f32[376 >> 2], 0.46875) +assertEq(f32[380 >> 2], 0.484375) +assertEq(f32[384 >> 2], 0.5) +assertEq(f32[388 >> 2], 0.53125) +assertEq(f32[392 >> 2], 0.5625) +assertEq(f32[396 >> 2], 0.59375) +assertEq(f32[400 >> 2], 0.625) +assertEq(f32[404 >> 2], 0.65625) +assertEq(f32[408 >> 2], 0.6875) +assertEq(f32[412 >> 2], 0.71875) +assertEq(f32[416 >> 2], 0.75) +assertEq(f32[420 >> 2], 0.78125) +assertEq(f32[424 >> 2], 0.8125) +assertEq(f32[428 >> 2], 0.84375) +assertEq(f32[432 >> 2], 0.875) +assertEq(f32[436 >> 2], 0.90625) +assertEq(f32[440 >> 2], 0.9375) +assertEq(f32[444 >> 2], 0.96875) +assertEq(f32[448 >> 2], 1.0) +assertEq(f32[452 >> 2], 1.0625) +assertEq(f32[456 >> 2], 1.125) +assertEq(f32[460 >> 2], 1.1875) +assertEq(f32[464 >> 2], 1.25) +assertEq(f32[468 >> 2], 1.3125) +assertEq(f32[472 >> 2], 1.375) +assertEq(f32[476 >> 2], 1.4375) +assertEq(f32[480 >> 2], 1.5) +assertEq(f32[484 >> 2], 1.5625) +assertEq(f32[488 >> 2], 1.625) +assertEq(f32[492 >> 2], 1.6875) +assertEq(f32[496 >> 2], 1.75) +assertEq(f32[500 >> 2], 1.8125) +assertEq(f32[504 >> 2], 1.875) +assertEq(f32[508 >> 2], 1.9375) +assertEq(f32[512 >> 2], -2.0) +assertEq(f32[516 >> 2], -2.125) +assertEq(f32[520 >> 2], -2.25) +assertEq(f32[524 >> 2], -2.375) +assertEq(f32[528 >> 2], -2.5) +assertEq(f32[532 >> 2], -2.625) +assertEq(f32[536 >> 2], -2.75) +assertEq(f32[540 >> 2], -2.875) +assertEq(f32[544 >> 2], -3.0) +assertEq(f32[548 >> 2], -3.125) +assertEq(f32[552 >> 2], -3.25) +assertEq(f32[556 >> 2], -3.375) +assertEq(f32[560 >> 2], -3.5) +assertEq(f32[564 >> 2], -3.625) +assertEq(f32[568 >> 2], -3.75) +assertEq(f32[572 >> 2], -3.875) +assertEq(f32[576 >> 2], -4.0) +assertEq(f32[580 >> 2], -4.25) +assertEq(f32[584 >> 2], -4.5) +assertEq(f32[588 >> 2], -4.75) +assertEq(f32[592 >> 2], -5.0) +assertEq(f32[596 >> 2], -5.25) +assertEq(f32[600 >> 2], -5.5) +assertEq(f32[604 >> 2], -5.75) +assertEq(f32[608 >> 2], -6.0) +assertEq(f32[612 >> 2], -6.25) +assertEq(f32[616 >> 2], -6.5) +assertEq(f32[620 >> 2], -6.75) +assertEq(f32[624 >> 2], -7.0) +assertEq(f32[628 >> 2], -7.25) +assertEq(f32[632 >> 2], -7.5) +assertEq(f32[636 >> 2], -7.75) +assertEq(f32[640 >> 2], -8.0) +assertEq(f32[644 >> 2], -8.5) +assertEq(f32[648 >> 2], -9.0) +assertEq(f32[652 >> 2], -9.5) +assertEq(f32[656 >> 2], -10.0) +assertEq(f32[660 >> 2], -10.5) +assertEq(f32[664 >> 2], -11.0) +assertEq(f32[668 >> 2], -11.5) +assertEq(f32[672 >> 2], -12.0) +assertEq(f32[676 >> 2], -12.5) +assertEq(f32[680 >> 2], -13.0) +assertEq(f32[684 >> 2], -13.5) +assertEq(f32[688 >> 2], -14.0) +assertEq(f32[692 >> 2], -14.5) +assertEq(f32[696 >> 2], -15.0) +assertEq(f32[700 >> 2], -15.5) +assertEq(f32[704 >> 2], -16.0) +assertEq(f32[708 >> 2], -17.0) +assertEq(f32[712 >> 2], -18.0) +assertEq(f32[716 >> 2], -19.0) +assertEq(f32[720 >> 2], -20.0) +assertEq(f32[724 >> 2], -21.0) +assertEq(f32[728 >> 2], -22.0) +assertEq(f32[732 >> 2], -23.0) +assertEq(f32[736 >> 2], -24.0) +assertEq(f32[740 >> 2], -25.0) +assertEq(f32[744 >> 2], -26.0) +assertEq(f32[748 >> 2], -27.0) +assertEq(f32[748 >> 2], -27.0) +assertEq(f32[752 >> 2], -28.0) +assertEq(f32[756 >> 2], -29.0) +assertEq(f32[760 >> 2], -30.0) +assertEq(f32[764 >> 2], -31.0) +assertEq(f32[768 >> 2], -0.125) +assertEq(f32[772 >> 2], -0.1328125) +assertEq(f32[776 >> 2], -0.140625) +assertEq(f32[780 >> 2], -0.1484375) +assertEq(f32[784 >> 2], -0.15625) +assertEq(f32[788 >> 2], -0.1640625) +assertEq(f32[792 >> 2], -0.171875) +assertEq(f32[796 >> 2], -0.1796875) +assertEq(f32[800 >> 2], -0.1875) +assertEq(f32[804 >> 2], -0.1953125) +assertEq(f32[808 >> 2], -0.203125) +assertEq(f32[812 >> 2], -0.2109375) +assertEq(f32[816 >> 2], -0.21875) +assertEq(f32[820 >> 2], -0.2265625) +assertEq(f32[824 >> 2], -0.234375) +assertEq(f32[828 >> 2], -0.2421875) +assertEq(f32[832 >> 2], -0.25) +assertEq(f32[836 >> 2], -0.265625) +assertEq(f32[840 >> 2], -0.28125) +assertEq(f32[844 >> 2], -0.296875) +assertEq(f32[848 >> 2], -0.3125) +assertEq(f32[852 >> 2], -0.328125) +assertEq(f32[856 >> 2], -0.34375) +assertEq(f32[860 >> 2], -0.359375) +assertEq(f32[864 >> 2], -0.375) +assertEq(f32[868 >> 2], -0.390625) +assertEq(f32[872 >> 2], -0.40625) +assertEq(f32[876 >> 2], -0.421875) +assertEq(f32[880 >> 2], -0.4375) +assertEq(f32[884 >> 2], -0.453125) +assertEq(f32[888 >> 2], -0.46875) +assertEq(f32[892 >> 2], -0.484375) +assertEq(f32[896 >> 2], -0.5) +assertEq(f32[900 >> 2], -0.53125) +assertEq(f32[904 >> 2], -0.5625) +assertEq(f32[908 >> 2], -0.59375) +assertEq(f32[912 >> 2], -0.625) +assertEq(f32[916 >> 2], -0.65625) +assertEq(f32[920 >> 2], -0.6875) +assertEq(f32[924 >> 2], -0.71875) +assertEq(f32[928 >> 2], -0.75) +assertEq(f32[932 >> 2], -0.78125) +assertEq(f32[936 >> 2], -0.8125) +assertEq(f32[940 >> 2], -0.84375) +assertEq(f32[944 >> 2], -0.875) +assertEq(f32[948 >> 2], -0.90625) +assertEq(f32[952 >> 2], -0.9375) +assertEq(f32[956 >> 2], -0.96875) +assertEq(f32[960 >> 2], -1.0) +assertEq(f32[964 >> 2], -1.0625) +assertEq(f32[968 >> 2], -1.125) +assertEq(f32[972 >> 2], -1.1875) +assertEq(f32[976 >> 2], -1.25) +assertEq(f32[980 >> 2], -1.3125) +assertEq(f32[984 >> 2], -1.375) +assertEq(f32[988 >> 2], -1.4375) +assertEq(f32[992 >> 2], -1.5) +assertEq(f32[996 >> 2], -1.5625) +assertEq(f32[1000 >> 2], -1.625) +assertEq(f32[1004 >> 2], -1.6875) +assertEq(f32[1008 >> 2], -1.75) +assertEq(f32[1012 >> 2], -1.8125) +assertEq(f32[1016 >> 2], -1.875) +assertEq(f32[1020 >> 2], -1.9375) + +assertEq(f32[1024 >> 2], 2.124999761581421) +assertEq(f32[1028 >> 2], 2.249999761581421) +assertEq(f32[1032 >> 2], 2.374999761581421) +assertEq(f32[1036 >> 2], 2.499999761581421) +assertEq(f32[1040 >> 2], 2.624999761581421) +assertEq(f32[1044 >> 2], 2.749999761581421) +assertEq(f32[1048 >> 2], 2.874999761581421) +assertEq(f32[1052 >> 2], 2.999999761581421) +assertEq(f32[1056 >> 2], 3.124999761581421) +assertEq(f32[1060 >> 2], 3.249999761581421) +assertEq(f32[1064 >> 2], 3.374999761581421) +assertEq(f32[1068 >> 2], 3.499999761581421) +assertEq(f32[1072 >> 2], 3.624999761581421) +assertEq(f32[1076 >> 2], 3.749999761581421) +assertEq(f32[1080 >> 2], 3.874999761581421) +assertEq(f32[1084 >> 2], 3.999999761581421) +assertEq(f32[1088 >> 2], 4.249999523162842) +assertEq(f32[1092 >> 2], 4.499999523162842) +assertEq(f32[1096 >> 2], 4.749999523162842) +assertEq(f32[1100 >> 2], 4.999999523162842) +assertEq(f32[1104 >> 2], 5.249999523162842) +assertEq(f32[1108 >> 2], 5.499999523162842) +assertEq(f32[1112 >> 2], 5.749999523162842) +assertEq(f32[1116 >> 2], 5.999999523162842) +assertEq(f32[1120 >> 2], 6.249999523162842) +assertEq(f32[1124 >> 2], 6.499999523162842) +assertEq(f32[1128 >> 2], 6.749999523162842) +assertEq(f32[1132 >> 2], 6.999999523162842) +assertEq(f32[1136 >> 2], 7.249999523162842) +assertEq(f32[1140 >> 2], 7.499999523162842) +assertEq(f32[1144 >> 2], 7.749999523162842) +assertEq(f32[1148 >> 2], 7.999999523162842) +assertEq(f32[1152 >> 2], 8.499999046325684) +assertEq(f32[1156 >> 2], 8.999999046325684) +assertEq(f32[1160 >> 2], 9.499999046325684) +assertEq(f32[1164 >> 2], 9.999999046325684) +assertEq(f32[1168 >> 2], 10.499999046325684) +assertEq(f32[1172 >> 2], 10.999999046325684) +assertEq(f32[1176 >> 2], 11.499999046325684) +assertEq(f32[1180 >> 2], 11.999999046325684) +assertEq(f32[1184 >> 2], 12.499999046325684) +assertEq(f32[1184 >> 2], 12.499999046325684) +assertEq(f32[1188 >> 2], 12.999999046325684) +assertEq(f32[1192 >> 2], 13.499999046325684) +assertEq(f32[1196 >> 2], 13.999999046325684) +assertEq(f32[1200 >> 2], 14.499999046325684) +assertEq(f32[1204 >> 2], 14.999999046325684) +assertEq(f32[1208 >> 2], 15.499999046325684) +assertEq(f32[1212 >> 2], 15.999999046325684) +assertEq(f32[1216 >> 2], 16.999998092651367) +assertEq(f32[1220 >> 2], 17.999998092651367) +assertEq(f32[1224 >> 2], 18.999998092651367) +assertEq(f32[1228 >> 2], 19.999998092651367) +assertEq(f32[1232 >> 2], 20.999998092651367) +assertEq(f32[1236 >> 2], 21.999998092651367) +assertEq(f32[1240 >> 2], 22.999998092651367) +assertEq(f32[1244 >> 2], 23.999998092651367) +assertEq(f32[1248 >> 2], 24.999998092651367) +assertEq(f32[1252 >> 2], 25.999998092651367) +assertEq(f32[1256 >> 2], 26.999998092651367) +assertEq(f32[1260 >> 2], 27.999998092651367) +assertEq(f32[1264 >> 2], 28.999998092651367) +assertEq(f32[1268 >> 2], 29.999998092651367) +assertEq(f32[1272 >> 2], 30.999998092651367) +assertEq(f32[1276 >> 2], 31.999998092651367) +assertEq(f32[1280 >> 2], 0.1328124850988388) +assertEq(f32[1284 >> 2], 0.1406249850988388) +assertEq(f32[1288 >> 2], 0.1484374850988388) +assertEq(f32[1292 >> 2], 0.1562499850988388) +assertEq(f32[1296 >> 2], 0.1640624850988388) +assertEq(f32[1300 >> 2], 0.1718749850988388) +assertEq(f32[1304 >> 2], 0.1796874850988388) +assertEq(f32[1308 >> 2], 0.1874999850988388) +assertEq(f32[1312 >> 2], 0.1953124850988388) +assertEq(f32[1316 >> 2], 0.2031249850988388) +assertEq(f32[1320 >> 2], 0.2109374850988388) +assertEq(f32[1324 >> 2], 0.2187499850988388) +assertEq(f32[1328 >> 2], 0.2265624850988388) +assertEq(f32[1332 >> 2], 0.2343749850988388) +assertEq(f32[1336 >> 2], 0.2421874850988388) +assertEq(f32[1340 >> 2], 0.2499999850988388) +assertEq(f32[1344 >> 2], 0.2656249701976776) +assertEq(f32[1348 >> 2], 0.2812499701976776) +assertEq(f32[1352 >> 2], 0.2968749701976776) +assertEq(f32[1356 >> 2], 0.3124999701976776) +assertEq(f32[1360 >> 2], 0.3281249701976776) +assertEq(f32[1364 >> 2], 0.3437499701976776) +assertEq(f32[1368 >> 2], 0.3593749701976776) +assertEq(f32[1372 >> 2], 0.3749999701976776) +assertEq(f32[1376 >> 2], 0.3906249701976776) +assertEq(f32[1380 >> 2], 0.4062499701976776) +assertEq(f32[1384 >> 2], 0.4218749701976776) +assertEq(f32[1388 >> 2], 0.4374999701976776) +assertEq(f32[1392 >> 2], 0.4531249701976776) +assertEq(f32[1396 >> 2], 0.4687499701976776) +assertEq(f32[1400 >> 2], 0.4843749701976776) +assertEq(f32[1404 >> 2], 0.4999999701976776) +assertEq(f32[1408 >> 2], 0.5312499403953552) +assertEq(f32[1412 >> 2], 0.5624999403953552) +assertEq(f32[1416 >> 2], 0.5937499403953552) +assertEq(f32[1420 >> 2], 0.6249999403953552) +assertEq(f32[1424 >> 2], 0.6562499403953552) +assertEq(f32[1428 >> 2], 0.6874999403953552) +assertEq(f32[1432 >> 2], 0.7187499403953552) +assertEq(f32[1436 >> 2], 0.7499999403953552) +assertEq(f32[1440 >> 2], 0.7812499403953552) +assertEq(f32[1444 >> 2], 0.8124999403953552) +assertEq(f32[1448 >> 2], 0.8437499403953552) +assertEq(f32[1452 >> 2], 0.8749999403953552) +assertEq(f32[1456 >> 2], 0.9062499403953552) +assertEq(f32[1460 >> 2], 0.9374999403953552) +assertEq(f32[1464 >> 2], 0.9687499403953552) +assertEq(f32[1468 >> 2], 0.9999999403953552) +assertEq(f32[1472 >> 2], 1.0624998807907104) +assertEq(f32[1476 >> 2], 1.1249998807907104) +assertEq(f32[1480 >> 2], 1.1874998807907104) +assertEq(f32[1484 >> 2], 1.2499998807907104) +assertEq(f32[1488 >> 2], 1.3124998807907104) +assertEq(f32[1492 >> 2], 1.3749998807907104) +assertEq(f32[1496 >> 2], 1.4374998807907104) +assertEq(f32[1500 >> 2], 1.4999998807907104) +assertEq(f32[1504 >> 2], 1.5624998807907104) +assertEq(f32[1508 >> 2], 1.6249998807907104) +assertEq(f32[1512 >> 2], 1.6874998807907104) +assertEq(f32[1516 >> 2], 1.7499998807907104) +assertEq(f32[1520 >> 2], 1.8124998807907104) +assertEq(f32[1524 >> 2], 1.8749998807907104) +assertEq(f32[1528 >> 2], 1.9374998807907104) +assertEq(f32[1532 >> 2], 1.9999998807907104) +assertEq(f32[1536 >> 2], -2.124999761581421) +assertEq(f32[1540 >> 2], -2.249999761581421) +assertEq(f32[1544 >> 2], -2.374999761581421) +assertEq(f32[1548 >> 2], -2.499999761581421) +assertEq(f32[1552 >> 2], -2.624999761581421) +assertEq(f32[1556 >> 2], -2.749999761581421) +assertEq(f32[1560 >> 2], -2.874999761581421) +assertEq(f32[1564 >> 2], -2.999999761581421) +assertEq(f32[1568 >> 2], -3.124999761581421) +assertEq(f32[1572 >> 2], -3.249999761581421) +assertEq(f32[1576 >> 2], -3.374999761581421) +assertEq(f32[1580 >> 2], -3.499999761581421) +assertEq(f32[1584 >> 2], -3.624999761581421) +assertEq(f32[1584 >> 2], -3.624999761581421) +assertEq(f32[1588 >> 2], -3.749999761581421) +assertEq(f32[1592 >> 2], -3.874999761581421) +assertEq(f32[1596 >> 2], -3.999999761581421) +assertEq(f32[1600 >> 2], -4.249999523162842) +assertEq(f32[1604 >> 2], -4.499999523162842) +assertEq(f32[1608 >> 2], -4.749999523162842) +assertEq(f32[1612 >> 2], -4.999999523162842) +assertEq(f32[1616 >> 2], -5.249999523162842) +assertEq(f32[1620 >> 2], -5.499999523162842) +assertEq(f32[1624 >> 2], -5.749999523162842) +assertEq(f32[1628 >> 2], -5.999999523162842) +assertEq(f32[1632 >> 2], -6.249999523162842) +assertEq(f32[1636 >> 2], -6.499999523162842) +assertEq(f32[1640 >> 2], -6.749999523162842) +assertEq(f32[1644 >> 2], -6.999999523162842) +assertEq(f32[1648 >> 2], -7.249999523162842) +assertEq(f32[1652 >> 2], -7.499999523162842) +assertEq(f32[1656 >> 2], -7.749999523162842) +assertEq(f32[1660 >> 2], -7.999999523162842) +assertEq(f32[1664 >> 2], -8.499999046325684) +assertEq(f32[1668 >> 2], -8.999999046325684) +assertEq(f32[1672 >> 2], -9.499999046325684) +assertEq(f32[1676 >> 2], -9.999999046325684) +assertEq(f32[1680 >> 2], -10.499999046325684) +assertEq(f32[1684 >> 2], -10.999999046325684) +assertEq(f32[1688 >> 2], -11.499999046325684) +assertEq(f32[1692 >> 2], -11.999999046325684) +assertEq(f32[1696 >> 2], -12.499999046325684) +assertEq(f32[1700 >> 2], -12.999999046325684) +assertEq(f32[1704 >> 2], -13.499999046325684) +assertEq(f32[1708 >> 2], -13.999999046325684) +assertEq(f32[1712 >> 2], -14.499999046325684) +assertEq(f32[1716 >> 2], -14.999999046325684) +assertEq(f32[1720 >> 2], -15.499999046325684) +assertEq(f32[1724 >> 2], -15.999999046325684) +assertEq(f32[1728 >> 2], -16.999998092651367) +assertEq(f32[1732 >> 2], -17.999998092651367) +assertEq(f32[1736 >> 2], -18.999998092651367) +assertEq(f32[1740 >> 2], -19.999998092651367) +assertEq(f32[1744 >> 2], -20.999998092651367) +assertEq(f32[1748 >> 2], -21.999998092651367) +assertEq(f32[1752 >> 2], -22.999998092651367) +assertEq(f32[1756 >> 2], -23.999998092651367) +assertEq(f32[1760 >> 2], -24.999998092651367) +assertEq(f32[1764 >> 2], -25.999998092651367) +assertEq(f32[1768 >> 2], -26.999998092651367) +assertEq(f32[1772 >> 2], -27.999998092651367) +assertEq(f32[1776 >> 2], -28.999998092651367) +assertEq(f32[1780 >> 2], -29.999998092651367) +assertEq(f32[1784 >> 2], -30.999998092651367) +assertEq(f32[1788 >> 2], -31.999998092651367) +assertEq(f32[1792 >> 2], -0.1328124850988388) +assertEq(f32[1796 >> 2], -0.1406249850988388) +assertEq(f32[1800 >> 2], -0.1484374850988388) +assertEq(f32[1804 >> 2], -0.1562499850988388) +assertEq(f32[1808 >> 2], -0.1640624850988388) +assertEq(f32[1812 >> 2], -0.1718749850988388) +assertEq(f32[1816 >> 2], -0.1796874850988388) +assertEq(f32[1820 >> 2], -0.1874999850988388) +assertEq(f32[1824 >> 2], -0.1953124850988388) +assertEq(f32[1828 >> 2], -0.2031249850988388) +assertEq(f32[1832 >> 2], -0.2109374850988388) +assertEq(f32[1836 >> 2], -0.2187499850988388) +assertEq(f32[1840 >> 2], -0.2265624850988388) +assertEq(f32[1844 >> 2], -0.2343749850988388) +assertEq(f32[1848 >> 2], -0.2421874850988388) +assertEq(f32[1852 >> 2], -0.2499999850988388) +assertEq(f32[1856 >> 2], -0.2656249701976776) +assertEq(f32[1860 >> 2], -0.2812499701976776) +assertEq(f32[1864 >> 2], -0.2968749701976776) +assertEq(f32[1868 >> 2], -0.3124999701976776) +assertEq(f32[1872 >> 2], -0.3281249701976776) +assertEq(f32[1876 >> 2], -0.3437499701976776) +assertEq(f32[1880 >> 2], -0.3593749701976776) +assertEq(f32[1884 >> 2], -0.3749999701976776) +assertEq(f32[1888 >> 2], -0.3906249701976776) +assertEq(f32[1892 >> 2], -0.4062499701976776) +assertEq(f32[1896 >> 2], -0.4218749701976776) +assertEq(f32[1900 >> 2], -0.4374999701976776) +assertEq(f32[1904 >> 2], -0.4531249701976776) +assertEq(f32[1908 >> 2], -0.4687499701976776) +assertEq(f32[1912 >> 2], -0.4843749701976776) +assertEq(f32[1916 >> 2], -0.4999999701976776) +assertEq(f32[1920 >> 2], -0.5312499403953552) +assertEq(f32[1924 >> 2], -0.5624999403953552) +assertEq(f32[1928 >> 2], -0.5937499403953552) +assertEq(f32[1932 >> 2], -0.6249999403953552) +assertEq(f32[1936 >> 2], -0.6562499403953552) +assertEq(f32[1940 >> 2], -0.6874999403953552) +assertEq(f32[1944 >> 2], -0.7187499403953552) +assertEq(f32[1948 >> 2], -0.7499999403953552) +assertEq(f32[1952 >> 2], -0.7812499403953552) +assertEq(f32[1956 >> 2], -0.8124999403953552) +assertEq(f32[1960 >> 2], -0.8437499403953552) +assertEq(f32[1964 >> 2], -0.8749999403953552) +assertEq(f32[1968 >> 2], -0.9062499403953552) +assertEq(f32[1972 >> 2], -0.9374999403953552) +assertEq(f32[1976 >> 2], -0.9687499403953552) +assertEq(f32[1980 >> 2], -0.9999999403953552) +assertEq(f32[1984 >> 2], -1.0624998807907104) +assertEq(f32[1984 >> 2], -1.0624998807907104) +assertEq(f32[1988 >> 2], -1.1249998807907104) +assertEq(f32[1992 >> 2], -1.1874998807907104) +assertEq(f32[1996 >> 2], -1.2499998807907104) +assertEq(f32[2000 >> 2], -1.3124998807907104) +assertEq(f32[2004 >> 2], -1.3749998807907104) +assertEq(f32[2008 >> 2], -1.4374998807907104) +assertEq(f32[2012 >> 2], -1.4999998807907104) +assertEq(f32[2016 >> 2], -1.5624998807907104) +assertEq(f32[2020 >> 2], -1.6249998807907104) +assertEq(f32[2024 >> 2], -1.6874998807907104) +assertEq(f32[2028 >> 2], -1.7499998807907104) +assertEq(f32[2032 >> 2], -1.8124998807907104) +assertEq(f32[2036 >> 2], -1.8749998807907104) +assertEq(f32[2040 >> 2], -1.9374998807907104) +assertEq(f32[2044 >> 2], -1.9999998807907104) + +assertEq(f32[2048 >> 2], 2.000000238418579) +assertEq(f32[2052 >> 2], 2.125000238418579) +assertEq(f32[2056 >> 2], 2.250000238418579) +assertEq(f32[2060 >> 2], 2.375000238418579) +assertEq(f32[2064 >> 2], 2.500000238418579) +assertEq(f32[2068 >> 2], 2.625000238418579) +assertEq(f32[2072 >> 2], 2.750000238418579) +assertEq(f32[2076 >> 2], 2.875000238418579) +assertEq(f32[2080 >> 2], 3.000000238418579) +assertEq(f32[2084 >> 2], 3.125000238418579) +assertEq(f32[2088 >> 2], 3.250000238418579) +assertEq(f32[2092 >> 2], 3.375000238418579) +assertEq(f32[2096 >> 2], 3.500000238418579) +assertEq(f32[2100 >> 2], 3.625000238418579) +assertEq(f32[2104 >> 2], 3.750000238418579) +assertEq(f32[2108 >> 2], 3.875000238418579) +assertEq(f32[2112 >> 2], 4.000000476837158) +assertEq(f32[2116 >> 2], 4.250000476837158) +assertEq(f32[2120 >> 2], 4.500000476837158) +assertEq(f32[2124 >> 2], 4.750000476837158) +assertEq(f32[2128 >> 2], 5.000000476837158) +assertEq(f32[2132 >> 2], 5.250000476837158) +assertEq(f32[2136 >> 2], 5.500000476837158) +assertEq(f32[2140 >> 2], 5.750000476837158) +assertEq(f32[2144 >> 2], 6.000000476837158) +assertEq(f32[2148 >> 2], 6.250000476837158) +assertEq(f32[2152 >> 2], 6.500000476837158) +assertEq(f32[2156 >> 2], 6.750000476837158) +assertEq(f32[2160 >> 2], 7.000000476837158) +assertEq(f32[2164 >> 2], 7.250000476837158) +assertEq(f32[2168 >> 2], 7.500000476837158) +assertEq(f32[2172 >> 2], 7.750000476837158) +assertEq(f32[2176 >> 2], 8.000000953674316) +assertEq(f32[2180 >> 2], 8.500000953674316) +assertEq(f32[2184 >> 2], 9.000000953674316) +assertEq(f32[2188 >> 2], 9.500000953674316) +assertEq(f32[2192 >> 2], 10.000000953674316) +assertEq(f32[2196 >> 2], 10.500000953674316) +assertEq(f32[2200 >> 2], 11.000000953674316) +assertEq(f32[2204 >> 2], 11.500000953674316) +assertEq(f32[2208 >> 2], 12.000000953674316) +assertEq(f32[2212 >> 2], 12.500000953674316) +assertEq(f32[2216 >> 2], 13.000000953674316) +assertEq(f32[2220 >> 2], 13.500000953674316) +assertEq(f32[2224 >> 2], 14.000000953674316) +assertEq(f32[2228 >> 2], 14.500000953674316) +assertEq(f32[2228 >> 2], 14.500000953674316) +assertEq(f32[2232 >> 2], 15.000000953674316) +assertEq(f32[2236 >> 2], 15.500000953674316) +assertEq(f32[2240 >> 2], 16.000001907348633) +assertEq(f32[2244 >> 2], 17.000001907348633) +assertEq(f32[2248 >> 2], 18.000001907348633) +assertEq(f32[2252 >> 2], 19.000001907348633) +assertEq(f32[2256 >> 2], 20.000001907348633) +assertEq(f32[2260 >> 2], 21.000001907348633) +assertEq(f32[2264 >> 2], 22.000001907348633) +assertEq(f32[2268 >> 2], 23.000001907348633) +assertEq(f32[2272 >> 2], 24.000001907348633) +assertEq(f32[2276 >> 2], 25.000001907348633) +assertEq(f32[2280 >> 2], 26.000001907348633) +assertEq(f32[2284 >> 2], 27.000001907348633) +assertEq(f32[2288 >> 2], 28.000001907348633) +assertEq(f32[2292 >> 2], 29.000001907348633) +assertEq(f32[2296 >> 2], 30.000001907348633) +assertEq(f32[2300 >> 2], 31.000001907348633) +assertEq(f32[2304 >> 2], 0.1250000149011612) +assertEq(f32[2308 >> 2], 0.1328125149011612) +assertEq(f32[2312 >> 2], 0.1406250149011612) +assertEq(f32[2316 >> 2], 0.1484375149011612) +assertEq(f32[2320 >> 2], 0.1562500149011612) +assertEq(f32[2324 >> 2], 0.1640625149011612) +assertEq(f32[2328 >> 2], 0.1718750149011612) +assertEq(f32[2332 >> 2], 0.1796875149011612) +assertEq(f32[2336 >> 2], 0.1875000149011612) +assertEq(f32[2340 >> 2], 0.1953125149011612) +assertEq(f32[2344 >> 2], 0.2031250149011612) +assertEq(f32[2348 >> 2], 0.2109375149011612) +assertEq(f32[2352 >> 2], 0.2187500149011612) +assertEq(f32[2356 >> 2], 0.2265625149011612) +assertEq(f32[2360 >> 2], 0.2343750149011612) +assertEq(f32[2364 >> 2], 0.2421875149011612) +assertEq(f32[2368 >> 2], 0.2500000298023224) +assertEq(f32[2372 >> 2], 0.2656250298023224) +assertEq(f32[2376 >> 2], 0.2812500298023224) +assertEq(f32[2380 >> 2], 0.2968750298023224) +assertEq(f32[2384 >> 2], 0.3125000298023224) +assertEq(f32[2388 >> 2], 0.3281250298023224) +assertEq(f32[2392 >> 2], 0.3437500298023224) +assertEq(f32[2396 >> 2], 0.3593750298023224) +assertEq(f32[2400 >> 2], 0.3750000298023224) +assertEq(f32[2404 >> 2], 0.3906250298023224) +assertEq(f32[2408 >> 2], 0.4062500298023224) +assertEq(f32[2412 >> 2], 0.4218750298023224) +assertEq(f32[2416 >> 2], 0.4375000298023224) +assertEq(f32[2420 >> 2], 0.4531250298023224) +assertEq(f32[2424 >> 2], 0.4687500298023224) +assertEq(f32[2428 >> 2], 0.4843750298023224) +assertEq(f32[2432 >> 2], 0.5000000596046448) +assertEq(f32[2436 >> 2], 0.5312500596046448) +assertEq(f32[2440 >> 2], 0.5625000596046448) +assertEq(f32[2444 >> 2], 0.5937500596046448) +assertEq(f32[2448 >> 2], 0.6250000596046448) +assertEq(f32[2452 >> 2], 0.6562500596046448) +assertEq(f32[2456 >> 2], 0.6875000596046448) +assertEq(f32[2460 >> 2], 0.7187500596046448) +assertEq(f32[2464 >> 2], 0.7500000596046448) +assertEq(f32[2468 >> 2], 0.7812500596046448) +assertEq(f32[2472 >> 2], 0.8125000596046448) +assertEq(f32[2476 >> 2], 0.8437500596046448) +assertEq(f32[2480 >> 2], 0.8750000596046448) +assertEq(f32[2484 >> 2], 0.9062500596046448) +assertEq(f32[2488 >> 2], 0.9375000596046448) +assertEq(f32[2492 >> 2], 0.9687500596046448) +assertEq(f32[2496 >> 2], 1.0000001192092896) +assertEq(f32[2500 >> 2], 1.0625001192092896) +assertEq(f32[2504 >> 2], 1.1250001192092896) +assertEq(f32[2508 >> 2], 1.1875001192092896) +assertEq(f32[2512 >> 2], 1.2500001192092896) +assertEq(f32[2516 >> 2], 1.3125001192092896) +assertEq(f32[2520 >> 2], 1.3750001192092896) +assertEq(f32[2524 >> 2], 1.4375001192092896) +assertEq(f32[2528 >> 2], 1.5000001192092896) +assertEq(f32[2532 >> 2], 1.5625001192092896) +assertEq(f32[2536 >> 2], 1.6250001192092896) +assertEq(f32[2540 >> 2], 1.6875001192092896) +assertEq(f32[2544 >> 2], 1.7500001192092896) +assertEq(f32[2548 >> 2], 1.8125001192092896) +assertEq(f32[2552 >> 2], 1.8750001192092896) +assertEq(f32[2556 >> 2], 1.9375001192092896) +assertEq(f32[2560 >> 2], -2.000000238418579) +assertEq(f32[2564 >> 2], -2.125000238418579) +assertEq(f32[2568 >> 2], -2.250000238418579) +assertEq(f32[2572 >> 2], -2.375000238418579) +assertEq(f32[2576 >> 2], -2.500000238418579) +assertEq(f32[2580 >> 2], -2.625000238418579) +assertEq(f32[2584 >> 2], -2.750000238418579) +assertEq(f32[2588 >> 2], -2.875000238418579) +assertEq(f32[2592 >> 2], -3.000000238418579) +assertEq(f32[2596 >> 2], -3.125000238418579) +assertEq(f32[2600 >> 2], -3.250000238418579) +assertEq(f32[2604 >> 2], -3.375000238418579) +assertEq(f32[2608 >> 2], -3.500000238418579) +assertEq(f32[2612 >> 2], -3.625000238418579) +assertEq(f32[2616 >> 2], -3.750000238418579) +assertEq(f32[2620 >> 2], -3.875000238418579) +assertEq(f32[2624 >> 2], -4.000000476837158) +assertEq(f32[2628 >> 2], -4.250000476837158) +assertEq(f32[2628 >> 2], -4.250000476837158) +assertEq(f32[2632 >> 2], -4.500000476837158) +assertEq(f32[2636 >> 2], -4.750000476837158) +assertEq(f32[2640 >> 2], -5.000000476837158) +assertEq(f32[2644 >> 2], -5.250000476837158) +assertEq(f32[2648 >> 2], -5.500000476837158) +assertEq(f32[2652 >> 2], -5.750000476837158) +assertEq(f32[2656 >> 2], -6.000000476837158) +assertEq(f32[2660 >> 2], -6.250000476837158) +assertEq(f32[2664 >> 2], -6.500000476837158) +assertEq(f32[2668 >> 2], -6.750000476837158) +assertEq(f32[2672 >> 2], -7.000000476837158) +assertEq(f32[2676 >> 2], -7.250000476837158) +assertEq(f32[2680 >> 2], -7.500000476837158) +assertEq(f32[2684 >> 2], -7.750000476837158) +assertEq(f32[2688 >> 2], -8.000000953674316) +assertEq(f32[2692 >> 2], -8.500000953674316) +assertEq(f32[2696 >> 2], -9.000000953674316) +assertEq(f32[2700 >> 2], -9.500000953674316) +assertEq(f32[2704 >> 2], -10.000000953674316) +assertEq(f32[2708 >> 2], -10.500000953674316) +assertEq(f32[2712 >> 2], -11.000000953674316) +assertEq(f32[2716 >> 2], -11.500000953674316) +assertEq(f32[2720 >> 2], -12.000000953674316) +assertEq(f32[2724 >> 2], -12.500000953674316) +assertEq(f32[2728 >> 2], -13.000000953674316) +assertEq(f32[2732 >> 2], -13.500000953674316) +assertEq(f32[2736 >> 2], -14.000000953674316) +assertEq(f32[2740 >> 2], -14.500000953674316) +assertEq(f32[2744 >> 2], -15.000000953674316) +assertEq(f32[2748 >> 2], -15.500000953674316) +assertEq(f32[2752 >> 2], -16.000001907348633) +assertEq(f32[2756 >> 2], -17.000001907348633) +assertEq(f32[2760 >> 2], -18.000001907348633) +assertEq(f32[2764 >> 2], -19.000001907348633) +assertEq(f32[2768 >> 2], -20.000001907348633) +assertEq(f32[2772 >> 2], -21.000001907348633) +assertEq(f32[2776 >> 2], -22.000001907348633) +assertEq(f32[2780 >> 2], -23.000001907348633) +assertEq(f32[2784 >> 2], -24.000001907348633) +assertEq(f32[2788 >> 2], -25.000001907348633) +assertEq(f32[2792 >> 2], -26.000001907348633) +assertEq(f32[2796 >> 2], -27.000001907348633) +assertEq(f32[2800 >> 2], -28.000001907348633) +assertEq(f32[2804 >> 2], -29.000001907348633) +assertEq(f32[2808 >> 2], -30.000001907348633) +assertEq(f32[2812 >> 2], -31.000001907348633) +assertEq(f32[2816 >> 2], -0.1250000149011612) +assertEq(f32[2820 >> 2], -0.1328125149011612) +assertEq(f32[2824 >> 2], -0.1406250149011612) +assertEq(f32[2828 >> 2], -0.1484375149011612) +assertEq(f32[2832 >> 2], -0.1562500149011612) +assertEq(f32[2836 >> 2], -0.1640625149011612) +assertEq(f32[2840 >> 2], -0.1718750149011612) +assertEq(f32[2844 >> 2], -0.1796875149011612) +assertEq(f32[2848 >> 2], -0.1875000149011612) +assertEq(f32[2852 >> 2], -0.1953125149011612) +assertEq(f32[2856 >> 2], -0.2031250149011612) +assertEq(f32[2860 >> 2], -0.2109375149011612) +assertEq(f32[2864 >> 2], -0.2187500149011612) +assertEq(f32[2868 >> 2], -0.2265625149011612) +assertEq(f32[2872 >> 2], -0.2343750149011612) +assertEq(f32[2876 >> 2], -0.2421875149011612) +assertEq(f32[2880 >> 2], -0.2500000298023224) +assertEq(f32[2884 >> 2], -0.2656250298023224) +assertEq(f32[2888 >> 2], -0.2812500298023224) +assertEq(f32[2892 >> 2], -0.2968750298023224) +assertEq(f32[2896 >> 2], -0.3125000298023224) +assertEq(f32[2900 >> 2], -0.3281250298023224) +assertEq(f32[2904 >> 2], -0.3437500298023224) +assertEq(f32[2908 >> 2], -0.3593750298023224) +assertEq(f32[2912 >> 2], -0.3750000298023224) +assertEq(f32[2916 >> 2], -0.3906250298023224) +assertEq(f32[2920 >> 2], -0.4062500298023224) +assertEq(f32[2924 >> 2], -0.4218750298023224) +assertEq(f32[2928 >> 2], -0.4375000298023224) +assertEq(f32[2932 >> 2], -0.4531250298023224) +assertEq(f32[2936 >> 2], -0.4687500298023224) +assertEq(f32[2940 >> 2], -0.4843750298023224) +assertEq(f32[2944 >> 2], -0.5000000596046448) +assertEq(f32[2948 >> 2], -0.5312500596046448) +assertEq(f32[2952 >> 2], -0.5625000596046448) +assertEq(f32[2956 >> 2], -0.5937500596046448) +assertEq(f32[2960 >> 2], -0.6250000596046448) +assertEq(f32[2964 >> 2], -0.6562500596046448) +assertEq(f32[2968 >> 2], -0.6875000596046448) +assertEq(f32[2972 >> 2], -0.7187500596046448) +assertEq(f32[2976 >> 2], -0.7500000596046448) +assertEq(f32[2980 >> 2], -0.7812500596046448) +assertEq(f32[2984 >> 2], -0.8125000596046448) +assertEq(f32[2988 >> 2], -0.8437500596046448) +assertEq(f32[2992 >> 2], -0.8750000596046448) +assertEq(f32[2996 >> 2], -0.9062500596046448) +assertEq(f32[3000 >> 2], -0.9375000596046448) +assertEq(f32[3004 >> 2], -0.9687500596046448) +assertEq(f32[3008 >> 2], -1.0000001192092896) +assertEq(f32[3012 >> 2], -1.0625001192092896) +assertEq(f32[3016 >> 2], -1.1250001192092896) +assertEq(f32[3020 >> 2], -1.1875001192092896) +assertEq(f32[3024 >> 2], -1.2500001192092896) +assertEq(f32[3028 >> 2], -1.3125001192092896) +assertEq(f32[3028 >> 2], -1.3125001192092896) +assertEq(f32[3032 >> 2], -1.3750001192092896) +assertEq(f32[3036 >> 2], -1.4375001192092896) +assertEq(f32[3040 >> 2], -1.5000001192092896) +assertEq(f32[3044 >> 2], -1.5625001192092896) +assertEq(f32[3048 >> 2], -1.6250001192092896) +assertEq(f32[3052 >> 2], -1.6875001192092896) +assertEq(f32[3056 >> 2], -1.7500001192092896) +assertEq(f32[3060 >> 2], -1.8125001192092896) +assertEq(f32[3064 >> 2], -1.8750001192092896) +assertEq(f32[3068 >> 2], -1.9375001192092896) + +assertEq(f32[3072 >> 2], 2.0625) +assertEq(f32[3076 >> 2], 2.1875) +assertEq(f32[3080 >> 2], 2.3125) +assertEq(f32[3084 >> 2], 2.4375) +assertEq(f32[3088 >> 2], 2.5625) +assertEq(f32[3092 >> 2], 2.6875) +assertEq(f32[3096 >> 2], 2.8125) +assertEq(f32[3100 >> 2], 2.9375) +assertEq(f32[3104 >> 2], 3.0625) +assertEq(f32[3108 >> 2], 3.1875) +assertEq(f32[3112 >> 2], 3.3125) +assertEq(f32[3116 >> 2], 3.4375) +assertEq(f32[3120 >> 2], 3.5625) +assertEq(f32[3124 >> 2], 3.6875) +assertEq(f32[3128 >> 2], 3.8125) +assertEq(f32[3132 >> 2], 3.9375) +assertEq(f32[3136 >> 2], 4.125) +assertEq(f32[3140 >> 2], 4.375) +assertEq(f32[3144 >> 2], 4.625) +assertEq(f32[3148 >> 2], 4.875) +assertEq(f32[3152 >> 2], 5.125) +assertEq(f32[3156 >> 2], 5.375) +assertEq(f32[3160 >> 2], 5.625) +assertEq(f32[3164 >> 2], 5.875) +assertEq(f32[3168 >> 2], 6.125) +assertEq(f32[3172 >> 2], 6.375) +assertEq(f32[3176 >> 2], 6.625) +assertEq(f32[3180 >> 2], 6.875) +assertEq(f32[3184 >> 2], 7.125) +assertEq(f32[3188 >> 2], 7.375) +assertEq(f32[3192 >> 2], 7.625) +assertEq(f32[3196 >> 2], 7.875) +assertEq(f32[3200 >> 2], 8.25) +assertEq(f32[3204 >> 2], 8.75) +assertEq(f32[3208 >> 2], 9.25) +assertEq(f32[3212 >> 2], 9.75) +assertEq(f32[3216 >> 2], 10.25) +assertEq(f32[3220 >> 2], 10.75) +assertEq(f32[3224 >> 2], 11.25) +assertEq(f32[3224 >> 2], 11.25) +assertEq(f32[3228 >> 2], 11.75) +assertEq(f32[3232 >> 2], 12.25) +assertEq(f32[3236 >> 2], 12.75) +assertEq(f32[3240 >> 2], 13.25) +assertEq(f32[3244 >> 2], 13.75) +assertEq(f32[3248 >> 2], 14.25) +assertEq(f32[3252 >> 2], 14.75) +assertEq(f32[3256 >> 2], 15.25) +assertEq(f32[3260 >> 2], 15.75) +assertEq(f32[3264 >> 2], 16.5) +assertEq(f32[3268 >> 2], 17.5) +assertEq(f32[3272 >> 2], 18.5) +assertEq(f32[3276 >> 2], 19.5) +assertEq(f32[3280 >> 2], 20.5) +assertEq(f32[3284 >> 2], 21.5) +assertEq(f32[3288 >> 2], 22.5) +assertEq(f32[3292 >> 2], 23.5) +assertEq(f32[3296 >> 2], 24.5) +assertEq(f32[3300 >> 2], 25.5) +assertEq(f32[3304 >> 2], 26.5) +assertEq(f32[3308 >> 2], 27.5) +assertEq(f32[3312 >> 2], 28.5) +assertEq(f32[3316 >> 2], 29.5) +assertEq(f32[3320 >> 2], 30.5) +assertEq(f32[3324 >> 2], 31.5) +assertEq(f32[3328 >> 2], 0.12890625) +assertEq(f32[3332 >> 2], 0.13671875) +assertEq(f32[3336 >> 2], 0.14453125) +assertEq(f32[3340 >> 2], 0.15234375) +assertEq(f32[3344 >> 2], 0.16015625) +assertEq(f32[3348 >> 2], 0.16796875) +assertEq(f32[3352 >> 2], 0.17578125) +assertEq(f32[3356 >> 2], 0.18359375) +assertEq(f32[3360 >> 2], 0.19140625) +assertEq(f32[3364 >> 2], 0.19921875) +assertEq(f32[3368 >> 2], 0.20703125) +assertEq(f32[3372 >> 2], 0.21484375) +assertEq(f32[3376 >> 2], 0.22265625) +assertEq(f32[3380 >> 2], 0.23046875) +assertEq(f32[3384 >> 2], 0.23828125) +assertEq(f32[3388 >> 2], 0.24609375) +assertEq(f32[3392 >> 2], 0.2578125) +assertEq(f32[3396 >> 2], 0.2734375) +assertEq(f32[3400 >> 2], 0.2890625) +assertEq(f32[3404 >> 2], 0.3046875) +assertEq(f32[3408 >> 2], 0.3203125) +assertEq(f32[3412 >> 2], 0.3359375) +assertEq(f32[3416 >> 2], 0.3515625) +assertEq(f32[3420 >> 2], 0.3671875) +assertEq(f32[3424 >> 2], 0.3828125) +assertEq(f32[3428 >> 2], 0.3984375) +assertEq(f32[3432 >> 2], 0.4140625) +assertEq(f32[3436 >> 2], 0.4296875) +assertEq(f32[3440 >> 2], 0.4453125) +assertEq(f32[3444 >> 2], 0.4609375) +assertEq(f32[3448 >> 2], 0.4765625) +assertEq(f32[3452 >> 2], 0.4921875) +assertEq(f32[3456 >> 2], 0.515625) +assertEq(f32[3460 >> 2], 0.546875) +assertEq(f32[3464 >> 2], 0.578125) +assertEq(f32[3468 >> 2], 0.609375) +assertEq(f32[3472 >> 2], 0.640625) +assertEq(f32[3476 >> 2], 0.671875) +assertEq(f32[3480 >> 2], 0.703125) +assertEq(f32[3484 >> 2], 0.734375) +assertEq(f32[3488 >> 2], 0.765625) +assertEq(f32[3492 >> 2], 0.796875) +assertEq(f32[3496 >> 2], 0.828125) +assertEq(f32[3500 >> 2], 0.859375) +assertEq(f32[3504 >> 2], 0.890625) +assertEq(f32[3508 >> 2], 0.921875) +assertEq(f32[3512 >> 2], 0.953125) +assertEq(f32[3516 >> 2], 0.984375) +assertEq(f32[3520 >> 2], 1.03125) +assertEq(f32[3524 >> 2], 1.09375) +assertEq(f32[3528 >> 2], 1.15625) +assertEq(f32[3532 >> 2], 1.21875) +assertEq(f32[3536 >> 2], 1.28125) +assertEq(f32[3540 >> 2], 1.34375) +assertEq(f32[3544 >> 2], 1.40625) +assertEq(f32[3548 >> 2], 1.46875) +assertEq(f32[3552 >> 2], 1.53125) +assertEq(f32[3556 >> 2], 1.59375) +assertEq(f32[3560 >> 2], 1.65625) +assertEq(f32[3564 >> 2], 1.71875) +assertEq(f32[3568 >> 2], 1.78125) +assertEq(f32[3572 >> 2], 1.84375) +assertEq(f32[3576 >> 2], 1.90625) +assertEq(f32[3580 >> 2], 1.96875) +assertEq(f32[3584 >> 2], -2.0625) +assertEq(f32[3588 >> 2], -2.1875) +assertEq(f32[3592 >> 2], -2.3125) +assertEq(f32[3596 >> 2], -2.4375) +assertEq(f32[3600 >> 2], -2.5625) +assertEq(f32[3604 >> 2], -2.6875) +assertEq(f32[3608 >> 2], -2.8125) +assertEq(f32[3612 >> 2], -2.9375) +assertEq(f32[3616 >> 2], -3.0625) +assertEq(f32[3620 >> 2], -3.1875) +assertEq(f32[3624 >> 2], -3.3125) +assertEq(f32[3624 >> 2], -3.3125) +assertEq(f32[3628 >> 2], -3.4375) +assertEq(f32[3632 >> 2], -3.5625) +assertEq(f32[3636 >> 2], -3.6875) +assertEq(f32[3640 >> 2], -3.8125) +assertEq(f32[3644 >> 2], -3.9375) +assertEq(f32[3648 >> 2], -4.125) +assertEq(f32[3652 >> 2], -4.375) +assertEq(f32[3656 >> 2], -4.625) +assertEq(f32[3660 >> 2], -4.875) +assertEq(f32[3664 >> 2], -5.125) +assertEq(f32[3668 >> 2], -5.375) +assertEq(f32[3672 >> 2], -5.625) +assertEq(f32[3676 >> 2], -5.875) +assertEq(f32[3680 >> 2], -6.125) +assertEq(f32[3684 >> 2], -6.375) +assertEq(f32[3688 >> 2], -6.625) +assertEq(f32[3692 >> 2], -6.875) +assertEq(f32[3696 >> 2], -7.125) +assertEq(f32[3700 >> 2], -7.375) +assertEq(f32[3704 >> 2], -7.625) +assertEq(f32[3708 >> 2], -7.875) +assertEq(f32[3712 >> 2], -8.25) +assertEq(f32[3716 >> 2], -8.75) +assertEq(f32[3720 >> 2], -9.25) +assertEq(f32[3724 >> 2], -9.75) +assertEq(f32[3728 >> 2], -10.25) +assertEq(f32[3732 >> 2], -10.75) +assertEq(f32[3736 >> 2], -11.25) +assertEq(f32[3740 >> 2], -11.75) +assertEq(f32[3744 >> 2], -12.25) +assertEq(f32[3748 >> 2], -12.75) +assertEq(f32[3752 >> 2], -13.25) +assertEq(f32[3756 >> 2], -13.75) +assertEq(f32[3760 >> 2], -14.25) +assertEq(f32[3764 >> 2], -14.75) +assertEq(f32[3768 >> 2], -15.25) +assertEq(f32[3772 >> 2], -15.75) +assertEq(f32[3776 >> 2], -16.5) +assertEq(f32[3780 >> 2], -17.5) +assertEq(f32[3784 >> 2], -18.5) +assertEq(f32[3788 >> 2], -19.5) +assertEq(f32[3792 >> 2], -20.5) +assertEq(f32[3796 >> 2], -21.5) +assertEq(f32[3800 >> 2], -22.5) +assertEq(f32[3804 >> 2], -23.5) +assertEq(f32[3808 >> 2], -24.5) +assertEq(f32[3812 >> 2], -25.5) +assertEq(f32[3816 >> 2], -26.5) +assertEq(f32[3820 >> 2], -27.5) +assertEq(f32[3824 >> 2], -28.5) +assertEq(f32[3828 >> 2], -29.5) +assertEq(f32[3832 >> 2], -30.5) +assertEq(f32[3836 >> 2], -31.5) +assertEq(f32[3840 >> 2], -0.12890625) +assertEq(f32[3844 >> 2], -0.13671875) +assertEq(f32[3848 >> 2], -0.14453125) +assertEq(f32[3852 >> 2], -0.15234375) +assertEq(f32[3856 >> 2], -0.16015625) +assertEq(f32[3860 >> 2], -0.16796875) +assertEq(f32[3864 >> 2], -0.17578125) +assertEq(f32[3868 >> 2], -0.18359375) +assertEq(f32[3872 >> 2], -0.19140625) +assertEq(f32[3876 >> 2], -0.19921875) +assertEq(f32[3880 >> 2], -0.20703125) +assertEq(f32[3884 >> 2], -0.21484375) +assertEq(f32[3888 >> 2], -0.22265625) +assertEq(f32[3892 >> 2], -0.23046875) +assertEq(f32[3896 >> 2], -0.23828125) +assertEq(f32[3900 >> 2], -0.24609375) +assertEq(f32[3904 >> 2], -0.2578125) +assertEq(f32[3908 >> 2], -0.2734375) +assertEq(f32[3912 >> 2], -0.2890625) +assertEq(f32[3916 >> 2], -0.3046875) +assertEq(f32[3920 >> 2], -0.3203125) +assertEq(f32[3924 >> 2], -0.3359375) +assertEq(f32[3928 >> 2], -0.3515625) +assertEq(f32[3932 >> 2], -0.3671875) +assertEq(f32[3936 >> 2], -0.3828125) +assertEq(f32[3940 >> 2], -0.3984375) +assertEq(f32[3944 >> 2], -0.4140625) +assertEq(f32[3948 >> 2], -0.4296875) +assertEq(f32[3952 >> 2], -0.4453125) +assertEq(f32[3956 >> 2], -0.4609375) +assertEq(f32[3960 >> 2], -0.4765625) +assertEq(f32[3964 >> 2], -0.4921875) +assertEq(f32[3968 >> 2], -0.515625) +assertEq(f32[3972 >> 2], -0.546875) +assertEq(f32[3976 >> 2], -0.578125) +assertEq(f32[3980 >> 2], -0.609375) +assertEq(f32[3984 >> 2], -0.640625) +assertEq(f32[3988 >> 2], -0.671875) +assertEq(f32[3992 >> 2], -0.703125) +assertEq(f32[3996 >> 2], -0.734375) +assertEq(f32[4000 >> 2], -0.765625) +assertEq(f32[4004 >> 2], -0.796875) +assertEq(f32[4008 >> 2], -0.828125) +assertEq(f32[4012 >> 2], -0.859375) +assertEq(f32[4016 >> 2], -0.890625) +assertEq(f32[4020 >> 2], -0.921875) +assertEq(f32[4024 >> 2], -0.953125) +assertEq(f32[4024 >> 2], -0.953125) +assertEq(f32[4028 >> 2], -0.984375) +assertEq(f32[4032 >> 2], -1.03125) +assertEq(f32[4036 >> 2], -1.09375) +assertEq(f32[4040 >> 2], -1.15625) +assertEq(f32[4044 >> 2], -1.21875) +assertEq(f32[4048 >> 2], -1.28125) +assertEq(f32[4052 >> 2], -1.34375) +assertEq(f32[4056 >> 2], -1.40625) +assertEq(f32[4060 >> 2], -1.46875) +assertEq(f32[4064 >> 2], -1.53125) +assertEq(f32[4068 >> 2], -1.59375) +assertEq(f32[4072 >> 2], -1.65625) +assertEq(f32[4076 >> 2], -1.71875) +assertEq(f32[4080 >> 2], -1.78125) +assertEq(f32[4084 >> 2], -1.84375) +assertEq(f32[4088 >> 2], -1.90625) +assertEq(f32[4092 >> 2], -1.96875) diff --git a/js/src/jit-test/tests/asm.js/testBug975182.js b/js/src/jit-test/tests/asm.js/testBug975182.js new file mode 100644 index 000000000..41c627148 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug975182.js @@ -0,0 +1,20 @@ +Function("\ + g = (function(t,foreign){\ + \"use asm\";\ + var ff = foreign.ff;\ + function f() {\ + +ff()\ + }\ + return f\ + })(this, {\ + ff: arguments.callee\ + }, new ArrayBuffer(4096))\ +")() +function m(f) { + for (var j = 0; j < 6000; ++j) { + f(); + if ((j % 1000) === 0) + gc(); + } +} +m(g); diff --git a/js/src/jit-test/tests/asm.js/testBug989166.js b/js/src/jit-test/tests/asm.js/testBug989166.js new file mode 100644 index 000000000..c96d19de4 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug989166.js @@ -0,0 +1,8 @@ +(function(stdlib) { + "use asm"; + var pow = stdlib.Math.pow + function f() { + return +pow(.0, .0) + } + return f +})(this, {}, ArrayBuffer)() diff --git a/js/src/jit-test/tests/asm.js/testBug999790.js b/js/src/jit-test/tests/asm.js/testBug999790.js new file mode 100644 index 000000000..85f92c22f --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug999790.js @@ -0,0 +1,65 @@ +function CanBeConstructed(f) { + var caught = false; + try { + new f; + } catch (e) { + caught = true; + } + return !caught; +} + +function IsConstructedFunction(f) { + return f.hasOwnProperty('length') + && f.hasOwnProperty('name') + && f.hasOwnProperty('prototype') + && f.prototype.hasOwnProperty('constructor') + && f.prototype.constructor === f; +} + +function IsntConstructedFunction(f) { + return !f.hasOwnProperty('length') + && !f.hasOwnProperty('name') + && !f.hasOwnProperty('prototype') +} + +var m = function() { + "use asm" + function g(){} + return g; +}; +assertEq(CanBeConstructed(m), true, "asm.js modules can't be constructed"); + +var objM = new m; +assertEq(IsConstructedFunction(objM), true); + +var g = m(); +assertEq(CanBeConstructed(g), true, "asm.js functions can't be constructed"); +// g is a ctor returning an primitive value, thus an empty object +assertEq(Object.getOwnPropertyNames(new g).length, 0); + +var n = function() { + "use asm" + function g(){return 42.0} + function h(){return 42} + return { + g: g, + h: h + }; +}; +assertEq(CanBeConstructed(n), true, "asm.js modules can't be constructed"); + +var objN = new n; +// objN is an object with attributes g and h +assertEq(IsntConstructedFunction(objN), true); +assertEq(objN.hasOwnProperty('g'), true); +assertEq(objN.hasOwnProperty('h'), true); + +assertEq(IsConstructedFunction(objN.g), true); +assertEq(IsConstructedFunction(objN.h), true); + +var h = n().h; +assertEq(CanBeConstructed(h), true, "asm.js functions can't be constructed"); +// h is a ctor returning an primitive value, thus an empty object +assertEq(Object.getOwnPropertyNames(new h).length, 0); + +assertEq(typeof(function() {"use asm"; return {}}.prototype) !== 'undefined', true); diff --git a/js/src/jit-test/tests/asm.js/testBullet.js b/js/src/jit-test/tests/asm.js/testBullet.js new file mode 100644 index 000000000..64a6377e7 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBullet.js @@ -0,0 +1,19 @@ +// Test a big fat asm.js module. First load/compile/cache bullet.js in a +// separate process and then load it again in this process, which should be a +// cache hit. + +setCachingEnabled(true); +if (!isAsmJSCompilationAvailable()) + quit(); + +// Note: if you get some failure in this test, it probably has to do with +// bullet.js and not the nestedShell() call, so try first commenting out +// nestedShell() (and the loadedFromCache assertion) to see if the error +// reproduces. +var code = "setIonCheckGraphCoherency(false); setCachingEnabled(true); load('" + libdir + "bullet.js'); runBullet()"; +nestedShell("--js-cache", "--no-js-cache-per-process", "--execute=" + code); +setIonCheckGraphCoherency(false); +load(libdir + 'bullet.js'); +var results = runBullet(); +assertEq(results.asmJSValidated, true); +assertEq(results.loadedFromCache, true); diff --git a/js/src/jit-test/tests/asm.js/testCaching.js b/js/src/jit-test/tests/asm.js/testCaching.js new file mode 100644 index 000000000..8029ce56b --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testCaching.js @@ -0,0 +1,102 @@ +load(libdir + "asm.js"); + +setCachingEnabled(true); +if (!isAsmJSCompilationAvailable() || !isCachingEnabled()) + quit(); + +var body1 = "'use asm'; function f() { return 42 } function ff() { return 43 } return f"; +var m = new Function(body1); +assertEq(isAsmJSModule(m), true); +assertEq(m()(), 42); +var m = new Function(body1); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +assertEq(m()(), 42); +var body2 = body1 + "f"; +var m = new Function(body2); +assertEq(isAsmJSModuleLoadedFromCache(m), false); +assertEq(m()(), 43); +var evalStr1 = "(function() { " + body1 + "})"; +var m = eval(evalStr1); +assertEq(isAsmJSModuleLoadedFromCache(m), false); +assertEq(m()(), 42); +var m = eval(evalStr1); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +assertEq(m()(), 42); +var evalStr2 = "(function() { " + body2 + "})"; +var m = eval(evalStr2); +assertEq(isAsmJSModuleLoadedFromCache(m), false); +assertEq(m()(), 43); +var m = eval(evalStr2); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +assertEq(m()(), 43); + +var evalStr3 = "(function(global) { 'use asm'; var sin=global.Math.sin; function g(d) { d=+d; return +sin(d) } return g })"; +var m = eval(evalStr3); +assertEq(isAsmJSModule(m), true); +assertEq(m(this)(.3), Math.sin(.3)); +var m = eval(evalStr3); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +assertEq(m(this)(.3), Math.sin(.3)); +var evalStr4 = "(function(gobal) { 'use asm'; var sin=global.Math.sin; function g(d) { d=+d; return +sin(d) } return g })"; +var m = eval(evalStr4); +assertEq(isAsmJSModule(m), false); +var m = eval(evalStr3); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +var evalStr5 = "(function(global,foreign) { 'use asm'; var sin=global.Math.sin; function g(d) { d=+d; return +sin(d) } return g })"; +var m = eval(evalStr5); +assertEq(isAsmJSModuleLoadedFromCache(m), false); + +var m = new Function(body1); +assertEq(isAsmJSModule(m), true); +var body3 = "'use asm'; var sin=global.Math.sin; function g(d) { d=+d; return +sin(d) } return g"; +var m = new Function('global', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), false); +assertEq(m(this)(.2), Math.sin(.2)); +var m = new Function('gobal', body3); +assertEq(isAsmJSModule(m), false); +var m = new Function('global', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +var m = new Function('global','foreign', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), false); +var m = new Function('global','foreign', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +var m = new Function('gobal','foreign', body3); +assertEq(isAsmJSModule(m), false); +var m = new Function('global','foreign', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +var m = new Function('global','foregn', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), false); +var m = new Function('global','foreign', 'buffer', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), false); +var m = new Function('global','foreign', 'buffer', 'foopy', body3); +assertEq(isAsmJSModule(m), false); +var m = new Function('global','foreign', 'buffer', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +var m = new Function('global','foreign', 'bffer', body3); +assertEq(isAsmJSModuleLoadedFromCache(m), false); +var m = new Function('global','foreign', 'foreign', body3); +assertEq(isAsmJSModule(m), false); + +var body = "f() { 'use asm'; function g() {} return g }"; +var evalStr6 = "(function " + body + ")"; +var evalStr7 = "(function* " + body + ")"; +var m = eval(evalStr6); +assertEq(isAsmJSModule(m), true); +var m = eval(evalStr6); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +var m = eval(evalStr7); +assertEq(isAsmJSModule(m), false); + +// Test caching using a separate process (which, with ASLR, should mean a +// separate address space) to compile/cache the code. Ideally, every asmCompile +// would do this, but that makes jit-tests run 100x slower. Do it here, for one +// of each feature. asm.js/testBullet.js should pound on everything. +assertEq(asmLink(asmCompileCached(USE_ASM + "function f(i) { i=i|0; return +((i+1)|0) } function g(d) { d=+d; return +(d + +f(42) + 1.5) } return g"))(.2), .2+43+1.5); +assertEq(asmLink(asmCompileCached(USE_ASM + "function f1() { return 1 } function f2() { return 2 } function f(i) { i=i|0; return T[i&1]()|0 } var T=[f1,f2]; return f"))(1), 2); +assertEq(asmLink(asmCompileCached("g", USE_ASM + "var s=g.Math.sin; function f(d) { d=+d; return +s(d) } return f"), this)(.3), Math.sin(.3)); +assertEq(asmLink(asmCompileCached("g","ffis", USE_ASM + "var ffi=ffis.ffi; function f(i) { i=i|0; return ffi(i|0)|0 } return f"), null, {ffi:function(i){return i+2}})(1), 3); +assertEq(asmLink(asmCompileCached("g","ffis", USE_ASM + "var x=ffis.x|0; function f() { return x|0 } return f"), null, {x:43})(), 43); +var i32 = new Int32Array(BUF_MIN/4); +i32[4] = 42; +assertEq(asmLink(asmCompileCached("g","ffis","buf", USE_ASM + "var i32=new g.Int32Array(buf); function f(i) { i=i|0; return i32[i>>2]|0 } return f"), this, null, i32.buffer)(4*4), 42); +assertEq(asmLink(asmCompileCached('glob', USE_ASM + 'var x=glob.Math.PI; function f() { return +x } return f'), this)(), Math.PI); diff --git a/js/src/jit-test/tests/asm.js/testCall.js b/js/src/jit-test/tests/asm.js/testCall.js new file mode 100644 index 000000000..5d15fe257 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testCall.js @@ -0,0 +1,75 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +assertAsmTypeFail(USE_ASM+"function f(){i=i|0} function g() { f(0) } return g"); +assertAsmTypeFail(USE_ASM+"function f(i){i=i|0} function g() { f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){} function g() { f()|0 } return g"); +assertAsmTypeFail(USE_ASM+"function f(){} function g() { +f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){} function g() { return f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { +f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { f()|f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { f()|0 } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { ~~f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { -f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(i,j,k,l){i=i|0;j=j|0;k=k|0;l=l|0} function g() { f(0,1,2) } return g"); +assertAsmTypeFail(USE_ASM+"function f(i,j,k,l){i=i|0;j=j|0;k=k|0;l=l|0} function g() { f(0,1,2,3,4) } return g"); +assertAsmTypeFail(USE_ASM+"function f(i){i=i|0} function g() { f(.1) } return g"); +assertAsmTypeFail(USE_ASM+"function f(i){i=+i} function g() { f(1) } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0.1; i=f()|0 } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0.1; i=+f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0.1} function g() { var i=0; i=f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0.1} function g() { var i=0; i=f()|0 } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0.1} function g() { var i=0; i=+f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){} function g() { (1, f()) } return g"); + +assertEq(asmLink(asmCompile(USE_ASM+"var x=0; function f() {x=42} function g() { return (f(),x)|0 } return g"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM+"function f() {return 42} function g() { return f()|0 } return g"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=i|0; return (i+2)|0 } function h(i) { i=i|0; return ((g(i)|0)+8)|0 } return h"))(50), 60); +assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=i|0; return (i+2)|0 } function h(i) { i=i|0; return ((g(i)|0)+i)|0 } return h"))(50), 102); +assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=+i; return +(i+.1) } function h(i) { i=+i; return +(+g(i)+.2) } return h"))(20), 20+.1+.2); +assertEq(asmLink(asmCompile(USE_ASM+"function g(i,j) { i=i|0;j=j|0; return (i-j)|0 } function h(j,i) { j=j|0;i=i|0; return ((g(i,j)|0)+8)|0 } return h"))(10,20), 18); +assertEq(asmLink(asmCompile(USE_ASM+"function g(i,j) { i=i|0;j=+j; return +(+~~i+j) } function h(i,j) { i=i|0;j=+j; return +(+g(i,j)+8.6) } return h"))(10, 1.5), 10+1.5+8.6); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0; return (n-o)|0 } return f"))(1,2,3,4,5,6,100), -94); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } return f"))(1,2,3,4,5,6,100,20), 80); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (((o+p)|0) + ((o+p)|0))|0 } return f"))(1,2,3,4,5,6,30,20), 100); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q,r) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p;q=+q;r=+r; return +(q-r) } return f"))(1,2,3,4,5,6,7,8,40.2,1.4), 40.2-1.4); + +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0; return (n-o)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,i,j)|0 } return g"))(20,5), 15); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,i,j)|0 } return g"))(20,5), 15); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,i,j) } return g"))(.5, .1), .5-.1); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; var k=0; k=(i+j)|0; return ((f(0,0,0,0,0,0,i,j)|0)+k)|0 } return g"))(20,10), 40); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; var k=0.1; k=i+j; return +(+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j)+k) } return g"))(.5, .1), (.5+.1)+(.5-.1)); + +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q) { i=i|0;j=j|0;k=k|0;l=l|0;m=+m;n=n|0;o=o|0;p=+p;q=q|0; return +((m-p) + +~~q) } function g(i,j,k) { i=+i;j=+j;k=k|0; return +f(0,0,0,0,j,0,0,i,k) } return g"))(.5, 20.1, 4), (20.1-.5)+4); + +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,f(0,0,0,0,0,0,i,j)|0,j)|0 } return g"))(20,5), 10); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,f(0,0,0,0,0,0,i,j)|0,f(0,0,0,0,0,0,j,i)|0)|0 } return g"))(20,5), 30); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j),j) } return g"))(10.3, .2), 10.3-.2-.2); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j),+f(0.0,0.0,0.0,0.0,0.0,0.0,j,i)) } return g"))(10.3, .2), (10.3-.2)-(.2-10.3)); +assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0;q=q|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,i,f(0,0,0,0,0,0,i,j,0)|0,0)|0 } return g"))(20,5), 5); + +assertEq(asmLink(asmCompile(USE_ASM+"function f(i) {i=i|0; return i|0} function g() { return 42; return f(13)|0 } return g"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM+"function e() { return 42 } function f(i) { i=i|0; switch(i|0) { case 0: return e()|0; default: return 13 } return 0 } function g() { return f(0)|0 } return g"))(), 42); + +var rec = asmLink(asmCompile(USE_ASM+"function rec() { rec() } return rec")); +assertThrowsInstanceOf(rec, InternalError); + +var rec = asmLink(asmCompile(USE_ASM+"function rec(i) { i=i|0; if (!i) return 0; return ((rec((i-1)|0)|0)+1)|0 } return rec")); +assertEq(rec(100), 100); +assertEq(rec(1000), 1000); +assertThrowsInstanceOf(function() rec(100000000000), InternalError); +assertEq(rec(2000), 2000); + +assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0; i=f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { var i=0.0; i=f() } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { return (f()+1)|0 } return g"); +assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { return +(f()+1.0) } return g"); + +assertEq(asmLink(asmCompile(USE_ASM + "const M = 42; function f() { return M } function g() { return f()|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "const M = -42; function f() { return M } function g() { return f()|0 } return f"))(), -42); +assertAsmTypeFail(USE_ASM + "const M = 42; function f() { return M } function g() { return +f() } return f"); +assertEq(asmLink(asmCompile(USE_ASM + "const M = 42.1; function f() { return M } function g() { return +f() } return f"))(), 42.1); +assertAsmTypeFail(USE_ASM + "const M = 42.1; function f() { return M } function g() { return f()|0 } return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + "var tof = glob.Math.fround; const M = tof(42); function f() { return M } function g() { return tof(f()) } return f"), this)(), 42); +assertAsmTypeFail('glob', USE_ASM + "var tof = glob.Math.fround; const M = tof(42); function f() { return M } function g() { return +f() } return f"); diff --git a/js/src/jit-test/tests/asm.js/testCloning.js b/js/src/jit-test/tests/asm.js/testCloning.js new file mode 100644 index 000000000..e84f34303 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testCloning.js @@ -0,0 +1,50 @@ +load(libdir + "asm.js"); + +setCachingEnabled(true); + +var code = asmCompile(USE_ASM + "function g() { return 42 } return g"); +assertEq(asmLink(code)(), 42); +assertEq(asmLink(code)(), 42); + +var code = evaluate("(function() { " + USE_ASM + " function g() { return 43 } return g})", {fileName: null}); +assertEq(asmLink(code)(), 43); +assertEq(asmLink(code)(), 43); + +var code = asmCompile('glob', 'ffis', 'buf', USE_ASM + 'var i32=new glob.Int32Array(buf); function g() { return i32[0]|0 } return g'); +var i32_1 = new Int32Array(BUF_MIN/4); +i32_1[0] = 42; +var i32_2 = new Int32Array(BUF_MIN/4); +i32_2[0] = 13; +assertEq(asmLink(code, this, null, i32_1.buffer)(), 42); +assertEq(asmLink(code, this, null, i32_2.buffer)(), 13); +var i32_3 = new Int32Array(4097); +assertAsmLinkFail(code, this, null, i32_3.buffer); + +var code = asmCompile('glob', 'ffis', USE_ASM + 'var ffi=ffis.ffi; function g(n) { n=n|0; var i=0; for(; (i|0)<(n|0); i=(i+1)|0) ffi() } return g'); +var calls1 = 0, calls2 = 0; +function ffi1() { calls1++ } +function ffi2() { calls2++ } +asmLink(code, null, {ffi:ffi1})(100000); +assertEq(calls1, 100000); +assertEq(calls2, 0); +calls1 = 0; +asmLink(code, null, {ffi:ffi2})(50000); +assertEq(calls1, 0); +assertEq(calls2, 50000); + +var code = asmCompile(USE_ASM + 'var g = 0; function h() { g=(g+1)|0; return g|0 } return h'); +var h1 = code(); +assertEq(h1(), 1); +assertEq(h1(), 2); +var h2 = code(); +assertEq(h2(), 1); +assertEq(h1(), 3); +assertEq(h2(), 2); +assertEq(h1(), 4); + +var code = asmCompile(USE_ASM + "return {}"); +var h1 = code(); +var h2 = code(); +assertEq(h1 === h2, false); +assertEq(Object.keys(h1).length, 0); +assertEq(Object.keys(h2).length, 0); diff --git a/js/src/jit-test/tests/asm.js/testCompoundPlusMinus.js b/js/src/jit-test/tests/asm.js/testCompoundPlusMinus.js new file mode 100644 index 000000000..9b070541e --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testCompoundPlusMinus.js @@ -0,0 +1,14 @@ +load(libdir + "asm.js"); + +assertAsmTypeFail(USE_ASM + "function f(i,j,k) { i=i|0;j=+j;k=+k; return (i+(j+k))|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=+k; return +((i+j)+k) } return f"); +assertAsmTypeFail('imp', USE_ASM + "var ffi=imp.ffi; function f(i) { i=i|0; return (i+ffi())|0 } return f"); + +assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return (i+j+k)|0 } return f"))(1,2,3), 6); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return (i+j-k)|0 } return f"))(1,2,3), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return (i-j+k)|0 } return f"))(1,2,3), 2); + +const INT32_MAX = Math.pow(2,31)-1; +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i+i+i+i+i+i+i+i+i+i)|0 } return f"))(INT32_MAX), (10*INT32_MAX)|0); +const INT32_MIN = -Math.pow(2,31); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i+i+i+i+i+i+i+i+i+i)|0 } return f"))(INT32_MIN), (10*INT32_MIN)|0); diff --git a/js/src/jit-test/tests/asm.js/testControlFlow.js b/js/src/jit-test/tests/asm.js/testControlFlow.js new file mode 100644 index 000000000..40711cd6c --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testControlFlow.js @@ -0,0 +1,374 @@ +load(libdir + "asm.js"); + +assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=+j; if (i) return j; return j+1.0 } return f"))(0, 1.2), 1.2+1.0); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=+j; if (i) return j; return +~~i } return f"))(1,1.4), 1.4); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; if (i) return j^0; return i^1 } return f"))(1, 1), 1); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; if (i) return j^0; return i|0 } return f"))(1,8), 8); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if ((i|0) == 0) return 10; else if ((i|0) == 1) return 12; else if ((i|0) == 2) return 14; return 0} return f"))(2), 14); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if ((i|0) == 0) return 10; else if ((i|0) == 1) return 12; else if ((i|0) == 2) return 14; else return 16; return 0} return f"))(3), 16); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if ((i|0) == 0) i = 10; else if ((i|0) == 1) return 12; return (i|0) } return f"))(0), 10); + +assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; } return f"); +assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; else return 1 } return f"); +assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; return 1.0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { if (0) return 0; 1 } return f"); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { while (0) {} return 0} return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { for (;0;) {} return 0} return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { do {} while(0); return 0} return f"))(), 0); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { while (0) ; return 0} return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { for (;0;) ; return 0} return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { do ; while(0); return 0} return f"))(), 0); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { do {} while (0); while (0); return 0} return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i = 0; do {} while (0); return i|0} return f"))(), 0); + +assertAsmTypeFail(USE_ASM + "function f(d) {d=+d; while (d) {}; return 0} return f"); +assertAsmTypeFail(USE_ASM + "function f(d) {d=+d; for (;d;) {}; return 0} return f"); +assertAsmTypeFail(USE_ASM + "function f(d) {d=+d; do {} while (d); return 0} return f"); + +assertEq(asmLink(asmCompile(USE_ASM + "function f(j) {j=j|0; var i=0; while ((i|0) < (j|0)) i=(i+4)|0; return i|0} return f"))(6), 8); +assertEq(asmLink(asmCompile(USE_ASM + "function f(j) {j=j|0; var i=0; for (;(i|0) < (j|0);) i=(i+4)|0; return i|0} return f"))(6), 8); +assertEq(asmLink(asmCompile(USE_ASM + "function f(j) {j=j|0; var i=0; do { i=(i+4)|0; } while ((i|0) < (j|0)); return i|0} return f"))(6), 8); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { while(1) return 42; return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { for(;1;) return 42; return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { do return 42; while(1); return 0 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1) { if (i) return 13; return 42 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;1;) { if (i) return 13; return 42 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if (i) return 13; return 42 } while(1); return 0 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1) { break; while(1) {} } return 42 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;;) { break; for(;;) {} } return 42 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { break; do {} while(1) {} } while(1); return 42 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; while(1) { if (i) return 42; return 13 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; for(;1;) { if (i) return 42; return 13 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; do { if (i) return 42; return 13 } while(1); return 0 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1) { if (i) return 13; else return 42; return 13 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;;) { if (i) return 13; else return 42; return 13 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if (i) return 13; else return 42; return 13 } while(1); return 0 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while((i|0) < 3) { if (i) return 42; i=(i+1)|0 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;(i|0) < 3;) { if (i) return 42; i=(i+1)|0 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if (i) return 42; i=(i+1)|0 } while((i|0) < 3); return 0 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while((i|0) < 3) { if (!i) i=(i+1)|0; return 42 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;(i|0) < 3;) { if (!i) i=(i+1)|0; return 42 } return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if (!i) i=(i+1)|0; return 42 } while((i|0) < 3); return 0 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42; return i|0; while(1) {} return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42; return i|0; for(;1;) {} return 0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42; return i|0; do {} while(1); return 0 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while((i|0) < 10) if ((i|0) == 4) break; else i=(i+1)|0; return i|0 } return f"))(), 4); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(; (i|0) < 10;) if ((i|0) == 4) break; else i=(i+1)|0; return i|0 } return f"))(), 4); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do if ((i|0) == 4) break; else i=(i+1)|0; while((i|0) < 10); return i|0 } return f"))(), 4); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; while ((i=(i+1)|0)<2) { sum=(sum+1)|0; if ((i&1)==0) continue; sum=(sum+100)|0 } return sum|0 } return f"))(), 101); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; for (;(i=(i+1)|0)<2;) { sum=(sum+1)|0; if ((i&1)==0) continue; sum=(sum+100)|0 } return sum|0 } return f"))(), 101); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; do { sum=(sum+1)|0; if ((i&1)==0) continue; sum=(sum+100)|0 } while((i=(i+1)|0)<2); return sum|0 } return f"))(), 102); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; x:a:y:while(1) { i=1; while(1) { i=2; break a; } i=3; } return i|0 } return f"))(), 2); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; x:a:y:for(;;) { i=1; while(1) { i=2; break a; } i=3; } return i|0 } return f"))(), 2); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; x:a:y:do { i=1; while(1) { i=2; break a; } i=3; } while(1); return i|0 } return f"))(), 2); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; a:b:while((i|0) < 5) { i=(i+1)|0; while(1) continue b; } return i|0 } return f"))(), 5); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; a:b:for(;(i|0) < 5;) { i=(i+1)|0; while(1) continue b; } return i|0 } return f"))(), 5); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; a:b:do { i=(i+1)|0; while(1) continue b; } while((i|0) < 5); return i|0 } return f"))(), 5); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; return 0; a:b:while((i|0) < 5) { i=(i+1)|0; while(1) continue b; } return i|0 } return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; return 0; a:b:for(;(i|0) < 5;) { i=(i+1)|0; while(1) continue b; } return i|0 } return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; return 0; a:b:do { i=(i+1)|0; while(1) continue b; } while((i|0) < 5); return i|0 } return f"))(), 0); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42; a:{ break a; i=2; } b:{ c:{ break b; i=3 } i=4 } return i|0 } return f"))(), 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; a:b:for(;(i|0) < 5;i=(i+1)|0) { while(1) continue b; } return i|0 } return f"))(), 5); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,sum=0; for(i=1;(i|0)<4;i=(i+1)|0) sum=(sum+i)|0; return sum|0 } return f"))(), 6); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,sum=0; for(i=1;(i|0)<8;i=(i+1)|0) { if ((i&1) == 0) continue; sum=(sum+i)|0; } return sum|0 } return f"))(), 16); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1) { i=(i+1)|0; if ((i|0) > 10) break; } return i|0 } return f"))(), 11); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;1;i=(i+1)|0) { if ((i|0) > 10) break; } return i|0 } return f"))(), 11); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if ((i|0) > 10) break; i=(i+1)|0 } while(1); return i|0 } return f"))(), 11); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1){ if ((i|0)>0) break; while (1) { i=i+1|0; if ((i|0)==1) break; } } return i|0; } return f"))(), 1); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;;){ if ((i|0)>0) break; while (1) { i=i+1|0; if ((i|0)==1) break; } } return i|0; } return f"))(), 1); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do{ if ((i|0)>0) break; while (1) { i=i+1|0; if ((i|0)==1) break; } }while(1); return i|0; } return f"))(), 1); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; while(1){ if ((i|0)>5) break; while (1) { i=i+1|0; sum=(sum+i)|0; if ((i|0)>3) break; } } return sum|0; } return f"))(), 21); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; for(;;){ if ((i|0)>5) break; while (1) { i=i+1|0; sum=(sum+i)|0; if ((i|0)>3) break; } } return sum|0; } return f"))(), 21); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; do{ if ((i|0)>5) break; while (1) { i=i+1|0; sum=(sum+i)|0; if ((i|0)>3) break; } }while(1); return sum|0; } return f"))(), 21); + +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; while(1) { if (i) { break; } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;1;) { if (i) { break; } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; do { if (i) { break; } else { return i|0 } i = 1 } while (0); return i|0 } return f"))(3), 3); + +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; while(1) { if (i) { return i|0 } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;;) { if (i) { return i|0 } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; do { if (i) { return i|0 } else { return i|0 } i = 1 } while (0); return i|0 } return f"))(3), 3); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; while(j){ if(0) continue; j=i } return j|0 } return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; for(;j;){ if(0) continue; j=i } return j|0 } return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; do{ if(0) continue; j=i } while(j) return j|0 } return f"))(), 0); + +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;;) { return i|0 } return 0 } return f"))(42), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f(n) { n=n|0; var i=0,s=0; for(;;i=(i+1)|0) { if (~~i==~~n) return s|0; s=(s+i)|0 } return 0 } return f"))(8), 28); + +var f = asmLink(asmCompile(USE_ASM + "function f(n,m) { n=n|0;m=m|0; var i=0,sum=0; while((n|0)>(m|0) ? ((i|0)<(n|0))|0 : ((i|0)<(m|0))|0) { sum = (sum+i)|0; i=(i+1)|0 } return sum|0 } return f")); +assertEq(f(1,5), 10); +assertEq(f(6,5), 15); + +var f = asmLink(asmCompile(USE_ASM + "function f(n,m) { n=n|0;m=m|0; var i=0,sum=0; for(; (n|0)>(m|0) ? ((i|0)<(n|0))|0 : ((i|0)<(m|0))|0; i=(i+1)|0) { sum = (sum+i)|0 } return sum|0 } return f")); +assertEq(f(1,5), 10); +assertEq(f(6,5), 15); + +var f = asmLink(asmCompile(USE_ASM + "function f(n,m) { n=n|0;m=m|0; var i=0,sum=0; do { sum = (sum+i)|0; i=(i+1)|0 } while((n|0)>(m|0) ? ((i|0)<(n|0))|0 : ((i|0)<(m|0))|0); return sum|0 } return f")); +assertEq(f(1,5), 10); +assertEq(f(6,5), 15); + +assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: return 0; case 1: return 0 } return 0} return f"); +assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: return 0; case 2: return 0; case 1: return 0 } return 0} return f"); +assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; switch(1) { case 1: return 0; case 1: return 0 } return 0} return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0; switch(i) {}; return i|0 } return f"); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) {}; return i|0 } return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { default: i=42 } return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { default: i=42; break } return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { case 0: i=42 } return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { case 0: i=42; break } return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { case 0: default: i=42 } return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { case 0: default: i=42; break } return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; switch(i|0) { case 0: case 2: break; default: i=42 } return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; switch(i|0) { case 0: case 2: break; default: i=42; break } return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 42; switch(1) { case 1: return 13 } return 14 } return f"))(), 42); + +var exp = asmLink(asmCompile(USE_ASM + "var x=0; function a() { return x|0 } function b(i) { i=i|0; x=i } function c(i) { i=i|0; if (i) b(i); } return {a:a,b:b,c:c}")); +assertEq(exp.c(10), undefined); +assertEq(exp.a(), 10); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: i=-1; break; case 133742: i=2; break; default: i=42; break } return i|0 } return f")); +assertEq(f(1), -1); +assertEq(f(2), 42); +assertEq(f(133742), 2); +assertEq(f(133743), 42); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: i=42; break; default: i=13 } return i|0 } return f")); +assertEq(f(-1), 13); +assertEq(f(0), 13); +assertEq(f(1), 42); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case -1: i=42; break; default: i=13 } return i|0 } return f")); +assertEq(f(-1), 42); +assertEq(f(0), 13); +assertEq(f(1), 13); +assertEq(f(0xffffffff), 42); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var sum=0; switch(i|0) { case -1: sum=(sum+1)|0; case 1: sum=(sum+1)|0; case 3: sum=(sum+1)|0; default: sum=(sum+100)|0; } return sum|0 } return f")); +assertEq(f(-1), 103); +assertEq(f(0), 100); +assertEq(f(1), 102); +assertEq(f(2), 100); +assertEq(f(3), 101); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var sum=0; switch(i|0) { case -1: sum=10; break; case 1: sum=11; break; case 3: sum=12; break; default: sum=13; } return sum|0 } return f")); +assertEq(f(-1), 10); +assertEq(f(0), 13); +assertEq(f(1), 11); +assertEq(f(2), 13); +assertEq(f(3), 12); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=8,sum=0; a:for(; (i|0)<20; i=(i+1)|0) { switch(i&3) { case 0:case 1:sum=(sum+i)|0;break;case 2:sum=(sum+100)|0;continue;default:break a} sum=(sum+10)|0; } sum=(sum+1000)|0; return sum|0 } return f"))(), 1137); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { a: do{break a;}while(0); a: do{break a;}while(0); return 42 } return f"))(), 42); +assertEq(asmLink(asmCompile('g', USE_ASM + "function f() { g:{ return 42 } return 13 } return f"), null)(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f(x) {x=x|0;switch (x|0) {case 31:return 13;case 9: {x = 3;if ((x|0) <= 0) {return -1;}}}return 1;} return f"))(31), 13); + +var imp = { ffi:function() { throw "Wrong" } }; +assertEq(asmLink(asmCompile('glob','imp', USE_ASM + "var ffi=imp.ffi; function f() { var i=0; return (i+1)|0; return ffi(i|0)|0 } return f"), null, imp)(), 1); + +assertEq(asmLink(asmCompile(USE_ASM + 'function f() {var k = 1;if (1) {for(k = 1; k|0; k=k-1|0) {}} return 1}; return f'))(), 1); + +// Ternaries conditionals +// +// Basic ternaries +var f = asmLink(asmCompile(USE_ASM + "function f() { return 0; if (1) return -1; return -2} return f")); +assertEq(f(5), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(x) { x=x|0; var a=2;if(x?1:0)a=1;else a=0; return a|0 } return f")); +assertEq(f(1), 1); +assertEq(f(0), 0); + +var guard = (function() { + var called_ = false; + return { + called: function(){ return called_ }, + call: function(){ called_ = true } + } +})(); + +var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + "var func=ffi.func; function f(x) { x=x|0; var a=2;if(x?1:1)a=1; else {func();a=0}return a|0 } return f"), this, {func: guard.call}); +assertEq(f(1), 1); +assertEq(f(0), 1); +assertEq(guard.called(), false); + +var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + "var func=ffi.func; function f(x) { x=x|0; var a=2;if(x?0:0){a=1; func()}else a=0;return a|0 } return f"), this, {func: guard.call}); +assertEq(f(1), 0); +assertEq(f(0), 0); +assertEq(guard.called(), false); + +var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + "var func=ffi.func; function f(x,y) { x=x|0;y=y|0; var a=2;if(x?func()|0:y)a=1;else a=0; return a|0 } return f"), this, {func: guard.call}); +assertEq(f(0,1), 1); +assertEq(guard.called(), false); + +var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + "var func=ffi.func; function f(x,y) { x=x|0;y=y|0; var a=2;if(x?y:func()|0)a=1;else a=0; return a|0 } return f"), this, {func: guard.call}); +assertEq(f(1,0), 0); +assertEq(guard.called(), false); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var a=2;if(x?0:y)a=1;else a=0; return a|0 } return f")); +assertEq(f(1,1), 0); +assertEq(f(1,0), 0); +assertEq(f(0,0), 0); +assertEq(f(0,1), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var a=2;if(x?y:1)a=1;else a=0; return a|0 } return f")); +assertEq(f(1,1), 1); +assertEq(f(1,0), 0); +assertEq(f(0,0), 1); +assertEq(f(0,1), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2;if(x?y:z)a=1;else a=0; return a|0 } return f")); +for (var i = 0; i < 2; ++i) + for (var j = 0; j < 2; ++j) + for (var k = 0; k < 2; ++k) + assertEq(f(i,j,k), ((i && j) || (!i && k))|0); + +// Complex ternaries +function CheckTwoArgsTwoOptions(f) { + function check(x,y) { + return (x > 2 && y < 5) | 0; + } + for (var a = -10; a < 10; a++) + for (var b = -10; b < 10; b++) + assertEq(f(a,b), check(a,b)); +} + +function CheckThreeArgsTwoOptions(f) { + function check(x,y,z) { + return (x > 2 && y < 5 && z > -1) | 0; + } + for (var a = -10; a < 10; a++) + for (var b = -10; b < 10; b++) + for (var c = -10; c < 10; c++) + assertEq(f(a,b,c), check(a,b,c)); +} + +// Ternaries with && semantics +var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var z=0; if((x|0) > 2 ? (y|0) < 5 : 0) z=1; return z|0;} return f")); +CheckTwoArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var z=2; if((x|0) > 2 ? (y|0) < 5 : 0) z=1; else z=0; return z|0;} return f")); +CheckTwoArgsTwoOptions(f); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=0; if((x|0) > 2 ? ((y|0) < 5 ? (z|0) > -1 : 0) : 0) a=1; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) > 2 ? ((y|0) < 5 ? (z|0) > -1 : 0) : 0) a=1; else a=0; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=0; if((x|0) > 2 ? (y|0) < 5 : 0) {if ((z|0) > -1) a=1}; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) > 2 ? (y|0) < 5 : 0) {if ((z|0) > -1) a=1; else a=0;} else a=0; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=0; if(((x|0) == 3 ? 1 : ((x|0) > 3)) ? ((y|0) < 5 ? (z|0) > -1 : 0) : 0) a=1; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if(((x|0) == 3 ? 1 : ((x|0) > 3)) ? ((y|0) < 5 ? (z|0) > -1 : 0) : 0) a=1; else a=0; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=0; if((x|0) == 3 ? 1 : (x|0) > 3) {if ((y|0) < 5 ? (z|0) > -1 : 0) a=1;} return a|0;} return f")); +CheckThreeArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) == 3 ? 1 : (x|0) > 3) {if ((y|0) < 5 ? (z|0) > -1 : 0) a=1; else a=0;} else a=0; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); + +// Ternaries with || semantics +var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var z=1; if((x|0) <= 2 ? 1 : (y|0) >= 5) z=0; return z|0;} return f")); +CheckTwoArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var z=2; if((x|0) <= 2 ? 1 : (y|0) >= 5) z=0; else z=1; return z|0;} return f")); +CheckTwoArgsTwoOptions(f); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=1; if((x|0) <= 2 ? 1 : ((y|0) >= 5 ? 1 : (z|0) <= -1)) a=0; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) <= 2 ? 1 : ((y|0) >= 5 ? 1 : (z|0) <= -1)) a=0; else a=1; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=1; if((x|0) <= 2 ? 1 : (y|0) >= 5) a=0; else if ((z|0) <= -1) a=0; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) <= 2 ? 1 : (y|0) >= 5) a=0; else if ((z|0) <= -1) a=0; else a=1; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); + +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=1; if(((x|0) != 3 ? ((x|0) <= 3) : 0) ? 1 : ((y|0) >= 5 ? 1 : (z|0) <= -1)) a=0; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); +var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if(((x|0) != 3 ? ((x|0) <= 3) : 0) ? 1 : ((y|0) >= 5 ? 1 : (z|0) <= -1)) a=0; else a=1; return a|0;} return f")); +CheckThreeArgsTwoOptions(f); + +// Massive test +var code = '"use asm";\ + function g(x,y) {\ + x=x|0;\ + y=y|0;\ + var z = 0;\ + if ((y|0) == 1337) {\ + z = 1;\ + } else if ((x|0) == 1 ? 1 : ((x|0) < 0 ? (y|0) == 1 : 0)) {\ + z = 2;\ + } else if ((x|0) == 2) {\ + z = 3;\ + } else if ((x|0) == 3 ? 1 : (x|0) == 4) {\ + z = 4;\ + } else if ((x|0) == 5 ? (y|0) > 5 : 0) {\ + z = 5;\ + } else {\ + z = 6;\ + }\ + return z|0;\ + }\ + return g;'; + +var m = asmLink(asmCompile(code)); + +assertEq(m(0, 1337), 1); +assertEq(m(0, 1338), 6); +assertEq(m(0, 0), 6); +assertEq(m(0, 1), 6); +assertEq(m(0, 1336), 6); +assertEq(m(1, 1337), 1); +assertEq(m(2, 1337), 1); +assertEq(m(3, 1337), 1); +assertEq(m(4, 1337), 1); +assertEq(m(5, 1337), 1); + +assertEq(m(1, 10), 2); +assertEq(m(1, 1336), 2); +assertEq(m(-1, 10), 6); +assertEq(m(-1, 2), 6); +assertEq(m(-1, -1), 6); +assertEq(m(-1, 1), 2); +assertEq(m(-9, 1), 2); + +assertEq(m(2, 1), 3); +assertEq(m(2, 0), 3); +assertEq(m(2, 6), 3); + +assertEq(m(3, 1), 4); +assertEq(m(3, 0), 4); +assertEq(m(3, 6), 4); +assertEq(m(3, 3), 4); +assertEq(m(4, 1), 4); +assertEq(m(4, 0), 4); +assertEq(m(4, 6), 4); +assertEq(m(4, 3), 4); + +assertEq(m(5, -1), 6); +assertEq(m(5, 4), 6); +assertEq(m(5, 5), 6); +assertEq(m(5, 6), 5); +assertEq(m(5, 10), 5); diff --git a/js/src/jit-test/tests/asm.js/testDebugModeDisables.js b/js/src/jit-test/tests/asm.js/testDebugModeDisables.js new file mode 100644 index 000000000..56b1c4dde --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testDebugModeDisables.js @@ -0,0 +1,9 @@ +// |jit-test| + +load(libdir + "asm.js"); + +// Turn on debugging for the current global. +var g = newGlobal(); +var dbg = new g.Debugger(this); + +assertAsmTypeFail("'use asm'; function f() {} return f"); diff --git a/js/src/jit-test/tests/asm.js/testExpressions.js b/js/src/jit-test/tests/asm.js/testExpressions.js new file mode 100644 index 000000000..0e04ac0db --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testExpressions.js @@ -0,0 +1,403 @@ +load(libdir + "asm.js"); + +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i+j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i+j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i-j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i-j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i*j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i*j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i*j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0; return (i*1048576)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0; return (i*-1048576)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i + (j*4))|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var two30 = 1073741824; return (((two30 * 524288 * 16) + 1) & 1)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i/j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i/j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=1,j=1; return (i/j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i%j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i%j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i<j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i<j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i<j)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0.0; return (-i)|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (-(i+j))|0 } return f"); + +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i|0)/(k|0) } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i>>>0)/(k>>>0) } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i|0)%(k|0) } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i>>>0)%(k>>>0) } return f"); + +const UINT32_MAX = Math.pow(2,32)-1; +const INT32_MIN = -Math.pow(2,31); +const INT32_MAX = Math.pow(2,31)-1; + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i*2)|0 } return f")); +assertEq(f(0), 0); +assertEq(f(INT32_MIN), (2*INT32_MIN)|0); +assertEq(f(INT32_MAX), (2*INT32_MAX)|0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (2*i)|0 } return f")); +assertEq(f(0), 0); +assertEq(f(INT32_MIN), (2*INT32_MIN)|0); +assertEq(f(INT32_MAX), (2*INT32_MAX)|0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i*1048575)|0 } return f")); +assertEq(f(0), 0); +assertEq(f(2), (1048575*2)|0); +assertEq(f(-1), (1048575*-1)|0); +assertEq(f(INT32_MIN), (1048575*INT32_MIN)|0); +assertEq(f(INT32_MAX), (1048575*INT32_MAX)|0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (1048575*i)|0 } return f")); +assertEq(f(0), 0); +assertEq(f(2), (1048575*2)|0); +assertEq(f(-1), (1048575*-1)|0); +assertEq(f(INT32_MIN), (1048575*INT32_MIN)|0); +assertEq(f(INT32_MAX), (1048575*INT32_MAX)|0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0; j=~i; return j|0 } return f")); +assertEq(f(0), ~0); +assertEq(f(3), ~3); +assertEq(f(-3), ~-3); +assertEq(f(INT32_MAX), ~INT32_MAX); +assertEq(f(INT32_MIN), ~INT32_MIN); +assertEq(f(UINT32_MAX), ~UINT32_MAX); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=+i; var j=0; j=~~i; return j|0 } return f")); +assertEq(f(0), 0); +assertEq(f(3.5), 3); +assertEq(f(-3.5), -3); +assertEq(f(INT32_MAX), INT32_MAX); +assertEq(f(INT32_MIN), INT32_MIN); +assertEq(f(UINT32_MAX), -1); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0.0; j=+~~i; return +j } return f")); +assertEq(f(0), 0); +assertEq(f(INT32_MAX), INT32_MAX); +assertEq(f(INT32_MIN), INT32_MIN); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0.1; j=+(i>>>0); return +j } return f")); +assertEq(f(0), 0); +assertEq(f(INT32_MAX), INT32_MAX); +assertEq(f(UINT32_MAX), UINT32_MAX); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (-i)|0 } return f")); +assertEq(f(0), 0); +assertEq(f(-0), 0); +assertEq(f(1), -1); +assertEq(f(INT32_MAX), INT32_MIN+1); +assertEq(f(INT32_MIN), INT32_MIN); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=+i; return +(-i) } return f")); +assertEq(f(0), -0); +assertEq(f(-0), 0); +assertEq(f(-1), 1); +assertEq(f(1), -1); +assertEq(f(Math.pow(2,50)), -Math.pow(2,50)); +assertEq(f(1.54e20), -1.54e20); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0) < (j|0))|0 } return f")); +assertEq(f(0, 1), 1); +assertEq(f(1, 0), 0); +assertEq(f(1, 1), 0); +assertEq(f(INT32_MIN, INT32_MAX), 1); +assertEq(f(INT32_MAX, INT32_MIN), 0); +assertEq(f(0, INT32_MAX), 1); +assertEq(f(INT32_MAX, 0), 0); +assertEq(f(INT32_MIN, 0), 1); +assertEq(f(0, INT32_MIN), 0); +assertEq(f(UINT32_MAX, 0), 1); +assertEq(f(0, UINT32_MAX), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i>>>0) < (j>>>0))|0 } return f")); +assertEq(f(0, 1), 1); +assertEq(f(1, 0), 0); +assertEq(f(1, 1), 0); +assertEq(f(INT32_MIN, INT32_MAX), 0); +assertEq(f(INT32_MAX, INT32_MIN), 1); +assertEq(f(0, INT32_MAX), 1); +assertEq(f(INT32_MAX, 0), 0); +assertEq(f(INT32_MIN, 0), 0); +assertEq(f(0, INT32_MIN), 1); +assertEq(f(UINT32_MAX, 0), 0); +assertEq(f(0, UINT32_MAX), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)==(j|0); return k|0 } return f")); +assertEq(f(1,2), 0); +assertEq(f(1,1), 1); +assertEq(f(2,1), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)!=(j|0); return k|0 } return f")); +assertEq(f(1,2), 1); +assertEq(f(1,1), 0); +assertEq(f(2,1), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)<(j|0); return k|0 } return f")); +assertEq(f(1,2), 1); +assertEq(f(1,1), 0); +assertEq(f(1,0), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)>(j|0); return k|0 } return f")); +assertEq(f(1,2), 0); +assertEq(f(1,1), 0); +assertEq(f(1,0), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)<=(j|0); return k|0 } return f")); +assertEq(f(1,2), 1); +assertEq(f(1,1), 1); +assertEq(f(1,0), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)>=(j|0); return k|0 } return f")); +assertEq(f(1,2), 0); +assertEq(f(1,1), 1); +assertEq(f(1,0), 1); + +assertEq(asmLink(asmCompile(USE_ASM + "const I=2; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f"))(1), 1); +assertEq(asmLink(asmCompile(USE_ASM + "const I=2; function f(i) { i=i|0; var k=0; k=(i>>>0)<I; return k|0 } return f"))(1), 1); +assertEq(asmLink(asmCompile(USE_ASM + "const I=-2; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f"))(-1), 0); +assertAsmTypeFail(USE_ASM + "const I=-2; function f(i) { i=i|0; var k=0; k=(i>>>0)<I; return k|0 } return f"); +assertAsmTypeFail(USE_ASM + "const I=0x80000000; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f"); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0)/(j|0))|0 } return f")); +assertEq(f(4,2), 2); +assertEq(f(3,2), 1); +assertEq(f(3,-2), -1); +assertEq(f(-3,-2), 1); +assertEq(f(0, -1), 0); +assertEq(f(0, INT32_MAX), 0); +assertEq(f(0, INT32_MIN), 0); +assertEq(f(INT32_MAX, 0), 0); +assertEq(f(INT32_MIN, 0), 0); +assertEq(f(-1, INT32_MAX), 0); +assertEq(f(-1, INT32_MIN), 0); +assertEq(f(INT32_MAX, -1), -INT32_MAX); +assertEq(f(INT32_MIN, -1), INT32_MIN); // !! +assertEq(f(INT32_MAX, INT32_MAX), 1); +assertEq(f(INT32_MAX, INT32_MIN), 0); +assertEq(f(INT32_MIN, INT32_MAX), -1); +assertEq(f(INT32_MIN, INT32_MIN), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i>>>0)/(j>>>0))|0 } return f")); +assertEq(f(4,2), 2); +assertEq(f(3,2), 1); +assertEq(f(3,-2), 0); +assertEq(f(-3,-2), 0); +assertEq(f(0, -1), 0); +assertEq(f(0, INT32_MAX), 0); +assertEq(f(0, INT32_MIN), 0); +assertEq(f(0, UINT32_MAX), 0); +assertEq(f(INT32_MAX, 0), 0); +assertEq(f(INT32_MIN, 0), 0); +assertEq(f(UINT32_MAX, 0), 0); +assertEq(f(-1, INT32_MAX), 2); +assertEq(f(-1, INT32_MIN), 1); +assertEq(f(-1, UINT32_MAX), 1); +assertEq(f(INT32_MAX, -1), 0); +assertEq(f(INT32_MIN, -1), 0); +assertEq(f(UINT32_MAX, -1), 1); +assertEq(f(INT32_MAX, INT32_MAX), 1); +assertEq(f(INT32_MAX, INT32_MIN), 0); +assertEq(f(UINT32_MAX, INT32_MAX), 2); +assertEq(f(INT32_MAX, UINT32_MAX), 0); +assertEq(f(UINT32_MAX, UINT32_MAX), 1); +assertEq(f(INT32_MIN, INT32_MAX), 1); +assertEq(f(INT32_MIN, UINT32_MAX), 0); +assertEq(f(INT32_MIN, INT32_MIN), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i|0)%(j|0)|0; return k|0 } return f")); +assertEq(f(4,2), 0); +assertEq(f(3,2), 1); +assertEq(f(3,-2), 1); +assertEq(f(-3,-2), -1); +assertEq(f(0, -1), 0); +assertEq(f(0, INT32_MAX), 0); +assertEq(f(0, INT32_MIN), 0); +assertEq(f(INT32_MAX, 0), 0); +assertEq(f(INT32_MIN, 0), 0); +assertEq(f(-1, INT32_MAX), -1); +assertEq(f(-1, INT32_MIN), -1); +assertEq(f(INT32_MAX, -1), 0); +assertEq(f(INT32_MIN, -1), 0); // !! +assertEq(f(INT32_MAX, INT32_MAX), 0); +assertEq(f(INT32_MAX, INT32_MIN), INT32_MAX); +assertEq(f(INT32_MIN, INT32_MAX), -1); +assertEq(f(INT32_MIN, INT32_MIN), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i|0)%4|0; return k|0 } return f")); +assertEq(f(0), 0); +assertEq(f(-1), -1); +assertEq(f(-3), -3); +assertEq(f(-4), 0); +assertEq(f(INT32_MIN), 0); +assertEq(f(3), 3); +assertEq(f(4), 0); +assertEq(f(INT32_MAX), 3); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i>>>0)%(j>>>0)|0; return k|0 } return f")); +assertEq(f(4,2), 0); +assertEq(f(3,2), 1); +assertEq(f(3,-2), 3); +assertEq(f(-3,-2), -3); +assertEq(f(0, -1), 0); +assertEq(f(0, INT32_MAX), 0); +assertEq(f(0, INT32_MIN), 0); +assertEq(f(0, UINT32_MAX), 0); +assertEq(f(INT32_MAX, 0), 0); +assertEq(f(INT32_MIN, 0), 0); +assertEq(f(UINT32_MAX, 0), 0); +assertEq(f(-1, INT32_MAX), 1); +assertEq(f(-1, INT32_MIN), INT32_MAX); +assertEq(f(-1, UINT32_MAX), 0); +assertEq(f(INT32_MAX, -1), INT32_MAX); +assertEq(f(INT32_MIN, -1), INT32_MIN); +assertEq(f(UINT32_MAX, -1), 0); +assertEq(f(INT32_MAX, INT32_MAX), 0); +assertEq(f(INT32_MAX, INT32_MIN), INT32_MAX); +assertEq(f(UINT32_MAX, INT32_MAX), 1); +assertEq(f(INT32_MAX, UINT32_MAX), INT32_MAX); +assertEq(f(UINT32_MAX, UINT32_MAX), 0); +assertEq(f(INT32_MIN, INT32_MAX), 1); +assertEq(f(INT32_MIN, UINT32_MAX), INT32_MIN); +assertEq(f(INT32_MIN, INT32_MIN), 0); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 / 2)|0 } return f"))(), 2); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (3 / 2)|0 } return f"))(), 1); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 % 2)|0 } return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (3 % 2)|0 } return f"))(), 1); + +assertAsmTypeFail(USE_ASM + "function f() { var i=42,j=1.1; return +(i?i:j) } return f"); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 0; 1 ? 1 : 1; return 0; } return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1.1; return +(i?+(i|0):j) } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1; return (i?i:j)|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1; return 13; return (i?i:j)|0 } return f"))(), 13); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (0 > (-(~~1) >>> 0)) | 0; } return f"))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 0 < 4294967294 | 0; } return f"))(), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0)>(j|0)?(i+10)|0:(j+100)|0)|0 } return f")); +assertEq(f(2, 4), 104); +assertEq(f(-2, -4), 8); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return ((i|0)>(j|0) ? (i|0)>(k|0) ? i : k : (j|0)>(k|0) ? j : k)|0 } return f")); +assertEq(f(1,2,3), 3); +assertEq(f(1,3,2), 3); +assertEq(f(2,1,3), 3); +assertEq(f(2,3,1), 3); +assertEq(f(3,1,2), 3); +assertEq(f(3,2,1), 3); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var a=0,b=0; a=i>>>0 < 4294967292; b=(i|0) < -4; return (j ? a : b)|0 } return f")); +assertEq(f(1,true), 1); +assertEq(f(-1,true), 0); +assertEq(f(-5,true), 1); +assertEq(f(1,false), 0); +assertEq(f(-1,false), 0); +assertEq(f(-5,false), 1); + +assertAsmTypeFail('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return (i32[0]+1)|0 } return f"); +new Float64Array(BUF_64KB)[0] = 2.3; +assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] + 2.0) } return f"), this, null, BUF_64KB)(), 2.3+2); +assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] - 2.0) } return f"), this, null, BUF_64KB)(), 2.3-2); +assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] * 2.0) } return f"), this, null, BUF_64KB)(), 2.3*2); +assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] / 2.0) } return f"), this, null, BUF_64KB)(), 2.3/2); +assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] % 2.0) } return f"), this, null, BUF_64KB)(), 2.3%2); +assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +-f64[0] } return f"), this, null, BUF_64KB)(), -2.3); +assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "var sqrt=glob.Math.sqrt; function f() { return +sqrt(f64[0]) } return f"), this, null, BUF_64KB)(), Math.sqrt(2.3)); +new Int32Array(BUF_64KB)[0] = 42; +assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "var imul=glob.Math.imul; function f() { return imul(i32[0], 2)|0 } return f"), this, null, BUF_64KB)(), 84); + +// beware ye phis of comparisons and integers +var f = asmLink(asmCompile(USE_ASM + "function g(i) { i=i|0; if (i) { i = ((i|0) == 2); } else { i=(i-1)|0 } return i|0; } return g ")); +assertEq(f(0), -1); +assertEq(f(1), 0); +assertEq(f(2), 1); +var f = asmLink(asmCompile(USE_ASM + "function g(i) { i=i|0; if (i) { i = !i } else { i=(i-1)|0 } return i|0; } return g ")); +assertEq(f(0), -1); +assertEq(f(1), 0); +assertEq(f(2), 0); + +// beware ye constant-evaluate of boolean-producing operators +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 | (2 == 2))|0 } return f"))(), 5); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 | (!2))|0 } return f"))(), 4); + +// get that order-of-operations right! +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob','imp','buf', USE_ASM + "var i32=new glob.Int32Array(buf); var x=0; function a() { return x|0 } function b() { x=42; return 0 } function f() { i32[((b()|0) & 0x3) >> 2] = a()|0 } return f"), this, null, buf)(); +assertEq(new Int32Array(buf)[0], 42); + +assertEq(asmLink(asmCompile(USE_ASM + "function f() { var a=0,i=0; for (; ~~i!=4; i=(i+1)|0) { a = (a*5)|0; if (+(a>>>0) != 0.0) return 1; } return 0; } return f"))(), 0) + +// Signed integer division by a power of two. +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((i|0)/1)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), Math.pow(2,i)); + assertEq(f(Math.pow(2,i)-1), Math.pow(2,i)-1); + assertEq(f(-Math.pow(2,i)), -Math.pow(2,i)); + assertEq(f(-Math.pow(2,i)-1), -Math.pow(2,i)-1); +} +assertEq(f(INT32_MIN), INT32_MIN); +assertEq(f(INT32_MAX), INT32_MAX); +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((i|0)/2)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/2)|0); + assertEq(f(Math.pow(2,i)-1), ((Math.pow(2,i)-1)/2)|0); + assertEq(f(-Math.pow(2,i)), (-Math.pow(2,i)/2)|0); + assertEq(f(-Math.pow(2,i)-1), ((-Math.pow(2,i)-1)/2)|0); +} +assertEq(f(INT32_MIN), (INT32_MIN/2)|0); +assertEq(f(INT32_MAX), (INT32_MAX/2)|0); +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((i|0)/4)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/4)|0); + assertEq(f(Math.pow(2,i)-1), ((Math.pow(2,i)-1)/4)|0); + assertEq(f(-Math.pow(2,i)), (-Math.pow(2,i)/4)|0); + assertEq(f(-Math.pow(2,i)-1), ((-Math.pow(2,i)-1)/4)|0); +} +assertEq(f(INT32_MIN), (INT32_MIN/4)|0); +assertEq(f(INT32_MAX), (INT32_MAX/4)|0); +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((i|0)/1073741824)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/Math.pow(2,30))|0); + assertEq(f(Math.pow(2,i)-1), ((Math.pow(2,i)-1)/Math.pow(2,30))|0); + assertEq(f(-Math.pow(2,i)), (-Math.pow(2,i)/Math.pow(2,30))|0); + assertEq(f(-Math.pow(2,i)-1), ((-Math.pow(2,i)-1)/Math.pow(2,30))|0); +} +assertEq(f(INT32_MIN), (INT32_MIN/Math.pow(2,30))|0); +assertEq(f(INT32_MAX), (INT32_MAX/Math.pow(2,30))|0); +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((((i|0)/1)|0)+i)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), (Math.pow(2,i) * 2)|0); + assertEq(f(Math.pow(2,i) - 1), ((Math.pow(2,i) - 1) * 2)|0); + assertEq(f(-Math.pow(2,i)), (-Math.pow(2,i) * 2)|0); + assertEq(f(-Math.pow(2,i) - 1), ((-Math.pow(2,i) - 1) * 2)|0); +} +assertEq(f(INT32_MIN), (INT32_MIN * 2)|0); +assertEq(f(INT32_MAX), (INT32_MAX * 2)|0); + +// Signed integer division by a power of two - with a non-negative numerator! +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((i|0)/1)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), Math.pow(2,i)); + assertEq(f(Math.pow(2,i+1)-1), Math.pow(2,i+1)-1); +} +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((i|0)/2)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/2)|0); + assertEq(f(Math.pow(2,i+1)-1), ((Math.pow(2,i+1)-1)/2)|0); +} +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((i|0)/4)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/4)|0); + assertEq(f(Math.pow(2,i+1)-1), ((Math.pow(2,i+1)-1)/4)|0); +} +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((i|0)/1073741824)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/Math.pow(2,30))|0); + assertEq(f(Math.pow(2,i+1)-1), ((Math.pow(2,i+1)-1)/Math.pow(2,30))|0); +} +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((((i|0)/1)|0)+i)|0; } return f;")); +for (let i = 0; i < 31; i++) { + assertEq(f(Math.pow(2,i)), (Math.pow(2,i) * 2)|0); + assertEq(f(Math.pow(2,i+1) - 1), ((Math.pow(2,i+1) - 1) * 2)|0); +} +assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f(x, y) { x = x|0; y = y|0; g = (x>>>0)%(y>>>0)|0; return (x|0)%(y|0)|0; } return f;"))(0xff40001, 0xfff80000), 0x40001); diff --git a/js/src/jit-test/tests/asm.js/testFFI.js b/js/src/jit-test/tests/asm.js/testFFI.js new file mode 100644 index 000000000..cc6b5af20 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testFFI.js @@ -0,0 +1,164 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +function ffi(a,b,c,d) { + return a+b+c+d; +} + +var f = asmLink(asmCompile('global','imp', USE_ASM + 'var ffi=imp.ffi; function g() { return 1 } function f() { var i=0; i=g()|0; return ((ffi(4,5,6,7)|0)+i)|0 } return f'), null, {ffi:ffi}); +assertEq(f(1), 23); + +var counter = 0; +function inc() { return counter++ } +function add1(x) { return x+1 } +function add2(x,y) { return x+y } +function add3(x,y,z) { return x+y+z } +function addN() { + var sum = 0; + for (var i = 0; i < arguments.length; i++) + sum += arguments[i]; + return sum; +} +var imp = { inc:inc, add1:add1, add2:add2, add3:add3, addN:addN, identity: x => x }; + +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { incc() } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { var i = 0; return (i + inc)|0 } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc = 0 } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return (inc() + 1)|0 } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return +((inc()|0) + 1.1) } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return +(inc() + 1.1) } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return (+inc() + 1)|0 } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { var i = 0; inc(i>>>0) } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { if (0) return inc(); return } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc(inc()) } return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { g(inc()) } function g() {} return f'); +assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc()|inc() } return f'); + +assertAsmLinkFail(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc()|0 } return f'), null, {}); +assertAsmLinkFail(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc()|0 } return f'), null, {inc:0}); +assertAsmLinkFail(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc()|0 } return f'), null, {inc:{}}); + +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function g() { inc() } return g'), null, imp)(), undefined); +assertEq(counter, 1); + +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function g() { return inc()|0 } return g'), null, imp); +assertEq(f(), 1); +assertEq(counter, 2); +assertEq(f(), 2); +assertEq(counter, 3); + +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add1=imp.add1; function g(i) { i=i|0; return add1(i|0)|0 } return g'), null, imp)(9), 10); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add1=imp.add1; function g(i) { i=i|0; return add1(i|0)|0 } return g'), null, imp)(9), 10); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function g() { var i=1,j=3,k=9; return add3(i|0,j|0,k|0)|0 } return g'), null, imp)(), 13); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add3=imp.add3; function g() { var i=1,j=3,k=9; return add3(i|0,j|0,k|0)|0 } return g'), null, imp)(), 13); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function g() { var i=1.4,j=2.3,k=32.1; return +add3(i,j,k) } return g'), null, imp)(), 1.4+2.3+32.1); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add3=imp.add3; function g() { var i=1.4,j=2.3,k=32.1; return +add3(i,j,k) } return g'), null, imp)(), 1.4+2.3+32.1); + +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function f(i,j,k) { i=i|0;j=+j;k=k|0; return add3(i|0,j,k|0)|0 } return f'), null, imp)(1, 2.5, 3), 6); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var addN=imp.addN; function f() { return +addN(1,2,3,4.1,5,6.1,7,8.1,9.1,10,11.1,12,13,14.1,15.1,16.1,17.1,18.1) } return f'), null, imp)(), 1+2+3+4.1+5+6.1+7+8.1+9.1+10+11.1+12+13+14.1+15.1+16.1+17.1+18.1); + +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add2=imp.add2; function f(i,j) { i=i|0;j=+j; return +(+(add2(i|0,1)|0) + +add2(j,1) + +add2(+~~i,j)) } return f'), null, imp)(2, 5.5), 3+(5.5+1)+(2+5.5)); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var addN=imp.addN; function f(i,j) { i=i|0;j=+j; return +(+addN(i|0,j,3,j,i|0) + +addN() + +addN(j,j,j)) } return f'), null, imp)(1, 2.2), (1+2.2+3+2.2+1)+(2.2+2.2+2.2)); + +counter = 0; +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var addN=imp.addN,inc=imp.inc; function f() { return ((addN(inc()|0,inc(3.3)|0,inc()|0)|0) + (addN(inc(0)|0)|0))|0 } return f'), null, imp)(), 6); +assertEq(counter, 4); + +var recurse = function(i,j) { if (i == 0) return j; return f(i-1,j+1)+j } +imp.recurse = recurse; +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var r=imp.recurse; function f(i,j) { i=i|0;j=+j; return +r(i|0,j) } return f'), null, imp); +assertEq(f(0,3.3), 3.3); +assertEq(f(1,3.3), 3.3+4.3); +assertEq(f(2,3.3), 3.3+4.3+5.3); + +function maybeThrow(i, j) { + if (i == 0) + throw j; + try { + return f(i-1, j); + } catch(e) { + assertEq(typeof e, "number"); + return e; + } +} +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i, j) { i=i|0;j=j|0; return ffi(i|0, (j+1)|0)|0 } return f'), null, {ffi:maybeThrow}); +assertThrowsValue(function() { f(0,0) }, 1); +assertThrowsValue(function() { f(0,Math.pow(2,31)-1) }, -Math.pow(2,31)); +assertEq(f(1,0), 2); +assertEq(f(2,0), 3); +assertEq(f(3,0), 4); +assertEq(f(4,5), 10); + +var recurse = function(i,j) { if (i == 0) throw j; f(i-1,j) } +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function g(i,j,k) { i=i|0;j=+j;k=k|0; if (!(k|0)) ffi(i|0,j)|0; else g(i, j+1.0, (k-1)|0) } function f(i,j) { i=i|0;j=+j; g(i,j,4) } return f'), null, {ffi:recurse}); +assertThrowsValue(function() { f(0,2.4) }, 2.4+4); +assertThrowsValue(function() { f(1,2.4) }, 2.4+8); +assertThrowsValue(function() { f(8,2.4) }, 2.4+36); + +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var identity=imp.identity; function g(x) { x=+x; return +identity(x) } return g'), null, imp)(13.37), 13.37); + +// Test asm.js => ion paths +setJitCompilerOption("ion.warmup.trigger", 10); +setJitCompilerOption("baseline.warmup.trigger", 0); +setJitCompilerOption("offthread-compilation.enable", 0); + +// In registers on x64 and ARM, on the stack for x86 +function ffiIntFew(a,b,c,d) { return d+1 } +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; return ffi(i|0,(i+1)|0,(i+2)|0,(i+3)|0)|0 } return f'), null, {ffi:ffiIntFew}); +for (var i = 0; i < 40; i++) + assertEq(f(i), i+4); + +// Stack and registers for x64 and ARM, stack for x86 +function ffiIntMany(a,b,c,d,e,f,g,h,i,j) { return j+1 } +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; return ffi(i|0,(i+1)|0,(i+2)|0,(i+3)|0,(i+4)|0,(i+5)|0,(i+6)|0,(i+7)|0,(i+8)|0,(i+9)|0)|0 } return f'), null, {ffi:ffiIntMany}); +for (var i = 0; i < 15; i++) + assertEq(f(i), i+10); + +// In registers on x64 and ARM, on the stack for x86 +function ffiDoubleFew(a,b,c,d) { return d+1 } +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=+i; return +ffi(i,i+1.0,i+2.0,i+3.0) } return f'), null, {ffi:ffiDoubleFew}); +for (var i = 0; i < 15; i++) + assertEq(f(i), i+4); + +// Stack and registers for x64 and ARM, stack for x86 +function ffiDoubleMany(a,b,c,d,e,f,g,h,i,j) { return j+1 } +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=+i; return +ffi(i,i+1.0,i+2.0,i+3.0,i+4.0,i+5.0,i+6.0,i+7.0,i+8.0,i+9.0) } return f'), null, {ffi:ffiDoubleMany}); +for (var i = 0; i < 15; i++) + assertEq(f(i), i+10); + +// Test the throw path +function ffiThrow(n) { if (n == 14) throw 'yolo'; } +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; ffi(i >> 0); } return f'), null, {ffi:ffiThrow}); +var i = 0; +try { + for (; i < 15; i++) + f(i); + throw 'assume unreachable'; +} catch (e) { + assertEq(e, 'yolo'); + assertEq(i, 14); +} + +// OOL conversion paths +var INT32_MAX = Math.pow(2, 31) - 1; +function ffiOOLConvertInt(n) { if (n == 40) return valueToConvert; return 42; } +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; return ffi(i >> 0) | 0; } return f'), null, {ffi:ffiOOLConvertInt}); +for (var i = 0; i < 40; i++) + assertEq(f(i), 42); +valueToConvert = INT32_MAX + 1; +assertEq(f(40), INT32_MAX + 1 | 0); +function testBadConversions(f) { + valueToConvert = {valueOf: function () { throw "FAIL"; }}; + assertThrowsValue(() => f(40), "FAIL"); + valueToConvert = Symbol(); + assertThrowsInstanceOf(() => f(40), TypeError); +} +testBadConversions(f); + +function ffiOOLConvertDouble(n) { if (n == 40) return valueToConvert; return 42.5; } +var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; return +ffi(i >> 0); } return f'), null, {ffi:ffiOOLConvertDouble}); +for (var i = 0; i < 40; i++) + assertEq(f(i), 42.5); +valueToConvert = {valueOf: function() { return 13.37 }}; +assertEq(f(40), 13.37); +testBadConversions(f); diff --git a/js/src/jit-test/tests/asm.js/testFastHeapAccess.js b/js/src/jit-test/tests/asm.js/testFastHeapAccess.js new file mode 100644 index 000000000..09bd89693 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testFastHeapAccess.js @@ -0,0 +1,81 @@ +load(libdir + "asm.js"); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; u32[((i<<2)+32 & 0xffff)>>2] = j } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + f(i, i); +var u32 = new Uint32Array(BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(u32[8+i], i); +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return u32[((i<<2)+32 & 0xffff)>>2]|0 } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(f(i), i); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; u32[(i<<2 & 0xffff)>>2] = j } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + f(i, i); +var u32 = new Uint32Array(BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(u32[i], i); +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return u32[(i<<2 & 0xffff)>>2]|0 } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(f(i), i); + +// For legacy compatibility, test Int8/Uint8 accesses with no shift. +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; u8[i+20 & 0xffff] = j } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + f(i, i); +var u8 = new Uint8Array(BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(u8[i+20], i); +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return u8[i+20 & 0xffff]|0 } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(f(i), i); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; u8[(i+20 & 0xffff)>>0] = j } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + f(i, i); +var u8 = new Uint8Array(BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(u8[i+20], i); +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return u8[(i+20 & 0xffff)>>0]|0 } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(f(i), i); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j,k) {i=i|0;j=j|0;k=k|0; i32[(i + (j<<2) & 0xffff) >> 2] = k } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + f(32, i, i); +var u32 = new Uint32Array(BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(u32[8+i], i); +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; return i32[(i + (j<<2) & 0xffff) >> 2]|0 } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(f(32, i), i); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j,k) {i=i|0;j=j|0;k=k|0; i32[(((i + (j<<2))|0) + 16 & 0xffff) >> 2] = k } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + f(32, i, i); +var u32 = new Uint32Array(BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(u32[8+i+4], i); +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; return i32[(((i + (j<<2))|0) + 16 & 0xffff) >> 2]|0 } return f'); +var f = asmLink(code, this, null, BUF_64KB); +for (var i = 0; i < 100; i++) + assertEq(f(32, i), i); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; return ((i32[(i+(j<<2)&0xffff)>>2]|0) + (i32[(((i+(j<<2))|0)+4&0xffff)>>2]|0))|0 } return f'); +var f = asmLink(code, this, null, BUF_64KB); +var i32 = new Uint32Array(BUF_64KB); +i32[11] = 3; +i32[12] = 97; +assertEq(f(12,8), 100); diff --git a/js/src/jit-test/tests/asm.js/testFloat32.js b/js/src/jit-test/tests/asm.js/testFloat32.js new file mode 100644 index 000000000..34f893b07 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testFloat32.js @@ -0,0 +1,321 @@ +load(libdir + "asm.js"); +const TO_FLOAT32 = "var toF = glob.Math.fround;"; +const HEAP32 = "var f32 = new glob.Float32Array(heap);"; +const HEAP64 = "var f64 = new glob.Float64Array(heap);" +var heap = new ArrayBuffer(BUF_MIN); + +// Module linking +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() {} return f"), null); +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() {} return f"), {fround: Math.fround}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() {} return f"), {Math: {fround: Math.imul}}); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() {} return f"), {Math:{fround: Math.fround}})(), undefined); + +// Argument coercions +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = unknown(x); } return f"); +assertAsmTypeFail('glob', USE_ASM + "function f(i) { i = toF(i); } return f"); +assertAsmTypeFail('glob', USE_ASM + "var cos = glob.Math.cos; function f(x) { x = cos(x); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x, x); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF('hi'); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(loat); } return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(i) { i = toF(i); } return f"), this)(), undefined); + +// Local variables declarations +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = unknown(); } return f"); +assertAsmTypeFail('glob', USE_ASM + "var cos = glob.Math.cos; function f() { var i = cos(); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(x, x); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF('hi'); } return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5); } return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); } return f"), this)(), undefined); + +// Return values +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(4, 4); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF({}); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(x); } return f"); + +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(42); } return f"), this)(), 42); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(0.); } return f"), this)(), 0); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(-0.); } return f"), this)(), -0); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var inf = glob.Infinity; function f() { return toF(inf); } return f"), this)(), Infinity); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(13.37); } return f"), this)(), Math.fround(13.37)); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return +toF(4.); } return f"), this)(), 4); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return +~~toF(4.5); } return f"), this)(), 4); + +// Assign values +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); i = 5; return toF(i); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); i = 6.; return toF(i); } return f"); + +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(-0.); return toF(i); } return f"), this)(), -0); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(0.); return toF(i); } return f"), this)(), 0); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); return toF(i); } return f"), this)(), 5); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); i = toF(42); return toF(i); } return f"), this)(), 42); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); i = toF(6.); return toF(i); } return f"), this)(), 6); + +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { var i = toF(5.); f32[0] = toF(6.); i = f32[0]; return toF(i); } return f"); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { var i = toF(5.); f32[0] = toF(6.); i = toF(f32[0]); return toF(i); } return f"), this, null, heap)(), 6); + +// Special array assignments (the other ones are tested in testHeapAccess) +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { var i = 5.; f32[0] = i; return toF(f32[0]); } return f"), this, null, heap)(), 5); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "var f64 = new glob.Float64Array(heap); function f() { var i = toF(5.); f64[0] = i; return +f64[0]; } return f"), this, null, heap)(), 5); + +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 1.5; return +f32[0]; } return f"), this, null, heap)(), 1.5); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + HEAP64 + "function f() { f64[0] = 1.5; return toF(f64[0]); } return f"), this, null, heap)(), 1.5); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + HEAP64 + "function f() { f32[0] = toF(42); f64[0] = f32[0]; return +f64[0]; } return f"), this, null, heap)(), 42); + +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = toF(-1.4013e-45) / toF(42.); } return f"), this, null, heap)(), undefined); + +// Coercions +// -> from Float32 +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var n = 0; n = toF(4.5) | 0; } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); var n = 0; n = i | 0; return n | 0; } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); var n = 0; n = ~~(x + x) >>> 0; return n | 0; } return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); var n = 0.; n = +x; return +n; } return f"), this)(16.64), Math.fround(16.64)); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); var n = 0; n = ~~x; return n | 0; } return f"), this)(16.64), 16); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); var n = 0; n = ~~x >>> 0; return n | 0; } return f"), this)(16.64), 16); + +// -> from float? +function makeCoercion(coercionFunc) { + return USE_ASM + HEAP32 + TO_FLOAT32 + "function f(x) { x = toF(x); f32[0] = x; return " + coercionFunc('f32[0]') + " } return f"; +} +assertAsmTypeFail('glob', 'ffi', 'heap', makeCoercion(x => x + '|0')); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', makeCoercion(x => '+' + x)), this, null, heap)(16.64), Math.fround(16.64)); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', makeCoercion(x => 'toF(' + x + ')')), this, null, heap)(16.64), Math.fround(16.64)); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', makeCoercion(x => '~~+' + x + '|0')), this, null, heap)(16.64), 16); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', makeCoercion(x => '~~toF(' + x + ')|0')), this, null, heap)(16.64), 16); + +// -> to Float32 +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(~~x); } return f"), this)(23), 23); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x >> 0); } return f"), this)(23), 23); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = +x; return toF(x); } return f"), this)(13.37), Math.fround(13.37)); + +UINT32_MAX = Math.pow(2, 32)-1; +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x >>> 0); } return f"), this)(-1), Math.fround(UINT32_MAX)); +var tof = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x>>>0) } return f"), this); +for (x of [0, 1, 10, 64, 1025, 65000, Math.pow(2,30), Math.pow(2,31), Math.pow(2,32)-2, Math.pow(2,32)-1]) + assertEq(tof(x), Math.fround(x)); + +// Global variables imports +assertAsmTypeFail('glob', USE_ASM + "var x = toF(); function f() {} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = some(3); function f() {} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(); function f() {} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(3, 4); function f() {} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF({x: 3}); function f() {} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(true); function f() {} return f"); +assertAsmTypeFail('glob', USE_ASM + "var x = toF(3);" + TO_FLOAT32 + "function f() {} return f"); + +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var x = toF(3.5); function f() {} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var x = toF(3); function f() {} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', 'ffi', USE_ASM + TO_FLOAT32 + "var x = toF(ffi.x); function f() {} return f"), this, {x:3})(), undefined); +assertEq(asmLink(asmCompile('glob', 'ffi', USE_ASM + TO_FLOAT32 + "var x = toF(ffi.x); function f() {} return f"), this, {x:3.5})(), undefined); + +// Global variables uses +values = [2.01, 13.37, -3.141592653] +specials = [NaN, Infinity] + +for (v of values) { + assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var x = toF(" + v + "); function f() {return toF(x);} return f"), this)(), Math.fround(v)); + assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "const x = toF(" + v + "); function f() {return toF(x);} return f"), this)(), Math.fround(v)); + assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var x = toF(0.); function f() {x = toF(" + v + "); return toF(x);} return f"), this)(), Math.fround(v)); + assertEq(asmLink(asmCompile('glob', 'ffi', USE_ASM + TO_FLOAT32 + "var x = toF(ffi.x); function f() {return toF(x);} return f"), this, {x:v})(), Math.fround(v)); +} + +for (v of specials) { + assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var special = glob." + v + "; var g=toF(0.); function f() {g=toF(special); return toF(g);} return f"), this)(), Math.fround(v)); +} + +// Math builtins +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var imul = glob.Math.imul; function f() {var x = toF(1.5), y = toF(2.4); return imul(x, y) | 0;} return f"); + +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(1.5); return abs(x) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(1.5); return +abs(x);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(1.5); return +toF(abs(x));} return f"), this)(), 1.5); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(1.5); return toF(abs(x))} return f"), this)(), Math.fround(1.5)); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(-1.5); return toF(abs(x))} return f"), this)(), Math.fround(1.5)); + +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(1.5); return sqrt(x) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(1.5); return +sqrt(x);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(1.5); return +toF(sqrt(x));} return f"), this)(), Math.fround(Math.sqrt(Math.fround(1.5)))); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(2.25); return toF(sqrt(x))} return f"), this)(), Math.fround(1.5)); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(-1.); return toF(sqrt(x))} return f"), this)(), NaN); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; var inf = glob.Infinity; function f() {var x = toF(0.); x = toF(inf); return toF(sqrt(x))} return f"), this)(), Infinity); + +// float?s +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f(x) { x = toF(x); f32[0] = x; return toF(sqrt(f32[0])) } return f"), this, null, heap)(64), Math.fround(8)); + +// The only other Math functions that can receive float32 as arguments and that strictly commute are floor and ceil (see +// also bug 969203). +var floorModule = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.floor; function f(x) {x = toF(x); return toF(g(x))} return f"), this); +for (v of [-10.5, -1.2345, -1, 0, 1, 3.141592653, 13.37, Math.Infinity, NaN]) + assertEq(floorModule(v), Math.fround(Math.floor(Math.fround(v)))); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var floor = glob.Math.floor; function f(x) { x = toF(x); f32[0] = x; return toF(floor(f32[0])) } return f"), this, null, heap)(13.37), 13); + +var ceilModule = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.ceil; function f(x) {x = toF(x); return toF(g(x))} return f"), this); +for (v of [-10.5, -1.2345, -1, 0, 1, 3.141592653, 13.37, Math.Infinity, NaN]) + assertEq(ceilModule(v), Math.fround(Math.ceil(Math.fround(v)))); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var ceil = glob.Math.ceil; function f(x) { x = toF(x); f32[0] = x; return toF(ceil(f32[0])) } return f"), this, null, heap)(13.37), 14); + +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return toF(g(x))} return f"); + +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return +(g(x))} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = x|0; return toF(g(x))} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return g(x) | 0} return f"); + +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = +x; return toF(g(+x))} return f"), this)(5), Math.fround(Math.cos(5))); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = +x; return toF(g(x))} return f"), this)(5), Math.fround(Math.cos(5))); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) { x = toF(x); return toF(+g(+x)) } return f"), this, null, heap)(3.14159265358), -1); + +// Math functions with arity of two are not specialized for floats, so we shouldn't feed them with floats arguments or +// return type +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(g(x, 2.))} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return +g(x, 2.)} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(g(+x, 2.))} return f"), this)(3), 9); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return +g(+x, 2.)} return f"), this)(3), 9); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(+g(+x, 2.))} return f"), this)(3), 9); + +// Other function calls +// -> Signature comparisons +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x); return toF(x);} function f() {var x=toF(4.); var y=toF(0.); var z = 0.; y=toF(g(x)); z = +g(x); return toF(z); } return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt=glob.Math.sqrt; function g(x){x=toF(x); return toF(sqrt(x));} function f() {var x=toF(4.); var y=toF(0.); var z = 0.; y = toF(g(x)); z = +toF(g(x)); return toF(z); } return f"), this)(), 2); + +// -> FFI +var FFI = "var ffi = env.ffi;"; +assertAsmTypeFail('glob', 'env', USE_ASM + TO_FLOAT32 + FFI + "function f() {var x = toF(3.14); return +ffi(x);} return f"); +assertAsmTypeFail('glob', 'env', USE_ASM + TO_FLOAT32 + FFI + "function f() {var x = toF(3.14); return toF(ffi(+x));} return f"); + +var env = {ffi: function(x) { return x+1; }}; // use registers +assertEq(asmLink(asmCompile('glob', 'env', USE_ASM + TO_FLOAT32 + FFI + "function f(x) {x = toF(x); return toF(+ffi(+x));} return f"), this, env)(5), Math.fround(6)); +env = {ffi: function(a,b,c,d,e,f,g,h,i) { return a+b+c+d+e+f+g+h+i; }}; // use stack arguments (> 8 arguments on linux x64) +assertEq(asmLink(asmCompile('glob', 'env', USE_ASM + TO_FLOAT32 + FFI + "function f(x) {x = toF(x); return toF(+ffi(+x, 1., 2., 3., 4., 5., -5., -4., 1.));} return f"), this, env)(5), Math.fround(12)); + +// -> Internal calls +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x);return toF(+x + 1.);} function f(x) {x = +x; return toF(g(x));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x);return toF(+x + 1.);} function f(x) {x = x|0; return toF(g(x));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x);return toF(+x + 1.);} function f(x) {x = x|0; return toF(g(x));} return f"); + +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x);return toF(+x + 1.);} function f(x) {x = toF(x); return toF(g(x));} return f"), this, env)(5), Math.fround(6)); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function g(x,y){x=toF(x);y=toF(y);return toF(+x + +y);} function f(x) {x = toF(x); return toF(g(x, toF(1.)));} return f"), this, env)(5), Math.fround(6)); + +// --> internal calls with unused return values +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = +x; g = (g + ~~x)|0; return g|0;} function f(x) { x = +x; toF(s(x)); return g|0} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = +x; g = (g + ~~x)|0; return toF(g|0);} function f(x) { x = +x; toF(s(x)); return g|0} return f"), this)(3), 7); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = toF(x); g = (g + ~~x)|0; return toF(g|0);} function f(x) { x = toF(x); return (toF(s(x)), g)|0} return f"), this)(3), 7); + +// --> coerced calls +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = toF(x); g = (g + ~~x)|0; return +(g|0);} function f(x) { x = toF(x); return toF(+s(x))} return f"), this)(3), 7); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = toF(x); g = (g + ~~x)|0; return g|0;} function f(x) { x = toF(x); return toF(s(x)|0)} return f"), this)(3), 7); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = toF(x); g = (g + ~~x)|0; return toF(g|0);} function f(x) { x = toF(x); return toF(toF(s(x)))} return f"), this)(3), 7); + +// --> test pressure on registers in internal calls when there are |numArgs| arguments +for (numArgs of [5, 9, 17, 33, 65, 129]) { + let code = (function(n) { + let args = "", coercions = "", sum = "", call="x"; + for (let i = 0; i < n; i++) { + let name = 'a' + i; + args += name + ((i == n-1)?'':','); + coercions += name + '=toF(' + name + ');'; + sum += ((i>0)?'+':'') + ' +' + name; + call += (i==0)?'':',toF(' + i + '.)' + } + return "function g(" + args + "){" + coercions + "return toF(" + sum + ");}" + +"function f(x) { x = toF(x); return toF(g(" + call + "))}"; + })(numArgs); + assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + code + "return f"), this, env)(5), Math.fround(5 + numArgs * (numArgs-1) / 2)); +} + +// -> Pointer calls +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);} function f(x, n) {x=+x;n=n|0;return toF(t[n&1](x));} var t=[a,b]; return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);} function f(x, n) {x=x|0;n=n|0;return toF(t[n&1](x));} var t=[a,b]; return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);} function f(x, n) {x=toF(x);n=n|0;return t[n&1](x)|0;} var t=[a,b]; return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);} function f(x, n) {x=toF(x);n=n|0;return +t[n&1](x);} var t=[a,b]; return f"); + +code = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);}" + + "function f(x, n) {x=toF(x);n=n|0;return toF(t[n&1](x));} var t=[a,b]; return f"), this); +assertEq(code(0, 0), .5); +assertEq(code(0, 1), -.5); +assertEq(code(13.37, 0), Math.fround(13.37 + .5)); +assertEq(code(13.37, 1), Math.fround(13.37 - .5)); + +// Arithmetic operations +// -> mul +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3 * toF(4.));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3. * toF(4.)); } return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return +(toF(3.) * toF(4.));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3) * toF(4) * toF(5));} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.) * toF(4.)); } return f"), this)(), 12); + +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3 * f32[0]);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3. * f32[0]);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return +(toF(3.) * f32[0]);} return f"); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(toF(3.) * f32[0]);} return f"), this, null, heap)(), 12); + +var mul = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x=toF(x); return toF(x * toF(4.));} return f"), this); +assertEq(mul(Infinity), Infinity); +assertEq(mul(NaN), NaN); +assertEq(mul(0), 0); +assertEq(mul(1), 4); +assertEq(mul(0.33), Math.fround(0.33 * 4)); + +// -> add +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3 + toF(4.));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3.5 + toF(4.));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return +(toF(3.5) + toF(4.));} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) + toF(4.)); } return f"), this)(), 7.5); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) + toF(4.) + toF(4.5));} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(toF(3.5) + toF(4.)) + toF(4.5)); } return f"), this)(), 12); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(toF(3) + f32[0]);} return f"), this, null, heap)(), 7); + +// --> no additions with float? or floatish +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3 + f32[0]);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3. + f32[0]);} return f"); + +// -> sub +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3 - toF(4.));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3.5 - toF(4.));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return +(toF(3.5) - toF(4.));} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) - toF(4.)); } return f"), this)(), -.5); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) - toF(4.) - toF(4.5));} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(toF(3.5) - toF(4.)) - toF(4.5)); } return f"), this)(), -5); + +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) + toF(4.) - toF(4.5));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) - toF(4.) + toF(4.5));} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(toF(3.5) + toF(4.)) - toF(4.5)); } return f"), this)(), 3); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(toF(3.5) - toF(4.)) + toF(4.5)); } return f"), this)(), 4); + +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3 - f32[0]);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3. - f32[0]);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return +(toF(3) - f32[0]);} return f"); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(toF(3) - f32[0]);} return f"), this, null, heap)(), -1); + +// -> div +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3 / toF(4.));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3.5 / toF(4.));} return f"); +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return +(toF(3.5) / toF(4.));} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(12.) / toF(4.)); } return f"), this)(), 3); + +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3 / f32[0]);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3. / f32[0]);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return +(toF(3) / f32[0]);} return f"); +assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 2.; return toF(toF(4) / f32[0]);} return f"), this, null, heap)(), 2); + +// -> mod +assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) % toF(4.));} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { return toF(f32[0] % toF(4.));} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { return toF(toF(3.5) % f32[0]);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { return toF(f32[1] % f32[0]);} return f"); + +// Comparisons +for (op of ['==', '!=', '<', '>', '<=', '>=']) { + let code = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); if( x " + op + " toF(3.) ) return 1; else return 0; return -1; } return f"), this); + let ternary = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); return ((x " + op + " toF(3.)) ? 1 : 0)|0 } return f"), this); + for (v of [-5, 0, 2.5, 3, 13.37, NaN, Infinity]) { + let expected = eval("("+ v + " " + op + " 3)|0"); + assertEq(code(v) | 0, expected); + assertEq(ternary(v) | 0, expected); + } + + assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { if( f32[0] " + op + " toF(3.) ) return 1; else return 0; return -1; } return f"); + assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { if( (toF(1.) + toF(2.)) " + op + " toF(3.) ) return 1; else return 0; return -1; } return f"); +} + diff --git a/js/src/jit-test/tests/asm.js/testFloatingPoint.js b/js/src/jit-test/tests/asm.js/testFloatingPoint.js new file mode 100644 index 000000000..bad22028e --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testFloatingPoint.js @@ -0,0 +1,134 @@ +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); +assertEq(f(1.1, 1.1), 1); +assertEq(f(2.1, 1.1), 0); +assertEq(f(NaN, 1.1), 0); +assertEq(f(1.1, NaN), 0); +assertEq(f(NaN, NaN), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d>e)|0 } return f")); +assertEq(f(2.1, 1.1), 1); +assertEq(f(1.1, 1.1), 0); +assertEq(f(1.1, 2.1), 0); +assertEq(f(NaN, 1.1), 0); +assertEq(f(1.1, NaN), 0); +assertEq(f(NaN, NaN), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d>=e)|0 } return f")); +assertEq(f(2.1, 1.1), 1); +assertEq(f(1.0, 1.1), 0); +assertEq(f(1.1, 2.1), 0); +assertEq(f(NaN, 1.1), 0); +assertEq(f(1.1, NaN), 0); +assertEq(f(NaN, NaN), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d==e)|0 } return f")); +assertEq(f(2.1, 1.1), 0); +assertEq(f(1.1, 1.1), 1); +assertEq(f(1.1, 2.1), 0); +assertEq(f(NaN, 1.1), 0); +assertEq(f(1.1, NaN), 0); +assertEq(f(NaN, NaN), 0); + +var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d!=e)|0 } return f")); +assertEq(f(2.1, 1.1), 1); +assertEq(f(1.1, 1.1), 0); +assertEq(f(1.1, 2.1), 1); +assertEq(f(NaN, 1.1), 1); +assertEq(f(1.1, NaN), 1); +assertEq(f(NaN, NaN), 1); + +var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d/e) } return f")); +assertEq(f(1.1, .1), (1.1/.1)); +assertEq(f(1.1, 0), (1.1/0)); +assertEq(f(1.1, -0), (1.1/-0)); + +var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d%e) } return f")); +assertEq(f(1.1, .1), (1.1%.1)); +assertEq(f(1.1, 0), (1.1%0)); +assertEq(f(1.1, -0), (1.1%-0)); + +var f = asmLink(asmCompile(USE_ASM + "function f(d) { d=+d; var i = 0; i = ~~d; return i|0 } return f")); +assertEq(f(1.0), 1); +assertEq(f(1.9), 1); +assertEq(f(1.9999), 1); +assertEq(f(2.0), 2); +assertEq(f(Math.pow(2,40)), ~~Math.pow(2,40)); +assertEq(f(-Math.pow(2,40)), ~~-Math.pow(2,40)); +assertEq(f(4000000000), ~~4000000000); +assertEq(f(-4000000000), ~~-4000000000); +assertEq(f(NaN), 0); +assertEq(f(Infinity), 0); +assertEq(f(-Infinity), 0); + +assertAsmTypeFail(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +((i|0)/(j|0)) } return f"); +assertAsmTypeFail(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +(i+j) } return f"); +assertAsmTypeFail(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +(i-j) } return f"); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +(((i|0)/(j|0))|0) } return f")); +assertEq(f(1,0), 0); +assertEq(f(-Math.pow(2,31),-1), -Math.pow(2,31)); + +var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +(((i|0)%(j|0))|0) } return f")); +assertEq(f(1,0), 0); +assertEq(f(-Math.pow(2,31),-1), 0); + +var {f,g} = asmLink(asmCompile(USE_ASM + "function f() { return 3.5 } function g(d) { d=+d; return +(d+3.5) } return {f:f,g:g}")); +assertEq(f(), 3.5); +assertEq(g(1), 1+3.5); + +var buf = new ArrayBuffer(BUF_MIN); +var f64 = new Float64Array(buf); +var i32 = new Int32Array(buf); +var u32 = new Uint32Array(buf); +var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[0] } return f'), this, null, buf); +f64[0] = 0; +assertEq(f(), 0); +f64[0] = -1; +assertEq(f(), -1); +f64[0] = 1; +assertEq(f(), 1); +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()|0; 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]); + + g(); + assertEq(str, String(f64[0])); + + assertEq(h(), Math.abs(f64[0])); + } +} diff --git a/js/src/jit-test/tests/asm.js/testFunctionPtr.js b/js/src/jit-test/tests/asm.js/testFunctionPtr.js new file mode 100644 index 000000000..9998356f0 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testFunctionPtr.js @@ -0,0 +1,74 @@ +load(libdir + "asm.js"); + +assertAsmTypeFail('imp', USE_ASM + "function f() {} var imp=[f]; return f"); +assertAsmTypeFail(USE_ASM + "function f() {} var eval=[f]; return f"); +assertAsmTypeFail(USE_ASM + "var tbl=0; function f() {} var tbl=[f]; return f"); +assertAsmTypeFail(USE_ASM + "function f() {} var tbl; return f"); +assertAsmTypeFail(USE_ASM + "function f() {} var tbl=[]; return f"); +assertAsmTypeFail(USE_ASM + "function f() {} var tbl=[f,f,f]; return f"); +assertAsmTypeFail(USE_ASM + "function f() {} var tbl=[1]; return f"); +assertAsmTypeFail(USE_ASM + "var g = 0; function f() {} var tbl=[g]; return f"); +assertAsmTypeFail(USE_ASM + "function f() {} function g(i) {i=i|0} var tbl=[f,g]; return f"); +assertAsmTypeFail(USE_ASM + "function f() {} function g() {return 0} var tbl=[f,g]; return f"); +assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) {i=+i} var tbl=[f,g]; return f"); +assertAsmTypeFail(USE_ASM + "function f() {return 0} function g() {return 0.0} var tbl=[f,g]; return f"); +assertAsmTypeFail(USE_ASM + "var tbl=0; function g() {tbl[0&1]()|0} return g"); +assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 42 } var tbl=[f]; return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 0} function g() {return 1} var tbl=[f,g]; return f"))(), 0); + +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return ([])[i&1]()|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return f[i&1]()|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i]()|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&0]()|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&3]()|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i,j) { i=i|0;j=+j; return tbl[j&1]()|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1](1)|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) { i=i|0; return tbl[i&1](3.0)|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function f(d) {d=+d} function g(i) { i=i|0; return tbl[i&1](3)|0 } var tbl=[f,f]; return g"); +assertAsmTypeFail(USE_ASM + "function g() {tbl[0&1]()|0} return g"); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,f]; return g"))(0), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1]()|0 } const tbl=[f,f]; return g"))(0), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,g]; return h"))(1), 13); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl[i&1]()|0 } const tbl=[f,g]; return h"))(1), 13); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&1]()|0 } var tbl1=[f,g]; var tbl2=[g,f]; return h"))(1), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&1]()|0 } const tbl1=[f,g]; const tbl2=[g,f]; return h"))(1), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&3]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(3), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&3]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(3), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl1[i&1]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(1), 13); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl1[i&1]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(1), 13); +assertEq(asmLink(asmCompile(USE_ASM + "var i=0,j=0; function f() {return i|0} function g() {return j|0} function h(x) { x=x|0; i=5;j=10; return tbl2[x&3]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(3), 5); +assertEq(asmLink(asmCompile(USE_ASM + "var i=0,j=0; function f() {return i|0} function g() {return j|0} function h(x) { x=x|0; i=5;j=10; return tbl2[x&3]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(3), 5); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi=imp.ffi; function f() {return ffi()|0} function g() {return 13} function h(x) { x=x|0; return tbl2[x&3]()|0 } var tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 20); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "const ffi=imp.ffi; function f() {return ffi()|0} function g() {return 13} function h(x) { x=x|0; return tbl2[x&3]()|0 } const tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 20); +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi=imp.ffi; var i=0; function f() {return ((ffi()|0)+i)|0} function g() {return 13} function h(x) { x=x|0; i=2; return tbl2[x&3]()|0 } var tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 22) +;assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "const ffi=imp.ffi; var i=0; function f() {return ((ffi()|0)+i)|0} function g() {return 13} function h(x) { x=x|0; i=2; return tbl2[x&3]()|0 } const tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 22); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) {i=i|0; return +((i+1)|0)} function g(d) { d=+d; return +(d+2.5) } function h(i,j) { i=i|0;j=j|0; return +tbl2[i&1](+tbl1[i&1](j)) } var tbl1=[f,f]; var tbl2=[g,g]; return h"))(0,10), 11+2.5); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) {i=i|0; return +((i+1)|0)} function g(d) { d=+d; return +(d+2.5) } function h(i,j) { i=i|0;j=j|0; return +tbl2[i&1](+tbl1[i&1](j)) } const tbl1=[f,f]; const tbl2=[g,g]; return h"))(0,10), 11+2.5); + +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0]()|0 } var tbl=[f]; return g"); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() { return tbl[0&0]()|0 } var tbl=[f]; return g"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() { return tbl[0&0]()|0 } const tbl=[f]; return g"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f1() {return 42} function f2() {return 13} function g() { return tbl[1&1]()|0 } var tbl=[f1,f2]; return g"))(), 13); +assertEq(asmLink(asmCompile(USE_ASM + "function f1() {return 42} function f2() {return 13} function g() { return tbl[1&1]()|0 } const tbl=[f1,f2]; return g"))(), 13); + +// Test some literal constant paths. +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&4294967295]()|0 } var tbl=[f]; return g"); +assertAsmTypeFail(USE_ASM + "const i=4294967295; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&-1]()|0 } var tbl=[f]; return g"); +assertAsmTypeFail(USE_ASM + "const i=-1; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&0x80000000]()|0 } var tbl=[f]; return g"); +assertAsmTypeFail(USE_ASM + "const i=0x80000000; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g"); +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&-2147483648]()|0 } var tbl=[f]; return g"); +assertAsmTypeFail(USE_ASM + "const i=-2147483648; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g"); +assertAsmTypeFail(USE_ASM + "const i=0; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g"); +// Limited by the inability to test really large tables. +assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&0x7fffffff]()|0 } var tbl=[f]; return g"); + +var f = asmLink(asmCompile(USE_ASM + "function f1(d) {d=+d; return +(d/2.0)} function f2(d) {d=+d; return +(d+10.0)} function g(i,j) { i=i|0;j=+j; return +tbl[i&1](+tbl[(i+1)&1](j)) } var tbl=[f1,f2]; return g")); +assertEq(f(0,10.2), (10.2+10)/2); +assertEq(f(1,10.2), (10.2/2)+10); + +var f = asmLink(asmCompile('glob','imp', USE_ASM + "var ffi=imp.ffi; function f(){return 13} function g(){return 42} function h(i) { i=i|0; var j=0; ffi(1); j=TBL[i&7]()|0; ffi(1.5); return j|0 } var TBL=[f,g,f,f,f,f,f,f]; return h"), null, {ffi:function(){}}); +for (var i = 0; i < 100; i++) + assertEq(f(i), (i%8 == 1) ? 42 : 13); diff --git a/js/src/jit-test/tests/asm.js/testGlobals.js b/js/src/jit-test/tests/asm.js/testGlobals.js new file mode 100644 index 000000000..1e9fc3ac9 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testGlobals.js @@ -0,0 +1,164 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +assertAsmTypeFail(USE_ASM + "var i; function f(){} return f"); +assertEq(asmLink(asmCompile(USE_ASM + "var i=0; function f(){} return f"))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + "const i=0; function f(){} return f"))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + "var i=42; function f(){ return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "const i=42; function f(){ return i|0 } return f"))(), 42); +assertEq(asmLink(asmCompile(USE_ASM + "var i=4.2; function f(){ return +i } return f"))(), 4.2); +assertEq(asmLink(asmCompile(USE_ASM + "const i=4.2; function f(){ return +i } return f"))(), 4.2); +assertAsmTypeFail(USE_ASM + "var i=42; function f(){ return +(i+.1) } return f"); +assertAsmTypeFail(USE_ASM + "const i=42; function f(){ return +(i+.1) } return f"); +assertAsmTypeFail(USE_ASM + "var i=1.2; function f(){ return i|0 } return f"); +assertAsmTypeFail(USE_ASM + "const i=1.2; function f(){ return i|0 } return f"); +assertAsmTypeFail(USE_ASM + "var i=0; function f(e){ e=+e; i=e } return f"); +assertAsmTypeFail(USE_ASM + "var d=0.1; function f(i){ i=i|0; d=i } return f"); +assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; i=j; return i|0 } return f"))(42), 42); +assertEq(asmLink(asmCompile(USE_ASM + "var d=.1; function f(e) { e=+e; d=e; return +e } return f"))(42.1), 42.1); +assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(i, j) { i=i|0; j=j|0; i=j; return i|0 } return f"))(42,43), 43); +assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; var i=0; i=j; return i|0 } return f"))(42), 42); + +var f = asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; if ((j|0) != -1) { i=j } else { return i|0 } return 0 } return f")); +assertEq(f(-1), 13); +assertEq(f(42), 0); +assertEq(f(-1), 42); + +assertAsmTypeFail(USE_ASM + "var i=13; function f() { var j=i; return j|0 } return f"); +assertAsmTypeFail(USE_ASM + "var i=13.37; function f() { var j=i; return +j } return f"); +assertAsmTypeFail('global', USE_ASM + "var f32 = global.Math.fround; var i=f32(13.37); function f() { var j=i; return f32(j) } return f"); + +assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { var j=i; return +j } return f'), {Infinity:Infinity})(), Infinity); +assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { var j=i; return +j } return f'), {NaN:NaN})(), NaN); + +assertEq(asmLink(asmCompile(USE_ASM + "const i=13; function f() { var j=i; return j|0 } return f"))(), 13); +assertEq(asmLink(asmCompile(USE_ASM + "const i=13.37; function f() { var j=i; return +j } return f"))(), 13.37); +assertEq(asmLink(asmCompile('global', USE_ASM + "var f32 = global.Math.fround; const i=f32(13.37); function f() { var j=i; return f32(j) } return f"), this)(), Math.fround(13.37)); + +assertAsmTypeFail(USE_ASM + "function f() { var j=i; return j|0 } return f"); +assertAsmTypeFail(USE_ASM + "function i(){} function f() { var j=i; return j|0 } return f"); +assertAsmTypeFail(USE_ASM + "function f() { var j=i; return j|0 } var i = [f]; return f"); +assertAsmTypeFail('global', USE_ASM + "var i=global.Math.fround; function f() { var j=i; return j|0 } return f"); +assertAsmTypeFail('global', 'imp', USE_ASM + "var i=imp.f; function f() { var j=i; return j|0 } return f"); +assertAsmTypeFail('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { var j=i; return j|0 } return f"); +assertAsmTypeFail('global', 'imp', USE_ASM + "var i=+imp.i; function f() { var j=i; return +j } return f"); +assertAsmTypeFail('global', 'imp', USE_ASM + "const i=imp.i|0; function f() { var j=i; return j|0 } return f"); +assertAsmTypeFail('global', 'imp', USE_ASM + "const i=+imp.i; function f() { var j=i; return +j } return f"); +assertAsmTypeFail('global', 'imp', 'heap', USE_ASM + "var i=new global.Float32Array(heap); function f() { var j=i; return +j } return f"); + +assertAsmTypeFail('global', USE_ASM + "var i=global; function f() { return i|0 } return f"); +assertAsmTypeFail('global', USE_ASM + "const i=global; function f() { return i|0 } return f"); +assertAsmTypeFail('global', USE_ASM + "var i=global|0; function f() { return i|0 } return f"); +assertAsmTypeFail('global', USE_ASM + "const i=global|0; function f() { return i|0 } return f"); +assertAsmTypeFail('global', USE_ASM + "var j=0;var i=j.i|0; function f() { return i|0 } return f"); +assertAsmTypeFail('global', USE_ASM + "var i=global.i|0; function f() { return i|0 } return f"); +assertAsmTypeFail('global', USE_ASM + "const i=global.i|0; function f() { return i|0 } return f"); +assertAsmTypeFail('global', USE_ASM + "var i=global.i|0; function f() { return i|0 } return f"); +assertAsmTypeFail('global', USE_ASM + 'var i=global.Infinity; function f() { i = 0.0 } return f'); +assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), undefined); +assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), undefined); +assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), null); +assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), null); +assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), 3); +assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {}); +assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:NaN}); +assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:-Infinity}); +assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:Infinity})(), Infinity); +assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), {Infinity:Infinity})(), Infinity); +assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), this)(), Infinity); +assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), this)(), Infinity); +assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), undefined); +assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), null); +assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), 3); +assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {}); +assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {Infinity:Infinity}); +assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {Infinity:-Infinity}); +assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {NaN:NaN})(), NaN); +assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.NaN; function f() { return +i } return f'), {NaN:NaN})(), NaN); +assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), this)(), NaN); +assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.NaN; function f() { return +i } return f'), this)(), NaN); + +assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'var t = new glob.Int32Array(buf); function f() {} return f'), {get Int32Array(){return Int32Array}}, null, new ArrayBuffer(4096)) +assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'const t = new glob.Int32Array(buf); function f() {} return f'), {get Int32Array(){return Int32Array}}, null, new ArrayBuffer(4096)) +assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'var t = new glob.Int32Array(buf); function f() {} return f'), new Proxy(this, {}), null, new ArrayBuffer(4096)) +assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'const t = new glob.Int32Array(buf); function f() {} return f'), new Proxy(this, {}), null, new ArrayBuffer(4096)) +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), {get Math(){return Math}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), new Proxy(this, {})); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), {Math:{get sin(){return Math.sin}}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), {Math:new Proxy(Math, {})}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Infinity; function f() {} return f'), {get Infinity(){return Infinity}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Infinity; function f() {} return f'), new Proxy(this, {})); +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() {} return f'), null, {get x(){return 42}}) +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() {} return f'), null, {get x(){return 42}}) +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() {} return f'), null, new Proxy({x:42}, {})); +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() {} return f'), null, new Proxy({x:42}, {})); +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x; function f() {} return f'), null, {get x(){return function(){}}}) +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x; function f() {} return f'), null, new Proxy({x:function(){}}, {})); +assertAsmTypeFail('global', 'imp', USE_ASM + "var i=imp; function f() { return i|0 } return f"); +assertAsmTypeFail('global', 'imp', USE_ASM + "var j=0;var i=j.i|0; function f() { return i|0 } return f"); +assertAsmLinkAlwaysFail(asmCompile('global','imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), null, undefined); +assertAsmLinkAlwaysFail(asmCompile('global','imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), this, undefined); +assertAsmLinkAlwaysFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), null, null); +assertAsmLinkAlwaysFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), this, null); +assertAsmLinkFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), this, 42); +assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f")(null, {i:42})), 42); +assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=imp.i|0; function f() { return i|0 } return f")(null, {i:42})), 42); +assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f")(null, {i:1.4})), 1); +assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=imp.i|0; function f() { return i|0 } return f")(null, {i:1.4})), 1); +assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=+imp.i; function f() { return +i } return f")(null, {i:42})), 42); +assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function f() { return +i } return f")(null, {i:42})), 42); +assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4); +assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4); +assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var i=42; while (1) { break; } g = i; return g|0 } return f"))(), 42); +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() {} return f'), null, {x:{valueOf:function() { return 42 }}}); +assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() {} return f'), null, {x:{valueOf:function() { return 42 }}}); +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f'), null, {x:"blah"})(), 0); +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() { return +i} return f'), null, {x:"blah"})(), NaN); +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f'), this, {x:"blah"})(), NaN); +assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f')(null, {x:Symbol("blah")}), TypeError); +assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = +foreign.x; function f() { return +i} return f')(null, {x:Symbol("blah")}), TypeError); +assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f')(this, {x:Symbol("blah")}), TypeError); + +// Temporary workaround; this test can be removed when Emscripten is fixed and +// the fix has propagated out to most apps: +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.i|0; function f() { return i|0} return f'), null, {i:function(){}})(), 0); +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.i; function f() { return +i} return f'), null, {i:function(){}})(), NaN); +assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.i); function f() { return +i} return f'), this, {i:function(){}})(), NaN); +var module = asmCompile('glob','foreign', USE_ASM + 'var i = foreign.i|0; function f() { return i|0} return f'); +var fun = function() {} +fun.valueOf = function() {} +assertAsmLinkFail(module, null, {i:fun}); +var fun = function() {} +fun.toString = function() {} +assertAsmLinkFail(module, null, {i:fun}); +var fun = function() {} +var origFunToString = Function.prototype.toString; +Function.prototype.toString = function() {} +assertAsmLinkFail(module, null, {i:fun}); +Function.prototype.toString = origFunToString; +assertEq(asmLink(module, null, {i:fun})(), 0); +Function.prototype.valueOf = function() {} +assertAsmLinkFail(module, null, {i:fun}); +delete Function.prototype.valueOf; +assertEq(asmLink(module, null, {i:fun})(), 0); +var origObjValueOf = Object.prototype.valueOf; +Object.prototype.valueOf = function() {} +assertAsmLinkFail(module, null, {i:fun}); +Object.prototype.valueOf = origObjValueOf; +assertEq(asmLink(module, null, {i:fun})(), 0); +Object.prototype.toString = function() {} +assertEq(asmLink(module, null, {i:fun})(), 0); + +var f1 = asmCompile('global', 'foreign', 'heap', USE_ASM + 'var i32 = new global.Int32Array(heap); function g() { return i32[4]|0 } return g'); +var global = this; +var ab = new ArrayBuffer(4096); +var p = new Proxy(global, + {has:function(name) { f1(global, null, ab); return true}, + getOwnPropertyDescriptor:function(name) { return {configurable:true, value:Int32Array}}}); +new Int32Array(ab)[4] = 42; +assertEq(f1(p, null, ab)(), 42); + +// GVN checks +assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var x = 0; g = 1; x = g; return (x+g)|0 } return f"))(), 2); +assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var x = 0; g = 1; x = g; g = 2; return (x+g)|0 } return f"))(), 3); +assertEq(asmLink(asmCompile(USE_ASM + "var g=0; var h=0; function f() { var x = 0; g = 1; x = g; h = 3; return (x+g)|0 } return f"))(), 2); diff --git a/js/src/jit-test/tests/asm.js/testHeapAccess.js b/js/src/jit-test/tests/asm.js/testHeapAccess.js new file mode 100644 index 000000000..d5c69082f --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testHeapAccess.js @@ -0,0 +1,515 @@ +load(libdir + "asm.js"); + +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[0>>2] = 4.0; return i32[0>>2]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[0>>2] = 4; return +f32[0>>2]; } return f'); + +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { var x=0,y=0; return i8[x+y]|0 } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { var x=0,y=0; return u8[x+y]|0 } return f'); + +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0>>0]|0 }; return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0>>1]|0 }; return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0>>4]|0 }; return f'); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0]|0 }; return f'), this, null, new ArrayBuffer(BUF_MIN))(), 0); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>2]|0; return i|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0), 0); + +setCachingEnabled(true); + +// In order to allow following tests work on both big-endian and little- +// endian architectures we need to define least significant byte (lsb) and +// least significant word (lsw). +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[0]|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +var lsb=0; +var lsw=0 +if (f(0x12345678) == 0x12) { + lsb=3; + lsw=1; +} + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0),0); +assertEq(f(0x7f),0x7f); +assertEq(f(0xff),-1); +assertEq(f(0x100),0); + +{ + var buf = new ArrayBuffer(BUF_MIN); + var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + '/* not a clone */ function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f'); + var f = asmLink(code, this, null, buf); + assertEq(f(0),0); + assertEq(f(0x7f),0x7f); + assertEq(f(0xff),-1); + assertEq(f(0x100),0); + + // Bug 1088655 + assertEq(asmLink(asmCompile('stdlib', 'foreign', 'heap', USE_ASM + 'var i32=new stdlib.Int32Array(heap); function f(i) {i=i|0;var j=0x10000;return (i32[j>>2] = i)|0 } return f'), this, null, buf)(1), 1); +} + +setCachingEnabled(false); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[' + lsb + ']|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +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) {i=i|0; i32[0] = i; return i16[' + lsw + ']|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0),0); +assertEq(f(0x7fff),0x7fff); +assertEq(f(0xffff),-1); +assertEq(f(0x10000),0); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u16[' + lsw + ']|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0),0); +assertEq(f(0x7fff),0x7fff); +assertEq(f(0xffff),0xffff); +assertEq(f(0x10000),0); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i32[0]|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0),0); +assertEq(f(0x7fffffff),0x7fffffff); +assertEq(f(0xffffffff),-1); +assertEq(f(0x100000000),0); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u32[0]|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0),0); +assertEq(f(0x7fffffff),0x7fffffff); +assertEq(f(0xffffffff),-1); +assertEq(f(0x100000000),0); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0),0); +assertEq(f(0x7f),0x7f); +assertEq(f(0xff),-1); +assertEq(f(0x100),0); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[' + lsb + ']|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +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) {i=i|0; i8[0] = i; return i8[0]|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0),0); +assertEq(f(0x7f),0x7f); +assertEq(f(0xff),-1); +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(BUF_MIN)); +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(BUF_MIN)); +assertEq(f(0, 1.3), 1); +assertEq(f(BUF_MIN-8, 2.5), 2); +assertEq(f(BUF_MIN, 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])|0}; return f'); +var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); +assertEq(f(0, 1.3), 1); +assertEq(f(BUF_MIN-8, 2.5), 2); +assertEq(f(BUF_MIN, 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(BUF_MIN)); +assertEq(f(0, 1.3), 1.3); +assertEq(f(BUF_MIN-8, 2.5), 2.5); +assertEq(f(BUF_MIN, 3.8), NaN); + +var i32 = new Int32Array(BUF_MIN); +i32[0] = 42; +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[1] = i32[0] }; return f'), this, null, i32.buffer)(); +assertEq(i32[1], 42); + +var f64 = new Float64Array(BUF_MIN); +f64[0] = 42; +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[1] = f64[0] }; return f'), this, null, f64.buffer)(); +assertEq(f64[1], 42); + +var i32 = new Int32Array(BUF_MIN/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); +assertEq(f(1), 0xfffeeee); +var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[(i<<1)>>2]|0 }; return f'), this, null, i32.buffer); +assertEq(f(0), 13); +assertEq(f(1), 13); +assertEq(f(2), 0xfffeeee); +assertEq(f(3), 0xfffeeee); + +var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[(i<<2)>>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)+4)>>2]|0 }; return f'), this, null, i32.buffer); +assertEq(f(0), 0xfffeeee); + +// For legacy compatibility, test Int8/Uint8 accesses with no shift. +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[7&0xffff] = 41 } return f'), this, null, BUF_64KB)(); +assertEq(new Uint8Array(BUF_64KB)[7], 41); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[7&0xffff] = -41 } return f'), this, null, BUF_64KB)(); +assertEq(new Int8Array(BUF_64KB)[7], -41); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[(7&0xffff)>>0] = 41 } return f'), this, null, BUF_64KB)(); +assertEq(new Uint8Array(BUF_64KB)[7], 41); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[(7&0xffff)>>0] = -41 } return f'), this, null, BUF_64KB)(); +assertEq(new Int8Array(BUF_64KB)[7], -41); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[(6&0xffff)>>1] = 0xabc } return f'), this, null, BUF_64KB)(); +assertEq(new Uint16Array(BUF_64KB)[3], 0xabc); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[(6&0xffff)>>1] = -0xabc } return f'), this, null, BUF_64KB)(); +assertEq(new Int16Array(BUF_64KB)[3], -0xabc); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[(4&0xffff)>>2] = 0xabcde } return f'), this, null, BUF_64KB)(); +assertEq(new Uint32Array(BUF_64KB)[1], 0xabcde); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[(4&0xffff)>>2] = -0xabcde } return f'), this, null, BUF_64KB)(); +assertEq(new Int32Array(BUF_64KB)[1], -0xabcde); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[(4&0xffff)>>2] = 1.0 } return f'), this, null, BUF_64KB)(); +assertEq(new Float32Array(BUF_64KB)[1], 1.0); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[(8&0xffff)>>3] = 1.3 } return f'), this, null, BUF_64KB)(); +assertEq(new Float64Array(BUF_64KB)[1], 1.3); + +new Float32Array(BUF_64KB)[1] = 1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[(4&0xffff)>>2] } return f'), this, null, BUF_64KB)(), 1.0); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'var toFloat32 = glob.Math.fround; function f() { return toFloat32(f32[(4&0xffff)>>2]) } return f'), this, null, BUF_64KB)(), 1.0); +new Float64Array(BUF_64KB)[1] = 1.3; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[(8&0xffff)>>3] } return f'), this, null, BUF_64KB)(), 1.3); + +asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u8[255]; u8[i] } return f'); +// For legacy compatibility, test Int8/Uint8 accesses with no shift. +asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u8[i&0xff]; u8[255] } return f'); +asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u8[(i&0xff)>>0]; u8[255] } return f'); +asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u32[63]; u32[i>>2] } return f'); +asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u32[i>>2]; u32[63] } return f'); + +var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u32[64] } return f'); +asmLink(code, this, null, new ArrayBuffer(BUF_MIN)); + +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u32[12] = i } return f'), this, null, BUF_64KB)(11); +assertEq(new Int32Array(BUF_64KB)[12], 11); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[12]|0 } return f'), this, null, BUF_64KB)(), 11); +new Float64Array(BUF_64KB)[0] = 3.5; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +-f64[0] } return f'), this, null, BUF_64KB)(), -3.5); + +// Test constant loads. +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[1] = -1 } return f'), this, null, buf)(); +assertEq(new Uint8Array(buf)[0], 0); +assertEq(new Uint8Array(buf)[1], 255); +assertEq(new Uint8Array(buf)[2], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[4095] = -1 } return f'), this, null, buf)(); +assertEq(new Uint8Array(buf)[4094], 0); +assertEq(new Uint8Array(buf)[4095], 255); +assertEq(new Uint8Array(buf)[4096], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[4096] = -1 } return f'), this, null, buf)(); +assertEq(new Uint8Array(buf)[4095], 0); +assertEq(new Uint8Array(buf)[4096], 255); +assertEq(new Uint8Array(buf)[4097], 0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[' + BUF_MIN + '] = -1 } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[258048] = -1 } return f'), this, null, buf)(); +assertEq(new Uint8Array(buf)[258047], 0); +assertEq(new Uint8Array(buf)[258048], 255); +assertEq(new Uint8Array(buf)[258049], 0); + +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[1] = -1 } return f'), this, null, buf)(); +assertEq(new Int8Array(buf)[0], 0); +assertEq(new Int8Array(buf)[1], -1); +assertEq(new Int8Array(buf)[2], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[4095] = -1 } return f'), this, null, buf)(); +assertEq(new Int8Array(buf)[4094], 0); +assertEq(new Int8Array(buf)[4095], -1); +assertEq(new Int8Array(buf)[4096], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[4096] = -1 } return f'), this, null, buf)(); +assertEq(new Int8Array(buf)[4095], 0); +assertEq(new Int8Array(buf)[4096], -1); +assertEq(new Int8Array(buf)[4097], 0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[' + BUF_MIN + '] = -1 } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[258048] = -1 } return f'), this, null, buf)(); +assertEq(new Int8Array(buf)[258047], 0); +assertEq(new Int8Array(buf)[258048], -1); +assertEq(new Int8Array(buf)[258049], 0); + +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[1] = -1 } return f'), this, null, buf)(); +assertEq(new Uint16Array(buf)[0], 0); +assertEq(new Uint16Array(buf)[1], 65535); +assertEq(new Uint16Array(buf)[2], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[' + (BUF_MIN/2-1) + '] = -1 } return f'), this, null, buf)(); +assertEq(new Uint16Array(buf)[BUF_MIN/2-2], 0); +assertEq(new Uint16Array(buf)[BUF_MIN/2-1], 65535); +assertEq(new Uint16Array(buf)[BUF_MIN/2], undefined); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[' + (BUF_MIN/4) + '] = -1 } return f'), this, null, buf)(); +assertEq(new Uint16Array(buf)[BUF_MIN/4-1], 0); +assertEq(new Uint16Array(buf)[BUF_MIN/4], 65535); +assertEq(new Uint16Array(buf)[BUF_MIN/4+1], 0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[' + (BUF_MIN/2) + '] = -1 } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[126976] = -1 } return f'), this, null, buf)(); +assertEq(new Uint16Array(buf)[126975], 0); +assertEq(new Uint16Array(buf)[126976], 65535); +assertEq(new Uint16Array(buf)[126977], 0); + +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[1] = -1 } return f'), this, null, buf)(); +assertEq(new Int16Array(buf)[0], 0); +assertEq(new Int16Array(buf)[1], -1); +assertEq(new Int16Array(buf)[2], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[' + (BUF_MIN/2-1) + '] = -1 } return f'), this, null, buf)(); +assertEq(new Int16Array(buf)[BUF_MIN/2-2], 0); +assertEq(new Int16Array(buf)[BUF_MIN/2-1], -1); +assertEq(new Int16Array(buf)[BUF_MIN/2], undefined); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[' + (BUF_MIN/4) + '] = -1 } return f'), this, null, buf)(); +assertEq(new Int16Array(buf)[BUF_MIN/4-1], 0); +assertEq(new Int16Array(buf)[BUF_MIN/4], -1); +assertEq(new Int16Array(buf)[BUF_MIN/4+1], 0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[' + (BUF_MIN/2) + '] = -1 } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[126976] = -1 } return f'), this, null, buf)(); +assertEq(new Int16Array(buf)[126975], 0); +assertEq(new Int16Array(buf)[126976], -1); +assertEq(new Int16Array(buf)[126977], 0); + +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[1] = -1 } return f'), this, null, buf)(); +assertEq(new Uint32Array(buf)[0], 0); +assertEq(new Uint32Array(buf)[1], 4294967295); +assertEq(new Uint32Array(buf)[2], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[' + (BUF_MIN/4-1) + '] = -1 } return f'), this, null, buf)(); +assertEq(new Uint32Array(buf)[BUF_MIN/4-2], 0); +assertEq(new Uint32Array(buf)[BUF_MIN/4-1], 4294967295); +assertEq(new Uint32Array(buf)[BUF_MIN/4], undefined); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[' + (BUF_MIN/8) + '] = -1 } return f'), this, null, buf)(); +assertEq(new Uint32Array(buf)[BUF_MIN/8-1], 0); +assertEq(new Uint32Array(buf)[BUF_MIN/8], 4294967295); +assertEq(new Uint32Array(buf)[BUF_MIN/8+1], 0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[' + (BUF_MIN/4) + '] = -1 } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[61440] = -1 } return f'), this, null, buf)(); +assertEq(new Uint32Array(buf)[61439], 0); +assertEq(new Uint32Array(buf)[61440], 4294967295); +assertEq(new Uint32Array(buf)[61441], 0); + +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[1] = -1 } return f'), this, null, buf)(); +assertEq(new Int32Array(buf)[0], 0); +assertEq(new Int32Array(buf)[1], -1); +assertEq(new Int32Array(buf)[2], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[' + (BUF_MIN/4-1) + '] = -1 } return f'), this, null, buf)(); +assertEq(new Int32Array(buf)[BUF_MIN/4-2], 0); +assertEq(new Int32Array(buf)[BUF_MIN/4-1], -1); +assertEq(new Int32Array(buf)[BUF_MIN/4], undefined); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[' + (BUF_MIN/8) + '] = -1 } return f'), this, null, buf)(); +assertEq(new Int32Array(buf)[BUF_MIN/8-1], 0); +assertEq(new Int32Array(buf)[BUF_MIN/8], -1); +assertEq(new Int32Array(buf)[BUF_MIN/8+1], 0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[' + (BUF_MIN/4) + '] = -1 } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[61440] = -1 } return f'), this, null, buf)(); +assertEq(new Int32Array(buf)[61439], 0); +assertEq(new Int32Array(buf)[61440], -1); +assertEq(new Int32Array(buf)[61441], 0); + +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[1] = -1.0 } return f'), this, null, buf)(); +assertEq(new Int32Array(buf)[0], 0); +assertEq(new Float32Array(buf)[1], -1.0); +assertEq(new Int32Array(buf)[2], 0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[' + (BUF_MIN/4-1) + '] = -1.0 } return f'), this, null, buf)(); +assertEq(new Int32Array(buf)[BUF_MIN/4-2], 0); +assertEq(new Float32Array(buf)[BUF_MIN/4-1], -1.0); +assertEq(new Int32Array(buf)[BUF_MIN/4], undefined); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[' + (BUF_MIN/8) + '] = -1.0 } return f'), this, null, buf)(); +assertEq(new Int32Array(buf)[BUF_MIN/8-1], 0); +assertEq(new Float32Array(buf)[BUF_MIN/8], -1.0); +assertEq(new Int32Array(buf)[BUF_MIN/8+1], 0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[' + (BUF_MIN/4) + '] = -1.0 } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[61440] = -1.0 } return f'), this, null, buf)(); +assertEq(new Float32Array(buf)[61439], 0.0); +assertEq(new Float32Array(buf)[61440], -1.0); +assertEq(new Float32Array(buf)[61441], 0.0); + +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[1] = -1.0 } return f'), this, null, buf)(); +assertEq(new Float64Array(buf)[0], 0.0); +assertEq(new Float64Array(buf)[1], -1.0); +assertEq(new Float64Array(buf)[2], 0.0); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[' + (BUF_MIN/8-1) + '] = -1.0 } return f'), this, null, buf)(); +assertEq(new Float64Array(buf)[BUF_MIN/8-2], 0.0); +assertEq(new Float64Array(buf)[BUF_MIN/8-1], -1.0); +assertEq(new Float64Array(buf)[BUF_MIN/8], undefined); +var buf = new ArrayBuffer(BUF_MIN); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[' + (BUF_MIN/16) + '] = -1.0 } return f'), this, null, buf)(); +assertEq(new Float64Array(buf)[BUF_MIN/16-1], 0.0); +assertEq(new Float64Array(buf)[BUF_MIN/16], -1.0); +assertEq(new Float64Array(buf)[BUF_MIN/16+1], 0.0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[' + (BUF_MIN/8) + '] = -1.0 } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[28672] = -1.0 } return f'), this, null, buf)(); +assertEq(new Float64Array(buf)[28671], 0.0); +assertEq(new Float64Array(buf)[28672], -1.0); +assertEq(new Float64Array(buf)[28673], 0.0); + + +var buf = new ArrayBuffer(BUF_MIN); +new Uint8Array(buf)[1] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[1]|0; } return f'), this, null, buf)(),255); +new Int8Array(buf)[1] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i8[1]|0; } return f'), this, null, buf)(),-1); +var buf = new ArrayBuffer(262144); +new Uint8Array(buf)[126976] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[126976]|0; } return f'), this, null, buf)(),255); +new Int8Array(buf)[126976] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i8[126976]|0; } return f'), this, null, buf)(),-1); + +var buf = new ArrayBuffer(BUF_MIN); +new Uint16Array(buf)[1] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u16[1]|0; } return f'), this, null, buf)(),65535); +new Int16Array(buf)[1] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i16[1]|0; } return f'), this, null, buf)(),-1); +var buf = new ArrayBuffer(262144); +new Uint16Array(buf)[126976] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u16[126976]|0; } return f'), this, null, buf)(),65535); +new Int16Array(buf)[126976] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i16[126976]|0; } return f'), this, null, buf)(),-1); + +var buf = new ArrayBuffer(BUF_MIN); +new Uint32Array(buf)[1] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[1]|0; } return f'), this, null, buf)(),-1); +new Int32Array(buf)[1] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[1]|0; } return f'), this, null, buf)(),-1); +var buf = new ArrayBuffer(262144); +new Int32Array(buf)[61440] = -1; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[61440]|0; } return f'), this, null, buf)(),-1); + +var buf = new ArrayBuffer(BUF_MIN); +new Float32Array(buf)[1] = -1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[1]; } return f'), this, null, buf)(),-1.0); +new Float32Array(buf)[BUF_MIN/4-1] = -1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[' + (BUF_MIN/4-1) + ']; } return f'), this, null, buf)(),-1.0); +new Float32Array(buf)[BUF_MIN/8] = -1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[' + (BUF_MIN/8) + ']; } return f'), this, null, buf)(),-1.0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[' + (BUF_MIN/4) + ']; } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +new Float32Array(buf)[61440] = -1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[61440]; } return f'), this, null, buf)(),-1.0); + +var buf = new ArrayBuffer(BUF_MIN); +new Float64Array(buf)[1] = -1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[1]; } return f'), this, null, buf)(),-1.0); +new Float64Array(buf)[BUF_MIN/8-1] = -1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[' + (BUF_MIN/8-1) + ']; } return f'), this, null, buf)(),-1.0); +new Float64Array(buf)[BUF_MIN/16] = -1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[' + (BUF_MIN/16) + ']; } return f'), this, null, buf)(),-1.0); +assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[' + (BUF_MIN/8) + ']; } return f'), this, null, buf); +var buf = new ArrayBuffer(262144); +new Float64Array(buf)[28672] = -1.0; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[28672]; } return f'), this, null, buf)(),-1.0); + +// Bug 913867 +var buf = new ArrayBuffer(BUF_MIN); +new Int32Array(buf)[0] = 0x55aa5a5a; +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f1() { i32[0] = 1; return 8; }; function f() { return i32[((f1()|0)&0)>>2]|0; } return f'), this, null, buf)(),1); +assertEq(new Int32Array(buf)[0], 1); + +// Bug 882012 +assertEq(asmLink(asmCompile('stdlib', 'foreign', 'heap', USE_ASM + "var id=foreign.id;var doubles=new stdlib.Float64Array(heap);function g(){doubles[0]=+id(2.0);return +doubles[0];}return g"), this, {id: function(x){return x;}}, BUF_64KB)(), 2.0); + +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[4294967295]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u8[i]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-1]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u8[i]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x80000000]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u8[i]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-2147483648]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u8[i]|0; } return f'); + +// GVN checks +var buf = new ArrayBuffer(BUF_MIN); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'var i=0; function f() { var x = 0, y = 0; u8[0] = 1; u8[1] = 2; x = 0|u8[i]; i = x; y = 0|u8[i]; return y|0;} return f'), this, null, buf)(),2); +assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'var i=0; function f() { var x = 0, y = 0; u8[0] = 1; u8[1] = 2; x = 0|u8[i]; y = 0|u8[i]; return (x+y)|0;} return f'), this, null, buf)(),2); + +// Heap length constraints +var m = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f'); +assertAsmLinkAlwaysFail(m, this, null, new ArrayBuffer(0xffff)); +assertEq(asmLink(m, this, null, new ArrayBuffer(0x10000))(0),0); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0x10010)); +assertEq(asmLink(m, this, null, new ArrayBuffer(0x20000))(0),0); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0xfe0000)); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0xfe0010)); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0xfe0000)); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0xff8000)); +var buf = new ArrayBuffer(0x100000); +new Uint8Array(buf)[0x4242] = 0xAA; +var f = asmLink(m, this, null, buf); +assertEq(f(0),0); +assertEq(f(0x4242),0xAA); +assertEq(f(0x100000),0); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0x104000)); +assertEq(asmLink(m, this, null, new ArrayBuffer(0x200000))(0),0); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0x3f8000)); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0x3fe000)); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0x3fc000)); +assertEq(asmLink(m, this, null, new ArrayBuffer(0x400000))(0),0); +assertAsmLinkFail(m, this, null, new ArrayBuffer(0x410000)); +assertEq(asmLink(m, this, null, new ArrayBuffer(0x800000))(0),0); +var buf = new ArrayBuffer(0x1000000); +new Uint8Array(buf)[0x424242] = 0xAA; +var f = asmLink(m, this, null, buf); +assertEq(f(0),0); +assertEq(f(0x424242),0xAA); +assertEq(f(0x1000000),0); +assertEq(asmLink(m, this, null, new ArrayBuffer(0x2000000))(0),0); +assertEq(asmLink(m, this, null, new ArrayBuffer(0x3000000))(0),0); + +// Heap offsets +var asmMod = function test (glob, env, b) { + 'use asm'; + var i8 = new glob.Int8Array(b); + function f(i) { + i = i | 0; + i = i & 1; + i = (i - 0x40000)|0; + i8[0x3ffff] = 0; + return i8[(i + 0x7fffe) >> 0] | 0; + } + return f; +}; +var buffer = new ArrayBuffer(0x40000); +var asm = asmMod(this, {}, buffer); +assertEq(asm(-1),0); diff --git a/js/src/jit-test/tests/asm.js/testJumpRange.js b/js/src/jit-test/tests/asm.js/testJumpRange.js new file mode 100644 index 000000000..bd983544b --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testJumpRange.js @@ -0,0 +1,46 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +var fatFunc = USE_ASM + '\n'; +for (var i = 0; i < 100; i++) + fatFunc += "function f" + i + "() { return ((f" + (i+1) + "()|0)+1)|0 }\n"; +fatFunc += "function f100() { return 42 }\n"; +fatFunc += "return f0"; + +for (let threshold of [0, 50, 100, 5000, -1]) { + setJitCompilerOption("jump-threshold", threshold); + + assertEq(asmCompile( + USE_ASM + ` + function h() { return ((g()|0)+2)|0 } + function g() { return ((f()|0)+1)|0 } + function f() { return 42 } + return h + `)()(), 45); + + if (isSimdAvailable() && this.SIMD) { + var buf = new ArrayBuffer(BUF_MIN); + new Int32Array(buf)[0] = 10; + new Float32Array(buf)[1] = 42; + assertEq(asmCompile('stdlib', 'ffis', 'buf', + USE_ASM + ` + var H = new stdlib.Uint8Array(buf); + var i4 = stdlib.SIMD.Int32x4; + var f4 = stdlib.SIMD.Float32x4; + var i4load = i4.load; + var f4load = f4.load; + var toi4 = i4.fromFloat32x4; + var i4ext = i4.extractLane; + function f(i) { i=i|0; return i4ext(i4load(H, i), 0)|0 } + function g(i) { i=i|0; return (i4ext(toi4(f4load(H, i)),1) + (f(i)|0))|0 } + function h(i) { i=i|0; return g(i)|0 } + return h + `)(this, null, buf)(0), 52); + } + + enableSPSProfiling(); + asmLink(asmCompile(USE_ASM + 'function f() {} function g() { f() } function h() { g() } return h'))(); + disableSPSProfiling(); + + assertEq(asmCompile(fatFunc)()(), 142); +} diff --git a/js/src/jit-test/tests/asm.js/testLinkErrorAssert.js b/js/src/jit-test/tests/asm.js/testLinkErrorAssert.js new file mode 100644 index 000000000..9084d72a2 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testLinkErrorAssert.js @@ -0,0 +1,20 @@ +// This test should not assert. + +function asmModule(g, foreign, heap) { + "use asm"; + let HEAP8 = new g.Int8Array(heap); + + function f() { return 99; } + return {f: f}; +} + +// linking error +let m = asmModule(this, 2, new ArrayBuffer(4095)); + +print(m.f()); + +// linking error +let m2 = asmModule(this, 2, new ArrayBuffer(2048)); + +print(m2.f()); + diff --git a/js/src/jit-test/tests/asm.js/testLiterals.js b/js/src/jit-test/tests/asm.js/testLiterals.js new file mode 100644 index 000000000..1a24002af --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testLiterals.js @@ -0,0 +1,50 @@ +load(libdir + 'asm.js'); + +assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=0; e=d; return +e } return f'); +assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=1e1; e=d; return +e } return f'); +assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=+0; e=d; return +e } return f'); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var e=-0; return +e } return f'))(-0), -0); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var e=-0.0; return +e } return f'))(-0), -0); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=0.0; e=d; return +e } return f'))(0.1), 0.1); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-0.0; e=d; return +e } return f'))(0.1), 0.1); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=10.0; e=d; return +e } return f'))(0.1), 0.1); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-10.0; e=d; return +e } return f'))(0.1), 0.1); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=1.0e2; e=d; return +e } return f'))(0.1), 0.1); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-1.0e2; e=d; return +e } return f'))(0.1), 0.1); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=1.0e0; e=d; return +e } return f'))(0.1), 0.1); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-1.0e0; e=d; return +e } return f'))(0.1), 0.1); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 0.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), 0); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return -0.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), -0); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 10.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), 10); +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"); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=1e0; j=i; return j|0 } return f"))(42), 42); +assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=1e9; j=i; return j|0 } return f"))(42), 42); + +assertAsmTypeFail(USE_ASM + 'function f() { var i=-2147483649; return i|0 } return f'); +assertAsmTypeFail(USE_ASM + 'function f() { var i=4294967296; return i|0 } return f'); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var i=-2147483648; return i|0 } return f'))(), -2147483648); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var i=4294967295; return i|0 } return f'))(), 4294967295|0); +assertAsmTypeFail(USE_ASM + 'function f(i) { i=i|0; return (i+-2147483649)|0 } return f'); +assertAsmTypeFail(USE_ASM + 'function f(i) { i=i|0; return (i+4294967296)|0 } return f'); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { i=i|0; return (i+-2147483648)|0 } return f'))(0), -2147483648); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { i=i|0; return (i+4294967295)|0 } return f'))(0), 4294967295|0); + +assertAsmTypeFail(USE_ASM + 'var i=-2147483649; function f() { return i|0 } return f'); +assertAsmTypeFail(USE_ASM + 'const i=-2147483649; function f() { return i|0 } return f'); +assertAsmTypeFail(USE_ASM + 'var i=4294967296; function f() { return i|0 } return f'); +assertAsmTypeFail(USE_ASM + 'const i=4294967296; function f() { return i|0 } return f'); +assertEq(asmLink(asmCompile(USE_ASM + 'var i=-2147483648; function f() { return i|0 } return f'))(), -2147483648); +assertEq(asmLink(asmCompile(USE_ASM + 'const i=-2147483648; function f() { return i|0 } return f'))(), -2147483648); +assertEq(asmLink(asmCompile(USE_ASM + 'var i=4294967295; function f() { return i|0 } return f'))(), 4294967295|0); +assertEq(asmLink(asmCompile(USE_ASM + 'const i=4294967295; function f() { return i|0 } return f'))(), 4294967295|0); diff --git a/js/src/jit-test/tests/asm.js/testMathLib.js b/js/src/jit-test/tests/asm.js/testMathLib.js new file mode 100644 index 000000000..5c2eb9db4 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testMathLib.js @@ -0,0 +1,189 @@ +load(libdir + "asm.js"); + +function testUnary(f, g) { + var numbers = [NaN, Infinity, -Infinity, -10000, -3.4, -0, 0, 3.4, 10000]; + for (n of numbers) + assertEq(f(n), g(n)); +} + +const FROUND = 'var fround=glob.Math.fround;'; + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sin}}), Math.sin); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'const sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sin}}), Math.sin); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var co=glob.Math.cos; function f(d) { d=+d; return +co(d) } return f'), {Math:{cos:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var co=glob.Math.cos; function f(d) { d=+d; return +co(d) } return f'), {Math:{cos:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var co=glob.Math.cos; function f(d) { d=+d; return +co(d) } return f'), {Math:{cos:Math.cos}}), Math.cos); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ta=glob.Math.tan; function f(d) { d=+d; return +ta(d) } return f'), {Math:{tan:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ta=glob.Math.tan; function f(d) { d=+d; return +ta(d) } return f'), {Math:{tan:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var ta=glob.Math.tan; function f(d) { d=+d; return +ta(d) } return f'), {Math:{tan:Math.tan}}), Math.tan); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var as=glob.Math.asin; function f(d) { d=+d; return +as(d) } return f'), {Math:{asin:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var as=glob.Math.asin; function f(d) { d=+d; return +as(d) } return f'), {Math:{asin:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var as=glob.Math.asin; function f(d) { d=+d; return +as(d) } return f'), {Math:{asin:Math.asin}}), Math.asin); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ac=glob.Math.acos; function f(d) { d=+d; return +ac(d) } return f'), {Math:{acos:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ac=glob.Math.acos; function f(d) { d=+d; return +ac(d) } return f'), {Math:{acos:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var ac=glob.Math.acos; function f(d) { d=+d; return +ac(d) } return f'), {Math:{acos:Math.acos}}), Math.acos); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan; function f(d) { d=+d; return +at(d) } return f'), {Math:{atan:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan; function f(d) { d=+d; return +at(d) } return f'), {Math:{atan:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan; function f(d) { d=+d; return +at(d) } return f'), {Math:{atan:Math.atan}}), Math.atan); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ce=glob.Math.ceil; function f(d) { d=+d; return +ce(d) } return f'), {Math:{ceil:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ce=glob.Math.ceil; function f(d) { d=+d; return +ce(d) } return f'), {Math:{ceil:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var ce=glob.Math.ceil; function f(d) { d=+d; return +ce(d) } return f'), {Math:{ceil:Math.ceil}}), Math.ceil); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var fl=glob.Math.floor; function f(d) { d=+d; return +fl(d) } return f'), {Math:{floor:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var fl=glob.Math.floor; function f(d) { d=+d; return +fl(d) } return f'), {Math:{floor:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var fl=glob.Math.floor; function f(d) { d=+d; return +fl(d) } return f'), {Math:{floor:Math.floor}}), Math.floor); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var exq=glob.Math.exp; function f(d) { d=+d; return +exq(d) } return f'), {Math:{exp:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var exq=glob.Math.exp; function f(d) { d=+d; return +exq(d) } return f'), {Math:{exp:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var exq=glob.Math.exp; function f(d) { d=+d; return +exq(d) } return f'), {Math:{exp:Math.exp}}), Math.exp); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var lo=glob.Math.log; function f(d) { d=+d; return +lo(d) } return f'), {Math:{log:Math.sqrt}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var lo=glob.Math.log; function f(d) { d=+d; return +lo(d) } return f'), {Math:{log:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var lo=glob.Math.log; function f(d) { d=+d; return +lo(d) } return f'), {Math:{log:Math.log}}), Math.log); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sqrt; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sqrt:Math.sin}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sqrt; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sqrt:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sqrt; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sqrt:Math.sqrt}}), Math.sqrt); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; return +abs(d) } return f'), {Math:{abs:Math.sin}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; return +abs(d) } return f'), {Math:{abs:null}}); +testUnary(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; return +abs(d) } return f'), {Math:{abs:Math.abs}}), Math.abs); + +var f = asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(i) { i=i|0; return abs(i|0)|0 } return f'), this); +for (n of [-Math.pow(2,31)-1, -Math.pow(2,31), -Math.pow(2,31)+1, -1, 0, 1, Math.pow(2,31)-2, Math.pow(2,31)-1, Math.pow(2,31)]) + assertEq(f(n), Math.abs(n|0)|0); + +var f = asmLink(asmCompile('glob', USE_ASM + 'var clz32=glob.Math.clz32; function f(i) { i=i|0; return clz32(i)|0 } return f'), this); +for (n of [0, 1, 2, 15, 16, Math.pow(2,31)-1, Math.pow(2,31), Math.pow(2,31)+1, Math.pow(2,32)-1, Math.pow(2,32), Math.pow(2,32)+1]) + assertEq(f(n), Math.clz32(n|0)); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var clz32=glob.Math.clz32; function f(i, j) { i=i|0;j=j|0; return (clz32(i) < (j|0))|0 } return f'), this)(0x1, 30), 0); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var clz32=glob.Math.clz32; function f(i, j) { i=i|0;j=j|0; return (clz32(i) < (j>>>0))|0 } return f'), this)(0x1, 30), 0); + +var doubleNumbers = [NaN, Infinity, -Infinity, -10000, -3.4, -0, 0, 3.4, 10000]; +var floatNumbers = []; +for (var x of doubleNumbers) floatNumbers.push(Math.fround(x)); +var intNumbers = [-Math.pow(2,31), -10000, -3, -1, 0, 3, 10000, Math.pow(2,31), Math.pow(2,31)+1]; + +function testBinary(f, g, numbers) { + for (n of numbers) + for (o of numbers) + assertEq(f(n,o), g(n,o)); +} + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var po=glob.Math.pow; function f(d,e) { d=+d;e=+e; return +po(d,e) } return f'), {Math:{pow:Math.sin}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var po=glob.Math.pow; function f(d,e) { d=+d;e=+e; return +po(d,e) } return f'), {Math:{pow:null}}); +testBinary(asmLink(asmCompile('glob', USE_ASM + 'var po=glob.Math.pow; function f(d,e) { d=+d;e=+e; return +po(d,e) } return f'), {Math:{pow:Math.pow}}), Math.pow, doubleNumbers); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan2; function f(d,e) { d=+d;e=+e; return +at(d,e) } return f'), {Math:{atan2:Math.sin}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan2; function f(d,e) { d=+d;e=+e; return +at(d,e) } return f'), {Math:{atan2:null}}); +testBinary(asmLink(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan2; function f(d,e) { d=+d;e=+e; return +at(d,e) } return f'), {Math:{atan2:Math.atan2}}), Math.atan2, doubleNumbers); + +function coercedMin(...args) { for (var i = 0; i < args.length; i++) args[i] = args[i]|0; return Math.min(...args) } +function coercedMax(...args) { for (var i = 0; i < args.length; i++) args[i] = args[i]|0; return Math.max(...args) } +assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(d) { d=+d; return +min(d) } return f'); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + 'var i32=new glob.Int32Array(heap); var min=glob.Math.min; function f() { return min(i32[0], 5)|0 } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(x) { x=x|0; return min(3 + x, 5)|0 } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(x) { x=x|0; return min(5, 3 + x)|0 } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(x) { x=x|0; return min(x, 1)|0 } return f'); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e) { d=+d;e=+e; return +min(d,e) } return f'), {Math:{min:Math.sin}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e) { d=+d;e=+e; return +min(d,e) } return f'), {Math:{min:null}}); +testBinary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e) { d=+d;e=+e; return +min(d,e) } return f'), {Math:{min:Math.min}}), Math.min, doubleNumbers); +testBinary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; var f32=glob.Math.fround; function f(d,e) { d=f32(d);e=f32(e); return f32(min(d,e)) } return f'), this), Math.min, floatNumbers); +testBinary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e) { d=d|0;e=e|0; return min(d|0,e|0)|0} return f'), {Math:{min:Math.min}}), coercedMin, intNumbers); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e) { d=+d;e=+e; return +max(d,e) } return f'), {Math:{max:Math.sin}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e) { d=+d;e=+e; return +max(d,e) } return f'), {Math:{max:null}}); +testBinary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e) { d=+d;e=+e; return +max(d,e) } return f'), {Math:{max:Math.max}}), Math.max, doubleNumbers); +testBinary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; var f32=glob.Math.fround; function f(d,e) { d=f32(d);e=f32(e); return f32(max(d,e)) } return f'), this), Math.max, floatNumbers); +testBinary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e) { d=d|0;e=e|0; return max(d|0,e|0)|0} return f'), {Math:{max:Math.max}}), coercedMax, intNumbers); + +function testTernary(f, g, numbers) { + for (n of numbers) + for (o of numbers) + for (p of numbers) + assertEq(f(n,o,p), g(n,o,p)); +} + +assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e,g) { d=+d;e=+e;g=g|0; return +min(d,e,g) } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e,g) { d=d|0;e=e|0;g=+g; return max(d,e,g)|0 } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e,g) { d=+d;e=+e;g=+g; return min(d,e,g)|0 } return f'); +testTernary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e,g) { d=d|0;e=e|0;g=g|0; return +max(d|0,e|0,g|0) } return f'), {Math:{max:Math.max}}), coercedMax, intNumbers); +testTernary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e,g) { d=d|0;e=e|0;g=g|0; return max(d|0,e|0,g|0)|0 } return f'), {Math:{max:Math.max}}), coercedMax, intNumbers); +testTernary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e,g) { d=+d;e=+e;g=+g; return +max(d,e,g) } return f'), {Math:{max:Math.max}}), Math.max, doubleNumbers); +testTernary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; var _=glob.Math.fround; function f(d,e,g) { d=_(d);e=_(e);g=_(g); return _(max(d,e,g)) } return f'), this), Math.max, floatNumbers); +testTernary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e,g) { d=d|0;e=e|0;g=g|0; return min(d|0,e|0,g|0)|0 } return f'), {Math:{min:Math.min}}), coercedMin, intNumbers); +testTernary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e,g) { d=+d;e=+e;g=+g; return +min(d,e,g) } return f'), {Math:{min:Math.min}}), Math.min, doubleNumbers); +testTernary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; var _=glob.Math.fround; function f(d,e,g) { d=_(d);e=_(e);g=_(g); return _(min(d,e,g)) } return f'), this), Math.min, floatNumbers); + +// Implicit return coercions of math functions +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i) { i=i|0; i = im(i,i); return i|0 } return f'), this)(3), 9); +assertAsmTypeFail('glob', USE_ASM + 'var im=glob.Math.imul; function f(d) { d=+d; d = im(d, d) } return f'); +assertAsmTypeFail('glob', USE_ASM + FROUND + 'var im=glob.Math.imul; function f(d) { d=fround(d); d = im(d, d) } return f'); + +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=d|0; d = abs(d|0); return +(d>>>0) } return f'), this)(-1), 1); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=d|0; var m = 0; m = (-1)>>>0; return (abs(d|0) < (m>>>0))|0 } return f'), this)(42), 1); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; d = abs(d); return +d } return f'), this)(-1.5), 1.5); +assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var abs=glob.Math.abs; function f(d) { d=fround(d); d = fround(abs(d)); return +d } return f'), this)(-1.5), 1.5); +assertAsmTypeFail('glob', USE_ASM + FROUND + 'var abs=glob.Math.abs; function f(d) { d=fround(d); d = abs(d); return +d } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=d|0; var m = 0; m = -1; return (abs(d|0) < (m|0))|0 } return f'); + +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var sqrt=glob.Math.sqrt; function f(d) { d=+d; d = sqrt(d); return +d } return f'), this)(256), 16); +assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var sqrt=glob.Math.sqrt; function f(d) { d=fround(d); d = fround(sqrt(d)); return +d } return f'), this)(13.37), Math.fround(Math.sqrt(Math.fround(13.37)))); +assertAsmTypeFail('glob', USE_ASM + FROUND + 'var sqrt=glob.Math.sqrt; function f(d) { d=fround(d); d = sqrt(d); return fround(d) } return f'); +assertAsmTypeFail('glob', USE_ASM + FROUND + 'var sqrt=glob.Math.sqrt; function f(d) { d=fround(d); d = sqrt(d); return d } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var sqrt=glob.Math.sqrt; function f(n) { n=n|0; var d=0.; d = sqrt(n|0) } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var sqrt=glob.Math.sqrt; function f(n) { n=n|0; var d=3.; n = sqrt(d)|0 } return f'); + +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d) { d=+d; d = min(d, 13.); return +d } return f'), this)(12), 12); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d) { d=d|0; d = min(d|0, 11); return d|0 } return f'), this)(12), 11); +assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var min=glob.Math.min; function f(d) { d=fround(d); d = min(d, fround(13.37)); return fround(d) } return f'), this)(14), Math.fround(13.37)); + +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var sin=glob.Math.sin; function f(d) { d=+d; d = sin(d); return +d } return f'), this)(Math.PI), Math.sin(Math.PI)); +assertAsmTypeFail('glob', USE_ASM + FROUND + 'var sin=glob.Math.sin; function f(d) { d=fround(d); d = sin(d) } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var sin=glob.Math.sin; function f(d) { d=d|0; d = sin(d) } return f'); + +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var pow=glob.Math.pow; function f(d) { d=+d; d = pow(d,d); return +d } return f'), this)(3), 27); +assertAsmTypeFail('glob', USE_ASM + FROUND + 'var pow=glob.Math.pow; function f(d) { d=fround(d); d = pow(d, d) } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var pow=glob.Math.pow; function f(d) { d=d|0; d = pow(d, d) } return f'); + +assertAsmTypeFail('glob', USE_ASM + 'var sin=glob.Math.sin; function f(d) { d=+d; var i=0; i = sin(d)|0; } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var pow=glob.Math.pow; function f(d) { d=+d; var i=0; i = pow(d,d)|0; } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var atan2=glob.Math.atan2; function f(d) { d=+d; var i=0; i = atan2(d,d)|0; } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var sqrt=glob.Math.sqrt; function f(d) { d=+d; sqrt(d)|0; } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; abs(d)|0; } return f'); + +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i) { i=i|0; var d=0.0; d = +im(i,i); return +d } return f'), this)(42), Math.imul(42, 42)); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(i) { i=i|0; var d=0.0; d = +abs(i|0); return +d } return f'), this)(-42), 42); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(i) { i=i|0; var d=0.0; d = +min(i|0, 0); return +d } return f'), this)(-42), -42); +assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var min=glob.Math.min; function f(i) { i=i|0; var d=fround(0); d = fround(min(i|0, 0)); return +d } return f'), this)(-42), -42); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(i) { i=i|0; var d=0.0; d = +max(i|0, 0); return +d } return f'), this)(-42), 0); +assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var max=glob.Math.max; function f(i) { i=i|0; var d=fround(0); d = fround(max(i|0, 0)); return +d } return f'), this)(-42), 0); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d) { d=+d; var i=0; i = ~~min(d, 0.)|0; return i|0 } return f'), this)(-42), -42); +assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var min=glob.Math.min; function f(d) { d=fround(d); var i=0; i = ~~min(d, fround(0))|0; return i|0 } return f'), this)(-42), -42); +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d) { d=+d; var i=0; i = ~~max(d, 0.)|0; return i|0 } return f'), this)(-42), 0); +assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var max=glob.Math.max; function f(d) { d=fround(d); var i=0; i = ~~max(d, fround(0))|0; return i|0 } return f'), this)(-42), 0); + +assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(i) { i=i|0; var d=0.0; return +d; +abs(i|0); return 3.0;} return f'), this)(-42), 0); + +assertAsmTypeFail('glob', USE_ASM + 'var tau=glob.Math.TAU; function f() {} return f'); +assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { return pi | 0 } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { return +pi() } return f'); +assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { pi = +3; } return f'); +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {PI: Math.cos}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {PI: Math.SQRT2}}); + +for (var c of ['E', 'LN10', 'LN2', 'LOG2E', 'LOG10E', 'PI', 'SQRT1_2', 'SQRT2']) { + var f = asmLink(asmCompile('glob', USE_ASM + 'var x=glob.Math.' + c +'; function f() { return +x } return f'), this); + assertEq(f(), eval('Math.' + c)); +} diff --git a/js/src/jit-test/tests/asm.js/testModuleFunctions.js b/js/src/jit-test/tests/asm.js/testModuleFunctions.js new file mode 100644 index 000000000..2e3c80f45 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testModuleFunctions.js @@ -0,0 +1,41 @@ + +function testUniqueness(asmJSModule) { + var f = asmJSModule(); + var g = asmJSModule(); + assertEq(f === g, false); + f.x = 4; + assertEq(f.x, 4); + assertEq(g.x, undefined); +} + +function deffun() { + if (Math.sin) { + function inner() { "use asm"; function g() {} return g } + } + return inner; +} + +testUniqueness(deffun); + +function lambda() { + var x = function inner() { "use asm"; function g() {} return g }; + return x; +} + +testUniqueness(lambda); + +function inEval() { + eval("function inner() { 'use asm'; function g() {} return g }"); + return inner; +} + +testUniqueness(inEval); + +function inWith() { + with ({}) { + function inner() { "use asm"; function g() {} return g } + } + return inner; +} + +testUniqueness(inWith); diff --git a/js/src/jit-test/tests/asm.js/testNeuter.js b/js/src/jit-test/tests/asm.js/testNeuter.js new file mode 100644 index 000000000..e7c743bf7 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testNeuter.js @@ -0,0 +1,44 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +if (!isAsmJSCompilationAvailable()) + quit(); + +var m = asmCompile('stdlib', 'foreign', 'buffer', + `"use asm"; + var i32 = new stdlib.Int32Array(buffer); + function set(i,j) { + i=i|0; + j=j|0; + i32[i>>2] = j; + } + function get(i) { + i=i|0; + return i32[i>>2]|0 + } + return {get:get, set:set}`); + +var buffer = new ArrayBuffer(BUF_MIN); +var {get, set} = asmLink(m, this, null, buffer); +set(4, 42); +assertEq(get(4), 42); +assertThrowsInstanceOf(() => detachArrayBuffer(buffer), Error); + +var m = asmCompile('stdlib', 'foreign', 'buffer', + `"use asm"; + var i32 = new stdlib.Int32Array(buffer); + var ffi = foreign.ffi; + function inner(i) { + i=i|0; + ffi(); + return i32[i>>2]|0 + } + return inner`); + +var buffer = new ArrayBuffer(BUF_MIN); +function ffi1() +{ + assertThrowsInstanceOf(() => detachArrayBuffer(buffer), Error); +} + +var inner = asmLink(m, this, {ffi: ffi1}, buffer); diff --git a/js/src/jit-test/tests/asm.js/testParallelCompile.js b/js/src/jit-test/tests/asm.js/testParallelCompile.js new file mode 100644 index 000000000..41f879735 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testParallelCompile.js @@ -0,0 +1,26 @@ +load(libdir + "asm.js"); + +if (!isAsmJSCompilationAvailable()) + quit(); + +var module = "'use asm';\n"; +for (var i = 0; i < 100; i++) { + module += "function f" + i + "(i) {\n"; + module += " i=i|0; var j=0; j=(i+1)|0; i=(j-4)|0; i=(i+j)|0; return i|0\n"; + module += "}\n"; +} +module += "return f0"; +var script = "(function() {\n" + module + "})"; + +for (var i = 0; i < 10; i++) { + try { + offThreadCompileScript(script); + var f = new Function(module); + var g = runOffThreadScript(); + assertEq(isAsmJSModule(f), true); + assertEq(isAsmJSModule(g), true); + } catch (e) { + // ignore spurious error when offThreadCompileScript can't run in + // parallel + } +} diff --git a/js/src/jit-test/tests/asm.js/testProfiling.js b/js/src/jit-test/tests/asm.js/testProfiling.js new file mode 100644 index 000000000..564f6f359 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testProfiling.js @@ -0,0 +1,246 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +// Run test only for asm.js +if (!isAsmJSCompilationAvailable()) + quit(); + +// Single-step profiling currently only works in the ARM simulator +if (!getBuildConfiguration()["arm-simulator"]) + quit(); + +function checkSubSequence(got, expect) +{ + var got_i = 0; + EXP: for (var exp_i = 0; exp_i < expect.length; exp_i++) { + var item = expect[exp_i]; + // Scan for next match in got. + while (got_i < got.length) { + if (got[got_i++] == expect[exp_i]) + continue EXP; + } + print("MISMATCH: " + got.join(",") + "\n" + + " VS " + expect.join(",")); + return false; + } + return true; +} + +function assertStackContainsSeq(got, expect) +{ + var normalized = []; + + for (var i = 0; i < got.length; i++) { + if (got[i].length == 0) + continue; + var parts = got[i].split(','); + for (var j = 0; j < parts.length; j++) { + var frame = parts[j]; + frame = frame.replace(/ \([^\)]*\)/g, ""); + frame = frame.replace(/(fast|slow) FFI trampoline/g, "<"); + frame = frame.replace(/entry trampoline/g, ">"); + frame = frame.replace(/(\/[^\/,<]+)*\/testProfiling.js/g, ""); + frame = frame.replace(/testBuiltinD2D/g, ""); + frame = frame.replace(/testBuiltinF2F/g, ""); + frame = frame.replace(/testBuiltinDD2D/g, ""); + frame = frame.replace(/assertThrowsInstanceOf/g, ""); + frame = frame.replace(/^ffi[12]?/g, ""); + normalized.push(frame); + } + } + + var gotNorm = normalized.join(',').replace(/,+/g, ","); + gotNorm = gotNorm.replace(/^,/, "").replace(/,$/, ""); + + assertEq(checkSubSequence(gotNorm.split(','), expect.split(',')), true); +} + +// Test profiling enablement while asm.js is running. +var stacks; +var ffi = function(enable) { + if (enable == +1) + enableSPSProfiling(); + enableSingleStepProfiling(); + stacks = disableSingleStepProfiling(); + if (enable == -1) + disableSPSProfiling(); +} +var f = asmLink(asmCompile('global','ffis',USE_ASM + "var ffi=ffis.ffi; function g(i) { i=i|0; ffi(i|0) } function f(i) { i=i|0; g(i|0) } return f"), null, {ffi}); +f(0); +assertStackContainsSeq(stacks, ""); +f(+1); +assertStackContainsSeq(stacks, ""); +f(0); +assertStackContainsSeq(stacks, "<,g,f,>"); +f(-1); +assertStackContainsSeq(stacks, "<,g,f,>"); +f(0); +assertStackContainsSeq(stacks, ""); + +// Enable profiling for the rest of the tests. +enableSPSProfiling(); + +var f = asmLink(asmCompile(USE_ASM + "function f() { return 42 } return f")); +enableSingleStepProfiling(); +assertEq(f(), 42); +var stacks = disableSingleStepProfiling(); +assertStackContainsSeq(stacks, ">,f,>,>"); + +var m = asmCompile(USE_ASM + "function g(i) { i=i|0; return (i+1)|0 } function f() { return g(42)|0 } return f"); +for (var i = 0; i < 3; i++) { + var f = asmLink(m); + enableSingleStepProfiling(); + assertEq(f(), 43); + var stacks = disableSingleStepProfiling(); + assertStackContainsSeq(stacks, ">,f,>,g,f,>,f,>,>"); +} + +var m = asmCompile(USE_ASM + "function g1() { return 1 } function g2() { return 2 } function f(i) { i=i|0; return TBL[i&1]()|0 } var TBL=[g1,g2]; return f"); +for (var i = 0; i < 3; i++) { + var f = asmLink(m); + enableSingleStepProfiling(); + assertEq(f(0), 1); + assertEq(f(1), 2); + var stacks = disableSingleStepProfiling(); + assertStackContainsSeq(stacks, ">,f,>,g1,f,>,f,>,>,>,f,>,g2,f,>,f,>,>"); +} + +function testBuiltinD2D(name) { + var m = asmCompile('g', USE_ASM + "var fun=g.Math." + name + "; function f(d) { d=+d; return +fun(d) } return f"); + for (var i = 0; i < 3; i++) { + var f = asmLink(m, this); + enableSingleStepProfiling(); + assertEq(f(.1), eval("Math." + name + "(.1)")); + var stacks = disableSingleStepProfiling(); + assertStackContainsSeq(stacks, ">,f,>,native call,>,f,>,>"); + } +} +for (name of ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'ceil', 'floor', 'exp', 'log']) + testBuiltinD2D(name); + +function testBuiltinF2F(name) { + var m = asmCompile('g', USE_ASM + "var tof=g.Math.fround; var fun=g.Math." + name + "; function f(d) { d=tof(d); return tof(fun(d)) } return f"); + for (var i = 0; i < 3; i++) { + var f = asmLink(m, this); + enableSingleStepProfiling(); + assertEq(f(.1), eval("Math.fround(Math." + name + "(Math.fround(.1)))")); + var stacks = disableSingleStepProfiling(); + assertStackContainsSeq(stacks, ">,f,>,native call,>,f,>,>"); + } +} +for (name of ['ceil', 'floor']) + testBuiltinF2F(name); + +function testBuiltinDD2D(name) { + var m = asmCompile('g', USE_ASM + "var fun=g.Math." + name + "; function f(d, e) { d=+d; e=+e; return +fun(d,e) } return f"); + for (var i = 0; i < 3; i++) { + var f = asmLink(m, this); + enableSingleStepProfiling(); + assertEq(f(.1, .2), eval("Math." + name + "(.1, .2)")); + var stacks = disableSingleStepProfiling(); + assertStackContainsSeq(stacks, ">,f,>,native call,>,f,>,>"); + } +} +for (name of ['atan2', 'pow']) + testBuiltinDD2D(name); + +// FFI tests: +setJitCompilerOption("ion.warmup.trigger", 10); +setJitCompilerOption("baseline.warmup.trigger", 0); +setJitCompilerOption("offthread-compilation.enable", 0); + +var m = asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2=ffis.ffi2; function f() { return ((ffi1()|0) + (ffi2()|0))|0 } return f"); + +var ffi1 = function() { return 10 } +var ffi2 = function() { return 73 } +var f = asmLink(m, null, {ffi1,ffi2}); + +// Interp FFI exit +enableSingleStepProfiling(); +assertEq(f(), 83); +var stacks = disableSingleStepProfiling(); +assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); + +// Ion FFI exit +for (var i = 0; i < 20; i++) + assertEq(f(), 83); +enableSingleStepProfiling(); +assertEq(f(), 83); +var stacks = disableSingleStepProfiling(); +assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); + +var ffi1 = function() { return { valueOf() { return 20 } } } +var ffi2 = function() { return { valueOf() { return 74 } } } +var f = asmLink(m, null, {ffi1,ffi2}); + +// Interp FFI exit +enableSingleStepProfiling(); +assertEq(f(), 94); +var stacks = disableSingleStepProfiling(); +assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); // TODO: add 'valueOf' once interp shows up + +// Ion FFI exit +for (var i = 0; i < 20; i++) + assertEq(f(), 94); +enableSingleStepProfiling(); +assertEq(f(), 94); +var stacks = disableSingleStepProfiling(); +assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); // TODO: add 'valueOf' once interp shows up + +var ffi1 = function() { return 15 } +var ffi2 = function() { return f2() + 17 } +var {f1,f2} = asmLink(asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2=ffis.ffi2; function f2() { return ffi1()|0 } function f1() { return ffi2()|0 } return {f1:f1, f2:f2}"), null, {ffi1, ffi2}); +// Interpreter FFI exit +enableSingleStepProfiling(); +assertEq(f1(), 32); +var stacks = disableSingleStepProfiling(); +assertStackContainsSeq(stacks, ">,f1,>,<,f1,>,>,<,f1,>,f2,>,<,f1,>,<,f2,>,<,f1,>,f2,>,<,f1,>,>,<,f1,>,<,f1,>,f1,>,>"); + + +// Ion FFI exit +for (var i = 0; i < 20; i++) + assertEq(f1(), 32); +enableSingleStepProfiling(); +assertEq(f1(), 32); +var stacks = disableSingleStepProfiling(); +assertStackContainsSeq(stacks, ">,f1,>,<,f1,>,>,<,f1,>,f2,>,<,f1,>,<,f2,>,<,f1,>,f2,>,<,f1,>,>,<,f1,>,<,f1,>,f1,>,>"); + + +if (isSimdAvailable() && typeof SIMD !== 'undefined') { + // SIMD out-of-bounds exit + var buf = new ArrayBuffer(0x10000); + var f = asmLink(asmCompile('g','ffi','buf', USE_ASM + 'var f4=g.SIMD.float32x4; var f4l=f4.load; var u8=new g.Uint8Array(buf); function f(i) { i=i|0; return f4l(u8, 0xFFFF + i | 0); } return f'), this, {}, buf); + enableSingleStepProfiling(); + assertThrowsInstanceOf(() => f(4), RangeError); + var stacks = disableSingleStepProfiling(); + // TODO check that expected is actually the correctly expected string, when + // SIMD is implemented on ARM. + assertStackContainsSeq(stacks, ">,f,>,inline stub,f,>"); +} + + +// Thunks +setJitCompilerOption("jump-threshold", 0); +var h = asmLink(asmCompile(USE_ASM + 'function f() {} function g() { f() } function h() { g() } return h')); +enableSingleStepProfiling(); +h(); +var stacks = disableSingleStepProfiling(); +assertStackContainsSeq(stacks, ">,h,>,g,h,>,f,g,h,>,g,h,>,h,>,>"); +setJitCompilerOption("jump-threshold", -1); + +// This takes forever to run. +// Stack-overflow exit test +//var limit = -1; +//var maxct = 0; +//function ffi(ct) { if (ct == limit) { enableSingleStepProfiling(); print("enabled"); } maxct = ct; } +//var f = asmLink(asmCompile('g', 'ffis',USE_ASM + "var ffi=ffis.ffi; var ct=0; function rec(){ ct=(ct+1)|0; ffi(ct|0); rec() } function f() { ct=0; rec() } return f"), null, {ffi}); +//// First find the stack limit: +//var caught = false; +//try { f() } catch (e) { caught = true; assertEq(String(e).indexOf("too much recursion") >= 0, true) } +//assertEq(caught, true); +//limit = maxct; +//print("Setting limit"); +//var caught = false; +//try { f() } catch (e) { caught = true; print("caught"); assertEq(String(e).indexOf("too much recursion") >= 0, true) } +//var stacks = disableSingleStepProfiling(); +//assertEq(String(stacks).indexOf("rec") >= 0, true); diff --git a/js/src/jit-test/tests/asm.js/testRangeAnalysis.js b/js/src/jit-test/tests/asm.js/testRangeAnalysis.js new file mode 100644 index 000000000..6418bc1b3 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testRangeAnalysis.js @@ -0,0 +1,15 @@ +// Bug 894781 +function m(stdlib) +{ + "use asm"; + var abs = stdlib.Math.abs; + function f(d) + { + d = +d; + return (~~(5.0 - +abs(d)))|0; + } + return f; +} +var f = m(this); +assertEq(f(0.2), 4); +assertEq(f(NaN), 0); diff --git a/js/src/jit-test/tests/asm.js/testSIMD-16x8.js b/js/src/jit-test/tests/asm.js/testSIMD-16x8.js new file mode 100644 index 000000000..6f017892c --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testSIMD-16x8.js @@ -0,0 +1,510 @@ +load(libdir + "asm.js"); +load(libdir + "simd.js"); +load(libdir + "asserts.js"); + +// Set to true to see more JS debugging spew. +const DEBUG = false; + +if (!isSimdAvailable()) { + DEBUG && print("won't run tests as simd extensions aren't activated yet"); + quit(0); +} + +// Tests for 16x8 SIMD types: Int16x8, Uint16x8, Bool16x8. + +const I16x8 = 'var i16x8 = glob.SIMD.Int16x8;' +const I16x8CHK = 'var i16x8chk = i16x8.check;' +const I16x8EXT = 'var i16x8ext = i16x8.extractLane;' +const I16x8REP = 'var i16x8rep = i16x8.replaceLane;' +const I16x8U16x8 = 'var i16x8u16x8 = i16x8.fromUint16x8Bits;' + +const U16x8 = 'var u16x8 = glob.SIMD.Uint16x8;' +const U16x8CHK = 'var u16x8chk = u16x8.check;' +const U16x8EXT = 'var u16x8ext = u16x8.extractLane;' +const U16x8REP = 'var u16x8rep = u16x8.replaceLane;' +const U16x8I16x8 = 'var u16x8i16x8 = u16x8.fromInt16x8Bits;' + +const B16x8 = 'var b16x8 = glob.SIMD.Bool16x8;' +const B16x8CHK = 'var b16x8chk = b16x8.check;' +const B16x8EXT = 'var b16x8ext = b16x8.extractLane;' +const B16x8REP = 'var b16x8rep = b16x8.replaceLane;' + +const INT16_MAX = 0x7fff +const INT16_MIN = -0x10000 +const UINT16_MAX = 0xffff + +// Linking +assertEq(asmLink(asmCompile('glob', USE_ASM + I16x8 + "function f() {} return f"), {SIMD:{Int16x8: SIMD.Int16x8}})(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + U16x8 + "function f() {} return f"), {SIMD:{Uint16x8: SIMD.Uint16x8}})(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + B16x8 + "function f() {} return f"), {SIMD:{Bool16x8: SIMD.Bool16x8}})(), undefined); + +// Local variable of Int16x8 type. +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Int16x8(1,2,3,4,5,6,7,8);} return f"); +assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8;} return f"); +assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8();} return f"); +assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7,8.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7,8,9);} return f"); +assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7,8|0);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7,8);} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7," + (INT16_MAX + 1) + ");} return f"), this)(), undefined); + +// Local variable of Uint16x8 type. +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Uint16x8(1,2,3,4,5,6,7,8);} return f"); +assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8;} return f"); +assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8();} return f"); +assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4);} return f"); +assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7,8.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7,8,9);} return f"); +assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7,8|0);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7,8);} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7," + (UINT16_MAX + 1) + ");} return f"), this)(), undefined); + +// Local variable of Bool16x8 type. +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Bool16x8(1,0,0,0, 0,0,0,0);} return f"); +assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8;} return f"); +assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8();} return f"); +assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0);} return f"); +assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0, 0,0,0,1.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0, 0,0,0,0|0);} return f"); +assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0, 0,0,0,0, 1);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0, 0,-1,-2,0);} return f"), this)(), undefined); + +// Only signed Int16x8 allowed as return value. +assertEqVecArr(asmLink(asmCompile('glob', USE_ASM + I16x8 + "function f() {return i16x8(1,2,3,4,5,6,7,8);} return f"), this)(), + [1, 2, 3, 4, 5, 6, 7, 8]); +assertEqVecArr(asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + "function f() {return i16x8chk(i16x8(1,2,3,32771,5,6,7,8));} return f"), this)(), + [1, 2, 3, -32765, 5, 6, 7, 8]); +assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {return u16x8(1,2,3,4,5,6,7,8);} return f"); +assertAsmTypeFail('glob', USE_ASM + U16x8 + U16x8CHK + "function f() {return u16x8chk(u16x8(1,2,3,4,5,6,7,8));} return f"); + +// Test splat. +function splat(x) { + let r = [] + for (let i = 0; i < 8; i++) + r.push(x); + return r +} + +splatB = asmLink(asmCompile('glob', USE_ASM + B16x8 + + 'var splat = b16x8.splat;' + + 'function f(x) { x = x|0; return splat(x); } return f'), this); +assertEqVecArr(splatB(true), splat(true)); +assertEqVecArr(splatB(false), splat(false)); + + +splatB0 = asmLink(asmCompile('glob', USE_ASM + B16x8 + + 'var splat = b16x8.splat;' + + 'function f() { var x = 0; return splat(x); } return f'), this); +assertEqVecArr(splatB0(), splat(false)); +splatB1 = asmLink(asmCompile('glob', USE_ASM + B16x8 + + 'var splat = b16x8.splat;' + + 'function f() { var x = 1; return splat(x); } return f'), this); +assertEqVecArr(splatB1(), splat(true)); + +splatI = asmLink(asmCompile('glob', USE_ASM + I16x8 + + 'var splat = i16x8.splat;' + + 'function f(x) { x = x|0; return splat(x); } return f'), this); +for (let x of [0, 1, -1, 0x12345, 0x1234, -1000, -1000000]) { + assertEqVecArr(splatI(x), splat(x << 16 >> 16)); +} + +splatIc = asmLink(asmCompile('glob', USE_ASM + I16x8 + + 'var splat = i16x8.splat;' + + 'function f() { var x = 100; return splat(x); } return f'), this); +assertEqVecArr(splatIc(), splat(100)) + +splatU = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8U16x8 + + 'var splat = u16x8.splat;' + + 'function f(x) { x = x|0; return i16x8u16x8(splat(x)); } return f'), this); +for (let x of [0, 1, -1, 0x12345, 0x1234, -1000, -1000000]) { + assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(splatI(x)), splat(x << 16 >>> 16)); +} + +splatUc = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8U16x8 + + 'var splat = u16x8.splat;' + + 'function f() { var x = 200; return i16x8u16x8(splat(x)); } return f'), this); +assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(splatUc()), splat(200)) + + +// Test extractLane. +// +// The lane index must be a literal int, and we generate different code for +// different lanes. +function extractI(a, i) { + return asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8EXT + + `function f() {var x=i16x8(${a.join(',')}); return i16x8ext(x, ${i})|0; } return f`), this)(); +} +a = [-1,2,-3,4,-5,6,-7,-8]; +for (var i = 0; i < 8; i++) + assertEq(extractI(a, i), a[i]); +a = a.map(x => -x); +for (var i = 0; i < 8; i++) + assertEq(extractI(a, i), a[i]); + +function extractU(a, i) { + return asmLink(asmCompile('glob', USE_ASM + U16x8 + U16x8EXT + + `function f() {var x=u16x8(${a.join(',')}); return u16x8ext(x, ${i})|0; } return f`), this)(); +} +a = [1,255,12,13,14,150,200,3]; +for (var i = 0; i < 8; i++) + assertEq(extractU(a, i), a[i]); +a = a.map(x => UINT16_MAX-x); +for (var i = 0; i < 8; i++) + assertEq(extractU(a, i), a[i]); + +function extractB(a, i) { + return asmLink(asmCompile('glob', USE_ASM + B16x8 + B16x8EXT + + `function f() {var x=b16x8(${a.join(',')}); return b16x8ext(x, ${i})|0; } return f`), this)(); +} +a = [1,1,0,1, 1,0,0,0]; +for (var i = 0; i < 8; i++) + assertEq(extractB(a, i), a[i]); +a = a.map(x => 1-x); +for (var i = 0; i < 8; i++) + assertEq(extractB(a, i), a[i]); + +// Test replaceLane. +function replaceI(a, i) { + return asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8REP + + `function f(v) {v=v|0; var x=i16x8(${a.join(',')}); return i16x8rep(x,${i},v); } return f`), this); +} +a = [-1,2,-3,4,-5,6,-7,-9]; +for (var i = 0; i < 8; i++) { + var f = replaceI(a, i); + var b = a.slice(0); + b[i] = -20; + assertEqVecArr(f(-20), b); +} + +function replaceU(a, i) { + return asmLink(asmCompile('glob', USE_ASM + U16x8 + U16x8REP + I16x8 + I16x8U16x8 + + `function f(v) {v=v|0; var x=u16x8(${a.join(',')}); return i16x8u16x8(u16x8rep(x,${i},v)); } return f`), this); +} +a = [65000-1,2,65000-3,4,65000-5,6,65000-7,65000-9]; +for (var i = 0; i < 8; i++) { + var rawf = replaceU(a, i); + var f = x => SIMD.Uint16x8.fromInt16x8Bits(rawf(x)) + var b = a.slice(0); + b[i] = 1000; + assertEqVecArr(f(1000), b); +} + +function replaceB(a, i) { + return asmLink(asmCompile('glob', USE_ASM + B16x8 + B16x8REP + + `function f(v) {v=v|0; var x=b16x8(${a.join(',')}); return b16x8rep(x,${i},v); } return f`), this); +} +a = [1,1,0,1,1,0,0,0]; +for (var i = 0; i < 8; i++) { + var f = replaceB(a, i); + var b = a.slice(0); + let v = 1 - a[i]; + b[i] = v; + assertEqVecArr(f(v), b.map(x => !!x)); +} + + +// Test select. +selectI = asmLink(asmCompile('glob', USE_ASM + I16x8 + B16x8 + B16x8CHK + + 'var select = i16x8.select;' + + 'var a = i16x8(-1,2,-3,4,-5, 6,-7, 8);' + + 'var b = i16x8( 5,6, 7,8, 9,10,11,12);' + + 'function f(x) { x = b16x8chk(x); return select(x, a, b); } return f'), this); +assertEqVecArr(selectI(SIMD.Bool16x8( 0,0, 1,0, 1,1, 1, 0)), + [ 5,6,-3,8,-5,6,-7,12]); + +selectU = asmLink(asmCompile('glob', USE_ASM + I16x8 + B16x8 + B16x8CHK + U16x8 + I16x8U16x8 + U16x8I16x8 + + 'var select = u16x8.select;' + + 'var a = i16x8(-1,2,-3,4,-5, 6,-7, 8);' + + 'var b = i16x8( 5,6, 7,8, 9,10,11,12);' + + 'function f(x) { x = b16x8chk(x); return i16x8u16x8(select(x, u16x8i16x8(a), u16x8i16x8(b))); } return f'), this); +assertEqVecArr(selectU(SIMD.Bool16x8( 0,0, 1,0, 1,1, 1, 0)), + [ 5,6,-3,8,-5,6,-7,12]); + +// Test swizzle. +function swizzle(vec, lanes) { + let r = []; + for (let i = 0; i < 8; i++) + r.push(vec[lanes[i]]); + return r; +} + +function swizzleI(lanes) { + let asm = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + + 'var swz = i16x8.swizzle;' + + `function f(a) { a = i16x8chk(a); return swz(a, ${lanes.join()}); } return f`), this); + let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16); + let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16); + let v1 = SIMD.Int16x8(...a1); + let v2 = SIMD.Int16x8(...a2); + assertEqVecArr(asm(v1), swizzle(a1, lanes)); + assertEqVecArr(asm(v2), swizzle(a2, lanes)); +} + +swizzleI([3, 4, 7, 1, 4, 3, 1, 2]); +swizzleI([0, 0, 0, 0, 0, 0, 0, 0]); +swizzleI([7, 7, 7, 7, 7, 7, 7, 7]); + +function swizzleU(lanes) { + let asm = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + U16x8 + U16x8I16x8 + I16x8U16x8 + + 'var swz = u16x8.swizzle;' + + `function f(a) { a = i16x8chk(a); return i16x8u16x8(swz(u16x8i16x8(a), ${lanes.join()})); } return f`), this); + let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16); + let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16); + let v1 = SIMD.Int16x8(...a1); + let v2 = SIMD.Int16x8(...a2); + assertEqVecArr(asm(v1), swizzle(a1, lanes)); + assertEqVecArr(asm(v2), swizzle(a2, lanes)); +} + +swizzleU([3, 4, 7, 1, 4, 3, 1, 2]); +swizzleU([0, 0, 0, 0, 0, 0, 0, 0]); +swizzleU([7, 7, 7, 7, 7, 7, 7, 7]); + +// Out-of-range lane indexes. +assertAsmTypeFail('glob', USE_ASM + I16x8 + 'var swz = i16x8.swizzle; ' + + 'function f() { var x=i16x8(0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8); } return f'); +assertAsmTypeFail('glob', USE_ASM + U16x8 + 'var swz = u16x8.swizzle; ' + + 'function f() { var x=u16x8(0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8); } return f'); +// Missing lane indexes. +assertAsmTypeFail('glob', USE_ASM + I16x8 + 'var swz = i16x8.swizzle; ' + + 'function f() { var x=i16x8(0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7); } return f'); +assertAsmTypeFail('glob', USE_ASM + U16x8 + 'var swz = u16x8.swizzle; ' + + 'function f() { var x=u16x8(0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7); } return f'); + + +// Test shuffle. +function shuffle(vec1, vec2, lanes) { + let r = []; + let vec = vec1.concat(vec2) + for (let i = 0; i < 8; i++) + r.push(vec[lanes[i]]); + return r; +} + +function shuffleI(lanes) { + let asm = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + + 'var shuf = i16x8.shuffle;' + + `function f(a1, a2) { a1 = i16x8chk(a1); a2 = i16x8chk(a2); return shuf(a1, a2, ${lanes.join()}); } return f`), this); + let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16); + let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16); + let v1 = SIMD.Int16x8(...a1); + let v2 = SIMD.Int16x8(...a2); + assertEqVecArr(asm(v1, v2), shuffle(a1, a2, lanes)); +} + +function shuffleU(lanes) { + let asm = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + U16x8 + U16x8I16x8 + I16x8U16x8 + + 'var shuf = u16x8.shuffle;' + + 'function f(a1, a2) { a1 = i16x8chk(a1); a2 = i16x8chk(a2); ' + + `return i16x8u16x8(shuf(u16x8i16x8(a1), u16x8i16x8(a2), ${lanes.join()})); } return f`), this); + let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16); + let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16); + let v1 = SIMD.Int16x8(...a1); + let v2 = SIMD.Int16x8(...a2); + assertEqVecArr(asm(v1, v2), shuffle(a1, a2, lanes)); +} + +shuffleI([0, 0, 0, 0, 0, 0, 0, 0]) +shuffleI([15, 15, 15, 15, 15, 15, 15, 15]) +shuffleI([6, 2, 0, 14, 6, 10, 11, 1]) + +shuffleU([7, 7, 7, 7, 7, 7, 7, 7]) +shuffleU([8, 15, 15, 15, 15, 15, 15, 15]) +shuffleU([6, 2, 0, 14, 6, 10, 11, 1]) + +// Test unary operators. +function unaryI(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + + `var fut = i16x8.${opname};` + + 'function f(v) { v = i16x8chk(v); return fut(v); } return f'), this); + let a = [65000-1,2,65000-3,4,65000-5,6,65000-7,65000-9]; + let v = SIMD.Int16x8(...a); + assertEqVecArr(simdfunc(v), a.map(lanefunc)); +} + +function unaryU(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8CHK + U16x8I16x8 + I16x8U16x8 + + `var fut = u16x8.${opname};` + + 'function f(v) { v = i16x8chk(v); return i16x8u16x8(fut(u16x8i16x8(v))); } return f'), this); + let a = [65000-1,2,65000-3,4,65000-5,6,65000-7,65000-9]; + let v = SIMD.Int16x8(...a); + assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(simdfunc(v)), a.map(lanefunc)); +} + +function unaryB(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + B16x8 + B16x8CHK + + `var fut = b16x8.${opname};` + + 'function f(v) { v = b16x8chk(v); return fut(v); } return f'), this); + let a = [1,1,0,1,1,0,0,0]; + let v = SIMD.Bool16x8(...a); + assertEqVecArr(simdfunc(v), a.map(lanefunc)); +} + +unaryI('not', x => ~x << 16 >> 16); +unaryU('not', x => ~x << 16 >>> 16); +unaryB('not', x => !x); +unaryI('neg', x => -x << 16 >> 16); +unaryU('neg', x => -x << 16 >>> 16); + + +// Test binary operators. +function zipmap(a1, a2, f) { + assertEq(a1.length, a2.length); + let r = []; + for (var i = 0; i < a1.length; i++) + r.push(f(a1[i], a2[i])); + return r +} + +function binaryI(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + + `var fut = i16x8.${opname};` + + 'function f(v1, v2) { v1 = i16x8chk(v1); v2 = i16x8chk(v2); return fut(v1, v2); } return f'), this); + let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16); + let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16); + let ref = zipmap(a1, a2, lanefunc); + let v1 = SIMD.Int16x8(...a1); + let v2 = SIMD.Int16x8(...a2); + assertEqVecArr(simdfunc(v1, v2), ref); +} + +function binaryU(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8CHK + U16x8I16x8 + I16x8U16x8 + + `var fut = u16x8.${opname};` + + 'function f(v1, v2) { v1 = i16x8chk(v1); v2 = i16x8chk(v2); return i16x8u16x8(fut(u16x8i16x8(v1), u16x8i16x8(v2))); } return f'), this); + let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >>> 16); + let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >>> 16); + let ref = zipmap(a1, a2, lanefunc); + let v1 = SIMD.Int16x8(...a1); + let v2 = SIMD.Int16x8(...a2); + let res = SIMD.Uint16x8.fromInt16x8Bits(simdfunc(v1, v2)); + assertEqVecArr(res, ref); +} + +function binaryB(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + B16x8 + B16x8CHK + + `var fut = b16x8.${opname};` + + 'function f(v1, v2) { v1 = b16x8chk(v1); v2 = b16x8chk(v2); return fut(v1, v2); } return f'), this); + let a = [1,1,0,1,1,0,0,0]; + let v = SIMD.Bool16x8(...a); + assertEqVecArr(simdfunc(v), a.map(lanefunc)); +} + +binaryI('add', (x, y) => (x + y) << 16 >> 16); +binaryI('sub', (x, y) => (x - y) << 16 >> 16); +binaryI('mul', (x, y) => (x * y) << 16 >> 16); +binaryU('add', (x, y) => (x + y) << 16 >>> 16); +binaryU('sub', (x, y) => (x - y) << 16 >>> 16); +binaryU('mul', (x, y) => (x * y) << 16 >>> 16); + +binaryI('and', (x, y) => (x & y) << 16 >> 16); +binaryI('or', (x, y) => (x | y) << 16 >> 16); +binaryI('xor', (x, y) => (x ^ y) << 16 >> 16); +binaryU('and', (x, y) => (x & y) << 16 >>> 16); +binaryU('or', (x, y) => (x | y) << 16 >>> 16); +binaryU('xor', (x, y) => (x ^ y) << 16 >>> 16); + +function sat(x, lo, hi) { + if (x < lo) return lo; + if (x > hi) return hi; + return x +} +function isat(x) { return sat(x, -32768, 32767); } +function usat(x) { return sat(x, 0, 0xffff); } + +binaryI('addSaturate', (x, y) => isat(x + y)) +binaryI('subSaturate', (x, y) => isat(x - y)) +binaryU('addSaturate', (x, y) => usat(x + y)) +binaryU('subSaturate', (x, y) => usat(x - y)) + + +// Test shift operators. +function zip1map(a, s, f) { + return a.map(x => f(x, s)); +} + +function shiftI(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + + `var fut = i16x8.${opname};` + + 'function f(v, s) { v = i16x8chk(v); s = s|0; return fut(v, s); } return f'), this); + let a = [-1,2,-3,0x80,0x7f,6,0x8000,0x7fff]; + let v = SIMD.Int16x8(...a); + for (let s of [0, 1, 2, 6, 7, 8, 9, 10, 16, 255, -1, -8, -7, -1000]) { + let ref = zip1map(a, s, lanefunc); + // 1. Test dynamic shift amount. + assertEqVecArr(simdfunc(v, s), ref); + + // 2. Test constant shift amount. + let cstf = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + + `var fut = i16x8.${opname};` + + `function f(v) { v = i16x8chk(v); return fut(v, ${s}); } return f`), this); + assertEqVecArr(cstf(v, s), ref); + } +} + +function shiftU(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8CHK + U16x8I16x8 + I16x8U16x8 + + `var fut = u16x8.${opname};` + + 'function f(v, s) { v = i16x8chk(v); s = s|0; return i16x8u16x8(fut(u16x8i16x8(v), s)); } return f'), this); + let a = [-1,2,-3,0x80,0x7f,6,0x8000,0x7fff]; + let v = SIMD.Int16x8(...a); + for (let s of [0, 1, 2, 6, 7, 8, 9, 10, 16, 255, -1, -8, -7, -1000]) { + let ref = zip1map(a, s, lanefunc); + // 1. Test dynamic shift amount. + assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(simdfunc(v, s)), ref); + + // 2. Test constant shift amount. + let cstf = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8CHK + U16x8I16x8 + I16x8U16x8 + + `var fut = u16x8.${opname};` + + `function f(v) { v = i16x8chk(v); return i16x8u16x8(fut(u16x8i16x8(v), ${s})); } return f`), this); + assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(cstf(v, s)), ref); + } +} + +shiftI('shiftLeftByScalar', (x,s) => (x << (s & 15)) << 16 >> 16); +shiftU('shiftLeftByScalar', (x,s) => (x << (s & 15)) << 16 >>> 16); +shiftI('shiftRightByScalar', (x,s) => ((x << 16 >> 16) >> (s & 15)) << 16 >> 16); +shiftU('shiftRightByScalar', (x,s) => ((x << 16 >>> 16) >>> (s & 15)) << 16 >>> 16); + + +// Comparisons. +function compareI(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + + `var fut = i16x8.${opname};` + + 'function f(v1, v2) { v1 = i16x8chk(v1); v2 = i16x8chk(v2); return fut(v1, v2); } return f'), this); + let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16); + let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16); + let ref = zipmap(a1, a2, lanefunc); + let v1 = SIMD.Int16x8(...a1); + let v2 = SIMD.Int16x8(...a2); + assertEqVecArr(simdfunc(v1, v2), ref); +} + +function compareU(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + U16x8 + U16x8I16x8 + + `var fut = u16x8.${opname};` + + 'function f(v1, v2) { v1 = i16x8chk(v1); v2 = i16x8chk(v2); return fut(u16x8i16x8(v1), u16x8i16x8(v2)); } return f'), this); + let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >>> 16); + let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >>> 16); + let ref = zipmap(a1, a2, lanefunc); + let v1 = SIMD.Int16x8(...a1); + let v2 = SIMD.Int16x8(...a2); + assertEqVecArr(simdfunc(v1, v2), ref); +} + +compareI("equal", (x,y) => x == y); +compareU("equal", (x,y) => x == y); +compareI("notEqual", (x,y) => x != y); +compareU("notEqual", (x,y) => x != y); +compareI("lessThan", (x,y) => x < y); +compareU("lessThan", (x,y) => x < y); +compareI("lessThanOrEqual", (x,y) => x <= y); +compareU("lessThanOrEqual", (x,y) => x <= y); +compareI("greaterThan", (x,y) => x > y); +compareU("greaterThan", (x,y) => x > y); +compareI("greaterThanOrEqual", (x,y) => x >= y); +compareU("greaterThanOrEqual", (x,y) => x >= y); diff --git a/js/src/jit-test/tests/asm.js/testSIMD-8x16.js b/js/src/jit-test/tests/asm.js/testSIMD-8x16.js new file mode 100644 index 000000000..160da82a8 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testSIMD-8x16.js @@ -0,0 +1,524 @@ +load(libdir + "asm.js"); +load(libdir + "simd.js"); +load(libdir + "asserts.js"); + +// Set to true to see more JS debugging spew. +const DEBUG = false; + +if (!isSimdAvailable()) { + DEBUG && print("won't run tests as simd extensions aren't activated yet"); + quit(0); +} + +// Tests for 8x16 SIMD types: Int8x16, Uint8x16, Bool8x16. + +const I8x16 = 'var i8x16 = glob.SIMD.Int8x16;' +const I8x16CHK = 'var i8x16chk = i8x16.check;' +const I8x16EXT = 'var i8x16ext = i8x16.extractLane;' +const I8x16REP = 'var i8x16rep = i8x16.replaceLane;' +const I8x16U8x16 = 'var i8x16u8x16 = i8x16.fromUint8x16Bits;' + +const U8x16 = 'var u8x16 = glob.SIMD.Uint8x16;' +const U8x16CHK = 'var u8x16chk = u8x16.check;' +const U8x16EXT = 'var u8x16ext = u8x16.extractLane;' +const U8x16REP = 'var u8x16rep = u8x16.replaceLane;' +const U8x16I8x16 = 'var u8x16i8x16 = u8x16.fromInt8x16Bits;' + +const B8x16 = 'var b8x16 = glob.SIMD.Bool8x16;' +const B8x16CHK = 'var b8x16chk = b8x16.check;' +const B8x16EXT = 'var b8x16ext = b8x16.extractLane;' +const B8x16REP = 'var b8x16rep = b8x16.replaceLane;' + +const INT8_MAX = 127 +const INT8_MIN = -128 +const UINT8_MAX = 255 + +// Linking +assertEq(asmLink(asmCompile('glob', USE_ASM + I8x16 + "function f() {} return f"), {SIMD:{Int8x16: SIMD.Int8x16}})(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + U8x16 + "function f() {} return f"), {SIMD:{Uint8x16: SIMD.Uint8x16}})(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + B8x16 + "function f() {} return f"), {SIMD:{Bool8x16: SIMD.Bool8x16}})(), undefined); + +// Local variable of Int8x16 type. +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Int8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"); +assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16;} return f"); +assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16();} return f"); +assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);} return f"); +assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16|0);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15," + (INT8_MAX + 1) + ");} return f"), this)(), undefined); + +// Local variable of Uint8x16 type. +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Uint8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"); +assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16;} return f"); +assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16();} return f"); +assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4);} return f"); +assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);} return f"); +assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16|0);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15," + (UINT8_MAX + 1) + ");} return f"), this)(), undefined); + +// Local variable of Bool8x16 type. +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Bool8x16(1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1);} return f"); +assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16;} return f"); +assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16();} return f"); +assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0);} return f"); +assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1|0);} return f"); +assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0,0,0,0,0,0,1,-1,2,-2,1,1,1);} return f"), this)(), undefined); + +// Only signed Int8x16 allowed as return value. +assertEqVecArr(asmLink(asmCompile('glob', USE_ASM + I8x16 + "function f() {return i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"), this)(), + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); +assertEqVecArr(asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + "function f() {return i8x16chk(i8x16(1,2,3,132,5,6,7,8,9,10,11,12,13,14,15,16));} return f"), this)(), + [1, 2, 3, -124, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); +assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {return u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"); +assertAsmTypeFail('glob', USE_ASM + U8x16 + U8x16CHK + "function f() {return u8x16chk(u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));} return f"); + +// Test splat. +function splat(x) { + let r = [] + for (let i = 0; i < 16; i++) + r.push(x); + return r +} + +splatB = asmLink(asmCompile('glob', USE_ASM + B8x16 + + 'var splat = b8x16.splat;' + + 'function f(x) { x = x|0; return splat(x); } return f'), this); +assertEqVecArr(splatB(true), splat(true)); +assertEqVecArr(splatB(false), splat(false)); + + +splatB0 = asmLink(asmCompile('glob', USE_ASM + B8x16 + + 'var splat = b8x16.splat;' + + 'function f() { var x = 0; return splat(x); } return f'), this); +assertEqVecArr(splatB0(), splat(false)); +splatB1 = asmLink(asmCompile('glob', USE_ASM + B8x16 + + 'var splat = b8x16.splat;' + + 'function f() { var x = 1; return splat(x); } return f'), this); +assertEqVecArr(splatB1(), splat(true)); + +splatI = asmLink(asmCompile('glob', USE_ASM + I8x16 + + 'var splat = i8x16.splat;' + + 'function f(x) { x = x|0; return splat(x); } return f'), this); +for (let x of [0, 1, -1, 0x1234, 0x12, 1000, -1000000]) { + assertEqVecArr(splatI(x), splat(x << 24 >> 24)); +} + +splatIc = asmLink(asmCompile('glob', USE_ASM + I8x16 + + 'var splat = i8x16.splat;' + + 'function f() { var x = 100; return splat(x); } return f'), this); +assertEqVecArr(splatIc(), splat(100)) + +splatU = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16U8x16 + + 'var splat = u8x16.splat;' + + 'function f(x) { x = x|0; return i8x16u8x16(splat(x)); } return f'), this); +for (let x of [0, 1, -1, 0x1234, 0x12, 1000, -1000000]) { + assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(splatI(x)), splat(x << 24 >>> 24)); +} + +splatUc = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16U8x16 + + 'var splat = u8x16.splat;' + + 'function f() { var x = 200; return i8x16u8x16(splat(x)); } return f'), this); +assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(splatUc()), splat(200)) + + +// Test extractLane. +// +// The lane index must be a literal int, and we generate different code for +// different lanes. +function extractI(a, i) { + return asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16EXT + + `function f() {var x=i8x16(${a.join(',')}); return i8x16ext(x, ${i})|0; } return f`), this)(); +} +a = [-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,-14,-15,-16]; +for (var i = 0; i < 16; i++) + assertEq(extractI(a, i), a[i]); +a = a.map(x => -x); +for (var i = 0; i < 16; i++) + assertEq(extractI(a, i), a[i]); + +function extractU(a, i) { + return asmLink(asmCompile('glob', USE_ASM + U8x16 + U8x16EXT + + `function f() {var x=u8x16(${a.join(',')}); return u8x16ext(x, ${i})|0; } return f`), this)(); +} +a = [1,255,12,13,14,150,200,3,4,5,6,7,8,9,10,16]; +for (var i = 0; i < 16; i++) + assertEq(extractU(a, i), a[i]); +a = a.map(x => 255-x); +for (var i = 0; i < 16; i++) + assertEq(extractU(a, i), a[i]); + +function extractB(a, i) { + return asmLink(asmCompile('glob', USE_ASM + B8x16 + B8x16EXT + + `function f() {var x=b8x16(${a.join(',')}); return b8x16ext(x, ${i})|0; } return f`), this)(); +} +a = [1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,1]; +for (var i = 0; i < 16; i++) + assertEq(extractB(a, i), a[i]); +a = a.map(x => 1-x); +for (var i = 0; i < 16; i++) + assertEq(extractB(a, i), a[i]); + +// Test replaceLane. +function replaceI(a, i) { + return asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16REP + + `function f(v) {v=v|0; var x=i8x16(${a.join(',')}); return i8x16rep(x,${i},v); } return f`), this); +} +a = [-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,-14,-15,-16]; +for (var i = 0; i < 16; i++) { + var f = replaceI(a, i); + var b = a.slice(0); + b[i] = -20; + assertEqVecArr(f(-20), b); +} + +function replaceU(a, i) { + return asmLink(asmCompile('glob', USE_ASM + U8x16 + U8x16REP + I8x16 + I8x16U8x16 + + `function f(v) {v=v|0; var x=u8x16(${a.join(',')}); x=u8x16rep(x,${i},v); return i8x16u8x16(x); } return f`), this); +} +a = [256-1,2,256-3,4,256-5,6,256-7,8,256-9,10,256-11,12,256-13,256-14,256-15,256-16]; +for (var i = 0; i < 16; i++) { + // Result returned as Int8x16, convert back. + var rawf = replaceU(a, i); + var f = x => SIMD.Uint8x16.fromInt8x16Bits(rawf(x)); + var b = a.slice(0); + b[i] = 100; + assertEqVecArr(f(100), b); +} + +function replaceB(a, i) { + return asmLink(asmCompile('glob', USE_ASM + B8x16 + B8x16REP + + `function f(v) {v=v|0; var x=b8x16(${a.join(',')}); return b8x16rep(x,${i},v); } return f`), this); +} +a = [1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,1]; +for (var i = 0; i < 16; i++) { + var f = replaceB(a, i); + var b = a.slice(0); + v = 1 - a[i]; + b[i] = v; + assertEqVecArr(f(v), b.map(x => !!x)); +} + + +// Test select. +selectI = asmLink(asmCompile('glob', USE_ASM + I8x16 + B8x16 + B8x16CHK + + 'var select = i8x16.select;' + + 'var a = i8x16(-1,2,-3,4,-5, 6,-7, 8,-9,10,-11,12,-13,-14,-15,-16);' + + 'var b = i8x16( 5,6, 7,8, 9,10,11,12,13,14, 15,16,-77, 45, 32, 0);' + + 'function f(x) { x = b8x16chk(x); return select(x, a, b); } return f'), this); +assertEqVecArr(selectI(SIMD.Bool8x16( 0,0, 1,0, 1,1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1)), + [ 5,6,-3,8,-5,6,-7,12,-9,10,15,16,-13,-14,32,-16]); + +selectU = asmLink(asmCompile('glob', USE_ASM + I8x16 + B8x16 + B8x16CHK + U8x16 + I8x16U8x16 + U8x16I8x16 + + 'var select = u8x16.select;' + + 'var a = i8x16(-1,2,-3,4,-5, 6,-7, 8,-9,10,-11,12,-13,-14,-15,-16);' + + 'var b = i8x16( 5,6, 7,8, 9,10,11,12,13,14, 15,16,-77, 45, 32, 0);' + + 'function f(x) { x = b8x16chk(x); return i8x16u8x16(select(x, u8x16i8x16(a), u8x16i8x16(b))); } return f'), this); +assertEqVecArr(selectU(SIMD.Bool8x16( 0,0, 1,0, 1,1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1)), + [ 5,6,-3,8,-5,6,-7,12,-9,10,15,16,-13,-14,32,-16]); + + +// Test swizzle. +function swizzle(vec, lanes) { + let r = []; + for (let i = 0; i < 16; i++) + r.push(vec[lanes[i]]); + return r; +} + +function swizzleI(lanes) { + let asm = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + + 'var swz = i8x16.swizzle;' + + `function f(a) { a = i8x16chk(a); return swz(a, ${lanes.join()}); } return f`), this); + let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16]; + let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1]; + let v1 = SIMD.Int8x16(...a1); + let v2 = SIMD.Int8x16(...a2); + assertEqVecArr(asm(v1), swizzle(a1, lanes)); + assertEqVecArr(asm(v2), swizzle(a2, lanes)); +} + +swizzleI([10, 1, 7, 5, 1, 2, 6, 8, 5, 13, 0, 6, 2, 8, 0, 9]); +swizzleI([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +swizzleI([15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15]); + +function swizzleU(lanes) { + let asm = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + U8x16 + U8x16I8x16 + I8x16U8x16 + + 'var swz = u8x16.swizzle;' + + `function f(a) { a = i8x16chk(a); return i8x16u8x16(swz(u8x16i8x16(a), ${lanes.join()})); } return f`), this); + let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16]; + let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1]; + let v1 = SIMD.Int8x16(...a1); + let v2 = SIMD.Int8x16(...a2); + assertEqVecArr(asm(v1), swizzle(a1, lanes)); + assertEqVecArr(asm(v2), swizzle(a2, lanes)); +} + +swizzleU([10, 1, 7, 5, 1, 2, 6, 8, 5, 13, 0, 6, 2, 8, 0, 9]); +swizzleU([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +swizzleU([15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15]); + +// Out-of-range lane indexes. +assertAsmTypeFail('glob', USE_ASM + I8x16 + 'var swz = i8x16.swizzle; ' + + 'function f() { var x=i8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16); } return f'); +assertAsmTypeFail('glob', USE_ASM + U8x16 + 'var swz = u8x16.swizzle; ' + + 'function f() { var x=u8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16); } return f'); +// Missing lane indexes. +assertAsmTypeFail('glob', USE_ASM + I8x16 + 'var swz = i8x16.swizzle; ' + + 'function f() { var x=i8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); } return f'); +assertAsmTypeFail('glob', USE_ASM + U8x16 + 'var swz = u8x16.swizzle; ' + + 'function f() { var x=u8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); } return f'); + + +// Test shuffle. +function shuffle(vec1, vec2, lanes) { + let r = []; + let vec = vec1.concat(vec2); + for (let i = 0; i < 16; i++) + r.push(vec[lanes[i]]); + return r; +} + +function shuffleI(lanes) { + let asm = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + + 'var shuf = i8x16.shuffle;' + + `function f(a1, a2) { a1 = i8x16chk(a1); a2 = i8x16chk(a2); return shuf(a1, a2, ${lanes.join()}); } return f`), this); + let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16]; + let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1]; + let v1 = SIMD.Int8x16(...a1); + let v2 = SIMD.Int8x16(...a2); + assertEqVecArr(asm(v1, v2), shuffle(a1, a2, lanes)); +} + +shuffleI([31, 9, 5, 4, 29, 12, 19, 10, 16, 22, 10, 9, 6, 18, 9, 8]); +shuffleI([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +shuffleI([31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31]); + +function shuffleU(lanes) { + let asm = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + U8x16 + U8x16I8x16 + I8x16U8x16 + + 'var shuf = u8x16.shuffle;' + + 'function f(a1, a2) { a1 = i8x16chk(a1); a2 = i8x16chk(a2); ' + + `return i8x16u8x16(shuf(u8x16i8x16(a1), u8x16i8x16(a2), ${lanes.join()})); } return f`), this); + let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16]; + let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1]; + let v1 = SIMD.Int8x16(...a1); + let v2 = SIMD.Int8x16(...a2); + assertEqVecArr(asm(v1, v2), shuffle(a1, a2, lanes)); +} + +shuffleU([31, 9, 5, 4, 29, 12, 19, 10, 16, 22, 10, 9, 6, 18, 9, 8]); +shuffleU([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +shuffleU([31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31]); + + +// Out-of-range lane indexes. +assertAsmTypeFail('glob', USE_ASM + I8x16 + 'var shuf = i8x16.shuffle; ' + + 'function f() { var x=i8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); shuf(x,x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,32); } return f'); +assertAsmTypeFail('glob', USE_ASM + U8x16 + 'var shuf = u8x16.shuffle; ' + + 'function f() { var x=u8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); shuf(x,x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,32); } return f'); +// Missing lane indexes. +assertAsmTypeFail('glob', USE_ASM + I8x16 + 'var shuf = i8x16.shuffle; ' + + 'function f() { var x=i8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); shuf(x,x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); } return f'); +assertAsmTypeFail('glob', USE_ASM + U8x16 + 'var shuf = u8x16.shuffle; ' + + 'function f() { var x=u8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); shuf(x,x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); } return f'); + + +// Test unary operators. +function unaryI(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + + `var fut = i8x16.${opname};` + + 'function f(v) { v = i8x16chk(v); return fut(v); } return f'), this); + let a = [-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,-14,-15,-16]; + let v = SIMD.Int8x16(...a); + assertEqVecArr(simdfunc(v), a.map(lanefunc)); +} + +function unaryU(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16CHK + U8x16I8x16 + I8x16U8x16 + + `var fut = u8x16.${opname};` + + 'function f(v) { v = i8x16chk(v); return i8x16u8x16(fut(u8x16i8x16(v))); } return f'), this); + let a = [256-1,2,256-3,4,256-5,6,256-7,8,256-9,10,256-11,12,256-13,256-14,256-15,256-16]; + let v = SIMD.Int8x16(...a); + assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(simdfunc(v)), a.map(lanefunc)); +} + +function unaryB(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + B8x16 + B8x16CHK + + `var fut = b8x16.${opname};` + + 'function f(v) { v = b8x16chk(v); return fut(v); } return f'), this); + let a = [1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,1]; + let v = SIMD.Bool8x16(...a); + assertEqVecArr(simdfunc(v), a.map(lanefunc)); +} + +unaryI('not', x => ~x << 24 >> 24); +unaryU('not', x => ~x << 24 >>> 24); +unaryB('not', x => !x); +unaryI('neg', x => -x << 24 >> 24); +unaryU('neg', x => -x << 24 >>> 24); + + +// Test binary operators. +function zipmap(a1, a2, f) { + assertEq(a1.length, a2.length); + let r = []; + for (var i = 0; i < a1.length; i++) + r.push(f(a1[i], a2[i])); + return r +} + +function binaryI(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + + `var fut = i8x16.${opname};` + + 'function f(v1, v2) { v1 = i8x16chk(v1); v2 = i8x16chk(v2); return fut(v1, v2); } return f'), this); + let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16]; + let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1]; + let ref = zipmap(a1, a2, lanefunc); + let v1 = SIMD.Int8x16(...a1); + let v2 = SIMD.Int8x16(...a2); + assertEqVecArr(simdfunc(v1, v2), ref); +} + +function binaryU(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16CHK + U8x16I8x16 + I8x16U8x16 + + `var fut = u8x16.${opname};` + + 'function f(v1, v2) { v1 = i8x16chk(v1); v2 = i8x16chk(v2); return i8x16u8x16(fut(u8x16i8x16(v1), u8x16i8x16(v2))); } return f'), this); + let a1 = [ -1,2, -3,0x80,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16].map(x => x & 0xff); + let a2 = [0x80,2,0x80,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16,0xff].map(x => x & 0xff); + let ref = zipmap(a1, a2, lanefunc); + let v1 = SIMD.Int8x16(...a1); + let v2 = SIMD.Int8x16(...a2); + let res = SIMD.Uint8x16.fromInt8x16Bits(simdfunc(v1, v2)); + assertEqVecArr(res, ref); +} + +function binaryB(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + B8x16 + B8x16CHK + + `var fut = b8x16.${opname};` + + 'function f(v1, v2) { v1 = b8x16chk(v1); v2 = b8x16chk(v2); return fut(v1, v2); } return f'), this); + let a = [1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,1]; + let v = SIMD.Bool8x16(...a); + assertEqVecArr(simdfunc(v), a.map(lanefunc)); +} + +binaryI('add', (x, y) => (x + y) << 24 >> 24); +binaryI('sub', (x, y) => (x - y) << 24 >> 24); +binaryI('mul', (x, y) => (x * y) << 24 >> 24); +binaryU('add', (x, y) => (x + y) << 24 >>> 24); +binaryU('sub', (x, y) => (x - y) << 24 >>> 24); +binaryU('mul', (x, y) => (x * y) << 24 >>> 24); + +binaryI('and', (x, y) => (x & y) << 24 >> 24); +binaryI('or', (x, y) => (x | y) << 24 >> 24); +binaryI('xor', (x, y) => (x ^ y) << 24 >> 24); +binaryU('and', (x, y) => (x & y) << 24 >>> 24); +binaryU('or', (x, y) => (x | y) << 24 >>> 24); +binaryU('xor', (x, y) => (x ^ y) << 24 >>> 24); + +function sat(x, lo, hi) { + if (x < lo) return lo; + if (x > hi) return hi; + return x +} +function isat(x) { return sat(x, -128, 127); } +function usat(x) { return sat(x, 0, 255); } + +binaryI('addSaturate', (x, y) => isat(x + y)) +binaryI('subSaturate', (x, y) => isat(x - y)) +binaryU('addSaturate', (x, y) => usat(x + y)) +binaryU('subSaturate', (x, y) => usat(x - y)) + +// Test shift operators. +function zip1map(a, s, f) { + return a.map(x => f(x, s)); +} + +function shiftI(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + + `var fut = i8x16.${opname};` + + 'function f(v, s) { v = i8x16chk(v); s = s|0; return fut(v, s); } return f'), this); + let a = [0x80,2,0x80,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16,0xff]; + let v = SIMD.Int8x16(...a); + for (let s of [0, 1, 2, 6, 7, 8, 9, 10, 16, 255, -1, -8, -7, -1000]) { + let ref = zip1map(a, s, lanefunc); + // 1. Test dynamic shift amount. + assertEqVecArr(simdfunc(v, s), ref); + + // 2. Test constant shift amount. + let cstf = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + + `var fut = i8x16.${opname};` + + `function f(v) { v = i8x16chk(v); return fut(v, ${s}); } return f`), this); + assertEqVecArr(cstf(v, s), ref); + } +} + +function shiftU(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16CHK + U8x16I8x16 + I8x16U8x16 + + `var fut = u8x16.${opname};` + + 'function f(v, s) { v = i8x16chk(v); s = s|0; return i8x16u8x16(fut(u8x16i8x16(v), s)); } return f'), this); + let a = [0x80,2,0x80,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16,0xff]; + let v = SIMD.Int8x16(...a); + for (let s of [0, 1, 2, 6, 7, 8, 9, 10, 16, 255, -1, -8, -7, -1000]) { + let ref = zip1map(a, s, lanefunc); + // 1. Test dynamic shift amount. + assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(simdfunc(v, s)), ref); + + // 2. Test constant shift amount. + let cstf = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16CHK + U8x16I8x16 + I8x16U8x16 + + `var fut = u8x16.${opname};` + + `function f(v) { v = i8x16chk(v); return i8x16u8x16(fut(u8x16i8x16(v), ${s})); } return f`), this); + assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(cstf(v, s)), ref); + } +} + +shiftI('shiftLeftByScalar', (x,s) => (x << (s & 7)) << 24 >> 24); +shiftU('shiftLeftByScalar', (x,s) => (x << (s & 7)) << 24 >>> 24); +shiftI('shiftRightByScalar', (x,s) => ((x << 24 >> 24) >> (s & 7)) << 24 >> 24); +shiftU('shiftRightByScalar', (x,s) => ((x << 24 >>> 24) >>> (s & 7)) << 24 >>> 24); + + +// Comparisons. +function compareI(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + + `var fut = i8x16.${opname};` + + 'function f(v1, v2) { v1 = i8x16chk(v1); v2 = i8x16chk(v2); return fut(v1, v2); } return f'), this); + let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16]; + let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1]; + let ref = zipmap(a1, a2, lanefunc); + let v1 = SIMD.Int8x16(...a1); + let v2 = SIMD.Int8x16(...a2); + assertEqVecArr(simdfunc(v1, v2), ref); +} + +function compareU(opname, lanefunc) { + let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + U8x16 + U8x16I8x16 + + `var fut = u8x16.${opname};` + + 'function f(v1, v2) { v1 = i8x16chk(v1); v2 = i8x16chk(v2); return fut(u8x16i8x16(v1), u8x16i8x16(v2)); } return f'), this); + let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16].map(x => x << 24 >>> 24); + let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1].map(x => x << 24 >>> 24); + let ref = zipmap(a1, a2, lanefunc); + let v1 = SIMD.Int8x16(...a1); + let v2 = SIMD.Int8x16(...a2); + assertEqVecArr(simdfunc(v1, v2), ref); +} + +compareI("equal", (x,y) => x == y); +compareU("equal", (x,y) => x == y); +compareI("notEqual", (x,y) => x != y); +compareU("notEqual", (x,y) => x != y); +compareI("lessThan", (x,y) => x < y); +compareU("lessThan", (x,y) => x < y); +compareI("lessThanOrEqual", (x,y) => x <= y); +compareU("lessThanOrEqual", (x,y) => x <= y); +compareI("greaterThan", (x,y) => x > y); +compareU("greaterThan", (x,y) => x > y); +compareI("greaterThanOrEqual", (x,y) => x >= y); +compareU("greaterThanOrEqual", (x,y) => x >= y); diff --git a/js/src/jit-test/tests/asm.js/testSIMD-bitcasts.js b/js/src/jit-test/tests/asm.js/testSIMD-bitcasts.js new file mode 100644 index 000000000..c5a5fb2bc --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testSIMD-bitcasts.js @@ -0,0 +1,84 @@ +load(libdir + "asm.js"); +load(libdir + "simd.js"); +load(libdir + "asserts.js"); + +// Set to true to see more JS debugging spew. +const DEBUG = false; + +if (!isSimdAvailable()) { + DEBUG && print("won't run tests as simd extensions aren't activated yet"); + quit(0); +} + +// Test all bit-casts and normal loads and stores. +var heap = new ArrayBuffer(BUF_MIN); +var asU8 = new Uint8Array(heap); +var allTypes = [ + "Int8x16", + "Int16x8", + "Int32x4", + "Uint8x16", + "Uint16x8", + "Uint32x4", + "Float32x4" +]; + +// Generate a load bit-cast store test function that performs: +// +// function f(a, b) { +// vec = src.load(H, a); +// cast = dst.from«src»Bits(vec); +// store(H, b, cast); +// } +// +// Here, `H` is the heap provided by `heap`. +function test_func(src, dst) { + text = ` + "use asm"; + var src = glob.SIMD.${src}; + var dst = glob.SIMD.${dst}; + var ld = src.load; + var st = dst.store; + var bc = dst.from${src}Bits; + + var H = new glob.Uint8Array(heap); + + function f(a, b) { + a = a|0; + b = b|0; + + st(H, b, bc(ld(H, a))); + } + + return f; + `; + return asmLink(asmCompile('glob', 'ffi', 'heap', text), this, null, heap); +} + +function assertBuf16(a, b) { + for (let i=0; i < 16; i++) { + assertEq(asU8[a+i], asU8[b+i]); + } +} + +for (let src of allTypes) { + for (let dst of allTypes) { + // Skip identity conversions. + if (src == dst) continue; + + print(src, dst); + let f = test_func(src, dst); + // Initialize with pseudo-random data. + for (let i = 0; i < 64; i++) { + asU8[i] = (i + 17) * 97; + } + + // Aligned load/store. + f(0, 16); + assertBuf16(0, 16); + + // Unaligned access. + f(1, 27); + assertBuf16(1, 27); + } +} diff --git a/js/src/jit-test/tests/asm.js/testSIMD-load-store.js b/js/src/jit-test/tests/asm.js/testSIMD-load-store.js new file mode 100644 index 000000000..d826c106b --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testSIMD-load-store.js @@ -0,0 +1,457 @@ +// |jit-test| +load(libdir + "asm.js"); +load(libdir + "simd.js"); +load(libdir + "asserts.js"); + +// Avoid pathological --ion-eager compile times due to bails in loops +setJitCompilerOption('ion.warmup.trigger', 1000000); + +// Set to true to see more JS debugging spew +const DEBUG = false; + +if (!isSimdAvailable() || typeof SIMD === 'undefined' || !isAsmJSCompilationAvailable()) { + DEBUG && print("won't run tests as simd extensions aren't activated yet"); + quit(0); +} + +const RuntimeError = WebAssembly.RuntimeError; + +const INT32_MAX = Math.pow(2, 31) - 1; +const INT32_MIN = INT32_MAX + 1 | 0; + +try { + +// Load / Store +var IMPORTS = USE_ASM + 'var H=new glob.Uint8Array(heap); var i4=glob.SIMD.Int32x4; var ci4=i4.check; var load=i4.load; var store=i4.store;'; + +// Bad number of args +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load();} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(3);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(3, 4, 5);} return f"); + +// Bad type of args +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(3, 5);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, 5.0);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0.;load(H, i);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var H2=new glob.Int32Array(heap); function f(){var i=0;load(H2, i)} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var H2=42; function f(){var i=0;load(H2, i)} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0;load(H2, i)} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var f4=glob.SIMD.Float32x4; function f(){var i=0;var vec=f4(1,2,3,4); store(H, i, vec)} return f"); + +// Bad coercions of returned values +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0;return load(H, i)|0;} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0;return +load(H, i);} return f"); + +// Literal index constants +var buf = new ArrayBuffer(BUF_MIN); +var SIZE_TA = BUF_MIN >> 2 +var asI32 = new Int32Array(buf); +asI32[SIZE_TA - 4] = 4; +asI32[SIZE_TA - 3] = 3; +asI32[SIZE_TA - 2] = 2; +asI32[SIZE_TA - 1] = 1; + +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, -1);} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1) + ");} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1 - 15) + ");} return f"); +asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1 - 16) + ");} return f"); + +assertAsmLinkFail(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + (BUF_MIN - 15) + "));} return f"), this, {}, buf); +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + (BUF_MIN - 16) + "));} return f"), this, {}, buf)(), [4, 3, 2, 1]); +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + BUF_MIN + " - 16 | 0));} return f"), this, {}, buf)(), [4, 3, 2, 1]); + +var CONSTANT_INDEX = 42; +var CONSTANT_BYTE_INDEX = CONSTANT_INDEX << 2; + +var loadStoreCode = ` + "use asm"; + + var H = new glob.Uint8Array(heap); + + var i4 = glob.SIMD.Int32x4; + var i4load = i4.load; + var i4store = i4.store; + var ci4 = i4.check; + + var f4 = glob.SIMD.Float32x4; + var f4load = f4.load; + var f4store = f4.store; + var cf4 = f4.check; + + function f32l(i) { i=i|0; return cf4(f4load(H, i|0)); } + function f32lcst() { return cf4(f4load(H, ${CONSTANT_BYTE_INDEX})); } + function f32s(i, vec) { i=i|0; vec=cf4(vec); f4store(H, i|0, vec); } + function f32scst(vec) { vec=cf4(vec); f4store(H, ${CONSTANT_BYTE_INDEX}, vec); } + + function i32l(i) { i=i|0; return ci4(i4load(H, i|0)); } + function i32lcst() { return ci4(i4load(H, ${CONSTANT_BYTE_INDEX})); } + function i32s(i, vec) { i=i|0; vec=ci4(vec); i4store(H, i|0, vec); } + function i32scst(vec) { vec=ci4(vec); i4store(H, ${CONSTANT_BYTE_INDEX}, vec); } + + function f32lbndcheck(i) { + i=i|0; + if ((i|0) > ${CONSTANT_BYTE_INDEX}) i=${CONSTANT_BYTE_INDEX}; + if ((i|0) < 0) i = 0; + return cf4(f4load(H, i|0)); + } + function f32sbndcheck(i, vec) { + i=i|0; + vec=cf4(vec); + if ((i|0) > ${CONSTANT_BYTE_INDEX}) i=${CONSTANT_BYTE_INDEX}; + if ((i|0) < 0) i = 0; + return cf4(f4store(H, i|0, vec)); + } + + return { + f32l: f32l, + f32lcst: f32lcst, + f32s: f32s, + f32scst: f32scst, + f32lbndcheck: f32lbndcheck, + f32sbndcheck: f32sbndcheck, + i32l: i32l, + i32lcst: i32lcst, + i32s: i32s, + i32scst: i32scst + } +`; + +const SIZE = 0x8000; + +var F32 = new Float32Array(SIZE); +var reset = function() { + for (var i = 0; i < SIZE; i++) + F32[i] = i + 1; +}; +reset(); + +var buf = F32.buffer; +var m = asmLink(asmCompile('glob', 'ffi', 'heap', loadStoreCode), this, null, buf); + +function slice(TA, i, n) { return Array.prototype.slice.call(TA, i, i + n); } + +// Float32x4.load +function f32l(n) { return m.f32l((n|0) << 2 | 0); }; + +// Correct accesses +assertEqX4(f32l(0), slice(F32, 0, 4)); +assertEqX4(f32l(1), slice(F32, 1, 4)); +assertEqX4(f32l(SIZE - 4), slice(F32, SIZE - 4, 4)); + +assertEqX4(m.f32lcst(), slice(F32, CONSTANT_INDEX, 4)); +assertEqX4(m.f32lbndcheck(CONSTANT_BYTE_INDEX), slice(F32, CONSTANT_INDEX, 4)); + +// OOB +assertThrowsInstanceOf(() => f32l(-1), RuntimeError); +assertThrowsInstanceOf(() => f32l(SIZE), RuntimeError); +assertThrowsInstanceOf(() => f32l(SIZE - 1), RuntimeError); +assertThrowsInstanceOf(() => f32l(SIZE - 2), RuntimeError); +assertThrowsInstanceOf(() => f32l(SIZE - 3), RuntimeError); + +var code = ` + "use asm"; + var f4 = glob.SIMD.Float32x4; + var f4l = f4.load; + var u8 = new glob.Uint8Array(heap); + + function g(x) { + x = x|0; + // set a constraint on the size of the heap + var ptr = 0; + ptr = u8[0xFFFF] | 0; + // give a precise range to x + x = (x>>0) > 5 ? 5 : x; + x = (x>>0) < 0 ? 0 : x; + // ptr value gets a precise range but the bounds check shouldn't get + // eliminated. + return f4l(u8, 0xFFFA + x | 0); + } + + return g; +`; +assertThrowsInstanceOf(() => asmLink(asmCompile('glob', 'ffi', 'heap', code), this, {}, new ArrayBuffer(0x10000))(0), RuntimeError); + +// Float32x4.store +function f32s(n, v) { return m.f32s((n|0) << 2 | 0, v); }; + +var vec = SIMD.Float32x4(5,6,7,8); +var vec2 = SIMD.Float32x4(0,1,2,3); +var vecWithNaN = SIMD.Float32x4(NaN, 2, NaN, 4); + +reset(); +f32s(0, vec); +assertEqX4(vec, slice(F32, 0, 4)); + +reset(); +f32s(0, vec2); +assertEqX4(vec2, slice(F32, 0, 4)); + +reset(); +f32s(4, vec); +assertEqX4(vec, slice(F32, 4, 4)); + +reset(); +f32s(4, vecWithNaN); +assertEqX4(vecWithNaN, slice(F32, 4, 4)); + +reset(); +m.f32scst(vec2); +assertEqX4(vec2, slice(F32, CONSTANT_INDEX, 4)); + +reset(); +m.f32sbndcheck(CONSTANT_BYTE_INDEX, vec); +assertEqX4(vec, slice(F32, CONSTANT_INDEX, 4)); + +// OOB +reset(); +assertThrowsInstanceOf(() => f32s(SIZE - 3, vec), RuntimeError); +assertThrowsInstanceOf(() => f32s(SIZE - 2, vec), RuntimeError); +assertThrowsInstanceOf(() => f32s(SIZE - 1, vec), RuntimeError); +assertThrowsInstanceOf(() => f32s(SIZE, vec), RuntimeError); +for (var i = 0; i < SIZE; i++) + assertEq(F32[i], i + 1); + +// Int32x4.load +var I32 = new Int32Array(buf); +reset = function () { + for (var i = 0; i < SIZE; i++) + I32[i] = i + 1; +}; +reset(); + +function i32(n) { return m.i32l((n|0) << 2 | 0); }; + +// Correct accesses +assertEqX4(i32(0), slice(I32, 0, 4)); +assertEqX4(i32(1), slice(I32, 1, 4)); +assertEqX4(i32(SIZE - 4), slice(I32, SIZE - 4, 4)); + +assertEqX4(m.i32lcst(), slice(I32, CONSTANT_INDEX, 4)); + +// OOB +assertThrowsInstanceOf(() => i32(-1), RuntimeError); +assertThrowsInstanceOf(() => i32(SIZE), RuntimeError); +assertThrowsInstanceOf(() => i32(SIZE - 1), RuntimeError); +assertThrowsInstanceOf(() => i32(SIZE - 2), RuntimeError); +assertThrowsInstanceOf(() => i32(SIZE - 3), RuntimeError); + +// Int32x4.store +function i32s(n, v) { return m.i32s((n|0) << 2 | 0, v); }; + +var vec = SIMD.Int32x4(5,6,7,8); +var vec2 = SIMD.Int32x4(0,1,2,3); + +reset(); +i32s(0, vec); +assertEqX4(vec, slice(I32, 0, 4)); + +reset(); +i32s(0, vec2); +assertEqX4(vec2, slice(I32, 0, 4)); + +reset(); +i32s(4, vec); +assertEqX4(vec, slice(I32, 4, 4)); + +reset(); +m.i32scst(vec2); +assertEqX4(vec2, slice(I32, CONSTANT_INDEX, 4)); + +// OOB +reset(); +assertThrowsInstanceOf(() => i32s(SIZE - 3, vec), RuntimeError); +assertThrowsInstanceOf(() => i32s(SIZE - 2, vec), RuntimeError); +assertThrowsInstanceOf(() => i32s(SIZE - 1, vec), RuntimeError); +assertThrowsInstanceOf(() => i32s(SIZE - 0, vec), RuntimeError); +for (var i = 0; i < SIZE; i++) + assertEq(I32[i], i + 1); + +// Partial loads and stores +(function() { + +// Variable indexes +function MakeCodeFor(typeName) { + return ` + "use asm"; + var type = glob.SIMD.${typeName}; + var c = type.check; + + var l1 = type.load1; + var l2 = type.load2; + + var s1 = type.store1; + var s2 = type.store2; + + var u8 = new glob.Uint8Array(heap); + + function load1(i) { i=i|0; return l1(u8, i); } + function load2(i) { i=i|0; return l2(u8, i); } + + function loadCst1() { return l1(u8, 41 << 2); } + function loadCst2() { return l2(u8, 41 << 2); } + + function store1(i, x) { i=i|0; x=c(x); return s1(u8, i, x); } + function store2(i, x) { i=i|0; x=c(x); return s2(u8, i, x); } + + function storeCst1(x) { x=c(x); return s1(u8, 41 << 2, x); } + function storeCst2(x) { x=c(x); return s2(u8, 41 << 2, x); } + + return { + load1: load1, + load2: load2, + loadCst1: loadCst1, + loadCst2: loadCst2, + store1: store1, + store2: store2, + storeCst1: storeCst1, + storeCst2: storeCst2, + } +`; +} + +var SIZE = 0x10000; + +function TestPartialLoads(m, typedArray, x, y, z, w) { + // Fill array with predictable values + for (var i = 0; i < SIZE; i += 4) { + typedArray[i] = x(i); + typedArray[i + 1] = y(i); + typedArray[i + 2] = z(i); + typedArray[i + 3] = w(i); + } + + // Test correct loads + var i = 0, j = 0; // i in elems, j in bytes + assertEqX4(m.load1(j), [x(i), 0, 0, 0]); + assertEqX4(m.load2(j), [x(i), y(i), 0, 0]); + + j += 4; + assertEqX4(m.load1(j), [y(i), 0, 0, 0]); + assertEqX4(m.load2(j), [y(i), z(i), 0, 0]); + + j += 4; + assertEqX4(m.load1(j), [z(i), 0, 0, 0]); + assertEqX4(m.load2(j), [z(i), w(i), 0, 0]); + + j += 4; + assertEqX4(m.load1(j), [w(i), 0, 0, 0]); + assertEqX4(m.load2(j), [w(i), x(i+4), 0, 0]); + + j += 4; + i += 4; + assertEqX4(m.load1(j), [x(i), 0, 0, 0]); + assertEqX4(m.load2(j), [x(i), y(i), 0, 0]); + + // Test loads with constant indexes (41) + assertEqX4(m.loadCst1(), [y(40), 0, 0, 0]); + assertEqX4(m.loadCst2(), [y(40), z(40), 0, 0]); + + // Test limit and OOB accesses + assertEqX4(m.load1((SIZE - 1) << 2), [w(SIZE - 4), 0, 0, 0]); + assertThrowsInstanceOf(() => m.load1(((SIZE - 1) << 2) + 1), RuntimeError); + + assertEqX4(m.load2((SIZE - 2) << 2), [z(SIZE - 4), w(SIZE - 4), 0, 0]); + assertThrowsInstanceOf(() => m.load2(((SIZE - 2) << 2) + 1), RuntimeError); +} + +// Partial stores +function TestPartialStores(m, typedArray, typeName, x, y, z, w) { + var val = SIMD[typeName](x, y, z, w); + + function Reset() { + for (var i = 0; i < SIZE; i++) + typedArray[i] = i + 1; + } + function CheckNotModified(low, high) { + for (var i = low; i < high; i++) + assertEq(typedArray[i], i + 1); + } + + function TestStore1(i) { + m.store1(i, val); + CheckNotModified(0, i >> 2); + assertEq(typedArray[i >> 2], x); + CheckNotModified((i >> 2) + 1, SIZE); + typedArray[i >> 2] = (i >> 2) + 1; + } + + function TestStore2(i) { + m.store2(i, val); + CheckNotModified(0, i >> 2); + assertEq(typedArray[i >> 2], x); + assertEq(typedArray[(i >> 2) + 1], y); + CheckNotModified((i >> 2) + 2, SIZE); + typedArray[i >> 2] = (i >> 2) + 1; + typedArray[(i >> 2) + 1] = (i >> 2) + 2; + } + + function TestOOBStore(f) { + assertThrowsInstanceOf(f, RuntimeError); + CheckNotModified(0, SIZE); + } + + Reset(); + + TestStore1(0); + TestStore1(1 << 2); + TestStore1(2 << 2); + TestStore1(3 << 2); + TestStore1(1337 << 2); + + var i = (SIZE - 1) << 2; + TestStore1(i); + TestOOBStore(() => m.store1(i + 1, val)); + TestOOBStore(() => m.store1(-1, val)); + + TestStore2(0); + TestStore2(1 << 2); + TestStore2(2 << 2); + TestStore2(3 << 2); + TestStore2(1337 << 2); + + var i = (SIZE - 2) << 2; + TestStore2(i); + TestOOBStore(() => m.store2(i + 1, val)); + TestOOBStore(() => m.store2(-1, val)); + + // Constant indexes (41) + m.storeCst1(val); + CheckNotModified(0, 41); + assertEq(typedArray[41], x); + CheckNotModified(42, SIZE); + typedArray[41] = 42; + + m.storeCst2(val); + CheckNotModified(0, 41); + assertEq(typedArray[41], x); + assertEq(typedArray[42], y); + CheckNotModified(43, SIZE); + typedArray[41] = 42; + typedArray[42] = 43; +} + +var f32 = new Float32Array(SIZE); +var mFloat32x4 = asmLink(asmCompile('glob', 'ffi', 'heap', MakeCodeFor('Float32x4')), this, null, f32.buffer); + +TestPartialLoads(mFloat32x4, f32, + (i) => i + 1, + (i) => Math.fround(13.37), + (i) => Math.fround(1/i), + (i) => Math.fround(Math.sqrt(0x2000 - i))); + +TestPartialStores(mFloat32x4, f32, 'Float32x4', 42, -0, NaN, 0.1337); + +var i32 = new Int32Array(f32.buffer); +var mInt32x4 = asmLink(asmCompile('glob', 'ffi', 'heap', MakeCodeFor('Int32x4')), this, null, i32.buffer); + +TestPartialLoads(mInt32x4, i32, + (i) => i + 1 | 0, + (i) => -i | 0, + (i) => i * 2 | 0, + (i) => 42); + +TestPartialStores(mInt32x4, i32, 'Int32x4', 42, -3, 13, 37); + +})(); + +} catch (e) { print('stack: ', e.stack); throw e } diff --git a/js/src/jit-test/tests/asm.js/testSIMD.js b/js/src/jit-test/tests/asm.js/testSIMD.js new file mode 100644 index 000000000..29786bc52 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testSIMD.js @@ -0,0 +1,1575 @@ +load(libdir + "asm.js"); +load(libdir + "simd.js"); +load(libdir + "asserts.js"); +var heap = new ArrayBuffer(0x10000); + +// Avoid pathological --ion-eager compile times due to bails in loops +setJitCompilerOption('ion.warmup.trigger', 1000000); + +// Set to true to see more JS debugging spew +const DEBUG = false; + +if (!isSimdAvailable() || typeof SIMD === 'undefined' || !isAsmJSCompilationAvailable()) { + DEBUG && print("won't run tests as simd extensions aren't activated yet"); + quit(0); +} + +const I32 = 'var i4 = glob.SIMD.Int32x4;' +const CI32 = 'var ci4 = i4.check;' +const I32A = 'var i4a = i4.add;' +const I32S = 'var i4s = i4.sub;' +const I32M = 'var i4m = i4.mul;' +const I32U32 = 'var i4u4 = i4.fromUint32x4Bits;' + +const U32 = 'var u4 = glob.SIMD.Uint32x4;' +const CU32 = 'var cu4 = u4.check;' +const U32A = 'var u4a = u4.add;' +const U32S = 'var u4s = u4.sub;' +const U32M = 'var u4m = u4.mul;' +const U32I32 = 'var u4i4 = u4.fromInt32x4Bits;' + +const F32 = 'var f4 = glob.SIMD.Float32x4;' +const CF32 = 'var cf4 = f4.check;' +const F32A = 'var f4a = f4.add;' +const F32S = 'var f4s = f4.sub;' +const F32M = 'var f4m = f4.mul;' +const F32D = 'var f4d = f4.div;' +const FROUND = 'var f32=glob.Math.fround;' +const B32 = 'var b4 = glob.SIMD.Bool32x4;' +const CB32 = 'var cb4 = b4.check;' + +const EXTI4 = 'var e = i4.extractLane;' +const EXTU4 = 'var e = u4.extractLane;' +const EXTF4 = 'var e = f4.extractLane;' +const EXTB4 = 'var e = b4.extractLane;' + +// anyTrue / allTrue on boolean vectors. +const ANYB4 = 'var anyt=b4.anyTrue;' +const ALLB4 = 'var allt=b4.allTrue;' + +const INT32_MAX = Math.pow(2, 31) - 1; +const INT32_MIN = INT32_MAX + 1 | 0; +const UINT32_MAX = Math.pow(2, 32) - 1; + +const assertEqFFI = {assertEq:assertEq}; + +function CheckI4(header, code, expected) { + // code needs to contain a local called x + header = USE_ASM + I32 + CI32 + EXTI4 + F32 + header; + var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return ci4(x)} return f'), this)(); + assertEqX4(observed, expected); +} + +function CheckU4(header, code, expected) { + // code needs to contain a local called x. + header = USE_ASM + U32 + CU32 + EXTU4 + I32 + CI32 + I32U32 + header; + var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return ci4(i4u4(x))} return f'), this)(); + // We can't return an unsigned SIMD type. Return Int32x4, convert to unsigned here. + observed = SIMD.Uint32x4.fromInt32x4Bits(observed) + assertEqX4(observed, expected); +} + +function CheckF4(header, code, expected) { + // code needs to contain a local called x + header = USE_ASM + F32 + CF32 + EXTF4 + header; + var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return cf4(x)} return f'), this)(); + assertEqX4(observed, expected.map(Math.fround)); +} + +function CheckB4(header, code, expected) { + // code needs to contain a local called x + header = USE_ASM + B32 + CB32 + header; + var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return cb4(x)} return f'), this)(); + assertEqX4(observed, expected); +} + +try { + +// 1. Constructors + +// 1.1 Compilation +assertAsmTypeFail('glob', USE_ASM + "var i4 = Int32x4 ; return {}") ; +assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.Int32x4 ; return {}") ; +assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.globglob.Int32x4 ; return {}") ; +assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.Math.Int32x4 ; return {}") ; +assertAsmTypeFail('glob', USE_ASM + "var herd = glob.SIMD.ponyX4 ; return {}") ; + +// 1.2 Linking +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: 42}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: Math.fround}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: 42}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: Math.fround}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: new Array}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: SIMD.Float32x4}}); + +var [Type, int32] = [TypedObject.StructType, TypedObject.int32]; +var MyStruct = new Type({'x': int32, 'y': int32, 'z': int32, 'w': int32}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: MyStruct}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: new MyStruct}}); + +assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {} return f"), {SIMD:{Int32x4: SIMD.Int32x4}})(), undefined); + +assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: 42}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: Math.fround}}); +assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: new Array}}); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {} return f"), {SIMD:{Float32x4: SIMD.Float32x4}})(), undefined); + +// 1.3 Correctness +// 1.3.1 Local variables declarations +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Int32x4(1,2,3,4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4();} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1, 2);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1, 2, 3);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1, 2, 3, 4.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1, 2.0, 3, 4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4a(1,2,3,4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,2+2|0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3," + (INT32_MIN - 1) + ");} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(i4(1,2,3,4));} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4);} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3," + (INT32_MAX + 1) + ");} return f"), this)(), undefined); + +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4();} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1.,2.,3.);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1.,2.,f32(3.),4.);} return f"); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1.,2.,3.,4.);} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4);} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3," + (INT32_MIN - 1) + ");} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3," + (INT32_MAX + 1) + ");} return f"), this)(), undefined); + +// Places where NumLit can creep in +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(i) {i=i|0; var z=0; switch(i|0) {case i4(1,2,3,4): z=1; break; default: z=2; break;}} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(i) {i=i|0; var z=0; return i * i4(1,2,3,4) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(i) {var x=i4(1,2,3,i4(4,5,6,7))} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(i) {var x=i4(1,2,3,f4(4,5,6,7))} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(i) {var x=f4(1,2,3,i4(4,5,6,7))} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return +i4(1,2,3,4)} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4)|0} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f() {return f32(i4(1,2,3,4))} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "function f() {return cf4(i4(1,2,3,4))} return f"); + +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return +f4(1,2,3,4)} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4)|0} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + FROUND + "function f() {return f32(f4(1,2,3,4))} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + "function f() {return ci4(f4(1,2,3,4))} return f"); + +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f() {return ci4(i4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f() {return cf4(f4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]); + +assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {i4(1,2,3,4);} return f"), this)(), undefined); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {f4(1,2,3,4);} return f"), this)(), undefined); + +// Int32x4 ctor should accept int? +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + CI32 + "var i32=new glob.Int32Array(heap); function f(i) {i=i|0; return ci4(i4(i32[i>>2], 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [0, 2, 3, 4]); +// Float32x4 ctor should accept floatish (i.e. float || float? || floatish) and doublit +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + FROUND + "var h=new glob.Float32Array(heap); function f(i) {i=i|0; return cf4(f4(h[i>>2], f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [NaN, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + FROUND + "function f(i) {i=i|0; return cf4(f4(f32(1) + f32(2), f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + FROUND + "function f(i) {i=i|0; return cf4(f4(f32(1) + f32(2), 2.0, 3.0, 4.0))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]); +// Bool32x4 ctor should accept int? +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + B32 + CB32 + "var i32=new glob.Int32Array(heap); function f(i) {i=i|0; return cb4(b4(i32[i>>2], 2, 0, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [false, true, false, true]); + +// 1.3.2 Getters - Reading values out of lanes +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=1; return e(x,1) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=1; return e(x + x, 1) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=1.; return e(x, 1) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + EXTF4 + "var f32=glob.Math.fround;" + I32 + "function f() {var x=f32(1); return e(x, 1) | 0;} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return x.length|0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=e(i4(1,2,3,4),1); return x|0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return (e(x,0) > (1>>>0)) | 0;} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return e(x,-1) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return e(x,4) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return e(x,.5) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return e(x,x) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTF4 + "function f() {var x=i4(1,2,3,4); return e(x,0) | 0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); var i=0; return e(x,i) | 0;} return f"); + +// The signMask property is no longer supported. Replaced by allTrue / anyTrue. +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=42; return x.signMask;} return f"); +assertAsmTypeFail('glob', USE_ASM + "function f() {var x=42.; return x.signMask;} return f"); +assertAsmTypeFail('glob', USE_ASM + FROUND + "function f() {var x=f32(42.); return x.signMask;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + 'function f() { var x=i4(1,2,3,4); return x.signMask | 0 } return f'); +assertAsmTypeFail('glob', USE_ASM + U32 + 'function f() { var x=u4(1,2,3,4); return x.signMask | 0 } return f'); +assertAsmTypeFail('glob', USE_ASM + F32 + FROUND + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(f32(1), f32(-13.37), f32(42), f32(-Infinity)); return x.signMask | 0 } return f'); + +// Check lane extraction. +function CheckLanes(innerBody, type, expected) { + var coerceBefore, coerceAfter, extractLane; + + if (type === SIMD.Int32x4) { + coerceBefore = ''; + coerceAfter = '|0'; + extractLane = 'ei'; + } else if (type === SIMD.Uint32x4) { + // Coerce Uint32 lanes to double so they can be legally returned. + coerceBefore = '+'; + coerceAfter = ''; + extractLane = 'eu'; + } else if (type === SIMD.Float32x4) { + coerceBefore = '+'; + coerceAfter = ''; + extractLane = 'ef'; + expected = expected.map(Math.fround); + } else if (type === SIMD.Bool32x4) { + coerceBefore = ''; + coerceAfter = '|0'; + extractLane = 'eb'; + } else throw "unexpected type in CheckLanes"; + + for (var i = 0; i < 4; i++) { + var lane = i; + var laneCheckCode = `"use asm"; + var i4=glob.SIMD.Int32x4; + var u4=glob.SIMD.Uint32x4; + var f4=glob.SIMD.Float32x4; + var b4=glob.SIMD.Bool32x4; + var ei=i4.extractLane; + var eu=u4.extractLane; + var ef=f4.extractLane; + var eb=b4.extractLane; + function f() {${innerBody}; return ${coerceBefore}${extractLane}(x, ${lane})${coerceAfter} } + return f;`; + assertEq(asmLink(asmCompile('glob', laneCheckCode), this)(), expected[i]); + } +} +function CheckLanesI4(innerBody, expected) { return CheckLanes(innerBody, SIMD.Int32x4, expected); } +function CheckLanesU4(innerBody, expected) { return CheckLanes(innerBody, SIMD.Uint32x4, expected); } +function CheckLanesF4(innerBody, expected) { return CheckLanes(innerBody, SIMD.Float32x4, expected); } +function CheckLanesB4(innerBody, expected) { return CheckLanes(innerBody, SIMD.Bool32x4, expected); } + +CheckLanesI4('var x=i4(0,0,0,0);', [0,0,0,0]); +CheckLanesI4('var x=i4(1,2,3,4);', [1,2,3,4]); +CheckLanesI4('var x=i4(' + INT32_MIN + ',2,3,' + INT32_MAX + ')', [INT32_MIN,2,3,INT32_MAX]); +CheckLanesI4('var x=i4(1,2,3,4); var y=i4(5,6,7,8)', [1,2,3,4]); +CheckLanesI4('var a=1; var b=i4(9,8,7,6); var c=13.37; var x=i4(1,2,3,4); var y=i4(5,6,7,8)', [1,2,3,4]); +CheckLanesI4('var y=i4(5,6,7,8); var x=i4(1,2,3,4)', [1,2,3,4]); + +CheckLanesU4('var x=u4(0,0,0,0);', [0,0,0,0]); +CheckLanesU4('var x=u4(1,2,3,4000000000);', [1,2,3,4000000000]); +CheckLanesU4('var x=u4(' + INT32_MIN + ',2,3,' + UINT32_MAX + ')', [INT32_MIN>>>0,2,3,UINT32_MAX]); +CheckLanesU4('var x=u4(1,2,3,4); var y=u4(5,6,7,8)', [1,2,3,4]); +CheckLanesU4('var a=1; var b=u4(9,8,7,6); var c=13.37; var x=u4(1,2,3,4); var y=u4(5,6,7,8)', [1,2,3,4]); +CheckLanesU4('var y=u4(5,6,7,8); var x=u4(1,2,3,4)', [1,2,3,4]); + +CheckLanesF4('var x=f4(' + INT32_MAX + ', 2, 3, ' + INT32_MIN + ')', [INT32_MAX, 2, 3, INT32_MIN]); +CheckLanesF4('var x=f4(' + (INT32_MAX + 1) + ', 2, 3, 4)', [INT32_MAX + 1, 2, 3, 4]); +CheckLanesF4('var x=f4(1.3, 2.4, 3.5, 98.76)', [1.3, 2.4, 3.5, 98.76]); +CheckLanesF4('var x=f4(13.37, 2., 3., -0)', [13.37, 2, 3, -0]); + +CheckLanesB4('var x=b4(0,0,0,0);', [0,0,0,0]); +CheckLanesB4('var x=b4(0,1,0,0);', [0,1,0,0]); +CheckLanesB4('var x=b4(0,2,0,0);', [0,1,0,0]); +CheckLanesB4('var x=b4(-1,0,1,-1);', [1,0,1,1]); + +// 1.3.3. Variable assignments +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4();} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2, 3);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1.0, 2, 3, 4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2.0, 3, 4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2, 3.0, 4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2, 3, 4.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2, 3, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); var c=4.0; x=i4(1, 2, 3, +c);} return f"); + +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + I32 + "var i32=new glob.Int32Array(heap); function f() {var x=i4(1,2,3,4); i32[0] = x;} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + I32 + "var i32=new glob.Int32Array(heap); function f() {var x=i4(1,2,3,4); x = i32[0];} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + F32 + "var f32=new glob.Float32Array(heap); function f() {var x=f4(1,2,3,4); f32[0] = x;} return f"); +assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + F32 + "var f32=new glob.Int32Array(heap); function f() {var x=f4(1,2,3,4); x = f32[0];} return f"); + +CheckI4('', 'var x=i4(1,2,3,4); x=i4(5,6,7,8)', [5, 6, 7, 8]); +CheckI4('', 'var x=i4(1,2,3,4); var c=6; x=i4(5,c|0,7,8)', [5, 6, 7, 8]); +CheckI4('', 'var x=i4(8,7,6,5); x=i4(e(x,3)|0,e(x,2)|0,e(x,1)|0,e(x,0)|0)', [5, 6, 7, 8]); + +CheckU4('', 'var x=u4(1,2,3,4); x=u4(5,6,7,4000000000)', [5, 6, 7, 4000000000]); +CheckU4('', 'var x=u4(1,2,3,4); var c=6; x=u4(5,c|0,7,8)', [5, 6, 7, 8]); +CheckU4('', 'var x=u4(8,7,6,5); x=u4(e(x,3)|0,e(x,2)|0,e(x,1)|0,e(x,0)|0)', [5, 6, 7, 8]); + +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=f4(1,2,3,c);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=f4(1.,2.,3.,c);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4.; x=f4(1,2,3,c);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4.; x=f4(1.,2.,3.,c);} return f"); + +CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(7.); x=f4(f32(5),f32(6),y,f32(8))', [5, 6, 7, 8]); +CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5),f32(6),f32(7),f32(8))', [5, 6, 7, 8]); +CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5.),f32(6.),f32(7.),f32(8.))', [5, 6, 7, 8]); +CheckF4('', 'var x=f4(1.,2.,3.,4.); x=f4(5.,6.,7.,8.)', [5, 6, 7, 8]); +CheckF4('', 'var x=f4(1.,2.,3.,4.); x=f4(1,2,3,4)', [1, 2, 3, 4]); +CheckF4(FROUND, 'var x=f4(1.,2.,3.,4.); var y=f32(7.); x=f4(9, 4, 2, 1)', [9, 4, 2, 1]); +CheckF4('', 'var x=f4(8.,7.,6.,5.); x=f4(e(x,3),e(x,2),e(x,1),e(x,0))', [5, 6, 7, 8]); + +// Optimization for all lanes from the same definition. +CheckI4('', 'var x=i4(1,2,3,4); var c=6; x=i4(c|0,c|0,c|0,c|0)', [6, 6, 6, 6]); +CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(7.); x=f4(y,y,y,y)', [7, 7, 7, 7]); +CheckI4('', 'var x=i4(1,2,3,4); var c=0; c=e(x,3)|0; x=i4(c,c,c,c)', [4, 4, 4, 4]); +CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(0); y=e(x,2); x=f4(y,y,y,y)', [3, 3, 3, 3]); +CheckI4('', 'var x=i4(1,2,3,4); var c=0; var d=0; c=e(x,3)|0; d=e(x,3)|0; x=i4(c,d,d,c)', [4, 4, 4, 4]); +CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(0); var z=f32(0); y=e(x,2); z=e(x,2); x=f4(y,z,y,z)', [3, 3, 3, 3]); + +// Uses in ternary conditionals +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; c=x?c:c;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=1?x:c;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=1?c:x;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4); var y=i4(1,2,3,4); x=1?x:y;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f"); +assertAsmTypeFail('glob', USE_ASM + B32 + I32 + "function f() {var x=b4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f"); +assertAsmTypeFail('glob', USE_ASM + U32 + I32 + "function f() {var x=u4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f"); +assertAsmTypeFail('glob', USE_ASM + U32 + I32 + "function f() {var x=i4(1,2,3,4); var y=u4(1,2,3,4); x=1?y:y;} return f"); + +CheckF4('', 'var x=f4(1,2,3,4); var y=f4(4,3,2,1); x=3?y:x', [4, 3, 2, 1]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=x|0; var v=f4(1,2,3,4); var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(1), [5,6,7,8]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v) {v=cf4(v); var w=f4(5,6,7,8); return cf4(4?w:v);} return f"), this)(SIMD.Float32x4(1,2,3,4)), [5,6,7,8]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v, x) {v=cf4(v); x=x|0; var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(SIMD.Float32x4(1,2,3,4), 0), [1,2,3,4]); + +CheckI4('', 'var x=i4(1,2,3,4); var y=i4(4,3,2,1); x=e(x,0)?y:x', [4, 3, 2, 1]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=x|0; var v=i4(1,2,3,4); var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(1), [5,6,7,8]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v) {v=ci4(v); var w=i4(5,6,7,8); return ci4(4?w:v);} return f"), this)(SIMD.Int32x4(1,2,3,4)), [5,6,7,8]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v, x) {v=ci4(v); x=x|0; var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(SIMD.Int32x4(1,2,3,4), 0), [1,2,3,4]); + +// Unsigned SIMD types can't be function arguments or return values. +assertAsmTypeFail('glob', USE_ASM + U32 + CU32 + "function f(x) {x=cu4(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + U32 + CU32 + "function f() {x=u4(0,0,0,0); return cu4(x);} return f"); + +// 1.3.4 Return values +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1; return ci4(x)} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1; return ci4(x + x)} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1.; return ci4(x)} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + "function f() {var x=f32(1.); return ci4(x)} return f"); + +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f() {var x=i4(1,2,3,4); return ci4(x)} return f"), this)(), [1,2,3,4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f() {var x=f4(1,2,3,4); return cf4(x)} return f"), this)(), [1,2,3,4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + "function f() {var x=b4(1,2,0,4); return cb4(x)} return f"), this)(), [true,true,false,true]); + +// 1.3.5 Coerce and pass arguments +// Via check +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4();} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); ci4(x, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4(1.);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + "function f() {ci4(f32(1.));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + CF32 + "function f(x) {x=cf4(x); ci4(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return 1 + ci4(x) | 0;} return f"); + +var i32x4 = SIMD.Int32x4(1, 3, 3, 7); +assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x)} return f"), this)(i32x4), undefined); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return ci4(x);} return f"), this)(i32x4), [1,3,3,7]); + +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4();} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); cf4(x, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4(1.);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + FROUND + "function f() {cf4(f32(1.));} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + F32 + CF32 + "function f(x) {x=cf4(x); cf4(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return 1 + cf4(x) | 0;} return f"); + +var f32x4 = SIMD.Float32x4(13.37, 42.42, -0, NaN); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x)} return f"), this)(f32x4), undefined); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return cf4(x);} return f"), this)(f32x4), [13.37, 42.42, -0, NaN].map(Math.fround)); + +var b32x4 = SIMD.Bool32x4(true, false, false, true); +assertEq(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + "function f(x) {x=cb4(x)} return f"), this)(b32x4), undefined); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + "function f(x) {x=cb4(x); return cb4(x);} return f"), this)(b32x4), [true, false, false, true]); + +// Legacy coercions +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4();} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4(1,2,3,4);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x,y) {x=i4(y);y=+y} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return i4(x);} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return +i4(1,2,3,4)} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return 0|i4(1,2,3,4)} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f(x) {return f32(i4(1,2,3,4))} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(x) {return f4(i4(1,2,3,4))} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return f4(x);} return f"); + + +function assertCaught(f) { + var caught = false; + try { + f.apply(null, Array.prototype.slice.call(arguments, 1)); + } catch (e) { + DEBUG && print('Assert caught: ', e, '\n', e.stack); + assertEq(e instanceof TypeError, true); + caught = true; + } + assertEq(caught, true); +} + +var f = asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return cf4(x);} return f"), this); +assertCaught(f); +assertCaught(f, 1); +assertCaught(f, {}); +assertCaught(f, "I sincerely am a SIMD typed object."); +assertCaught(f, SIMD.Int32x4(1,2,3,4)); +assertCaught(f, SIMD.Bool32x4(true, true, false, true)); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return ci4(x);} return f"), this); +assertCaught(f); +assertCaught(f, 1); +assertCaught(f, {}); +assertCaught(f, "I sincerely am a SIMD typed object."); +assertCaught(f, SIMD.Float32x4(4,3,2,1)); +assertCaught(f, SIMD.Bool32x4(true, true, false, true)); + +var f = asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + "function f(x) {x=cb4(x); return cb4(x);} return f"), this); +assertCaught(f); +assertCaught(f, 1); +assertCaught(f, {}); +assertCaught(f, "I sincerely am a SIMD typed object."); +assertCaught(f, SIMD.Int32x4(1,2,3,4)); +assertCaught(f, SIMD.Float32x4(4,3,2,1)); + +// 1.3.6 Globals +// 1.3.6.1 Local globals +// Read +assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); function f() {var x=4; x=g|0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); function f() {var x=4.; x=+g;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); var f32=glob.Math.fround; function f() {var x=f32(4.); x=f32(g);} return f"); + +assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4; x=g|0;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4.; x=+g;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); var f32=glob.Math.fround; function f() {var x=f32(4.); x=f32(g);} return f"); + +assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CI32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); x=ci4(g);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); x=cf4(g);} return f"); +assertAsmTypeFail('glob', USE_ASM + U32 + I32 + CI32 + "var g=u4(1,2,3,4); function f() {var x=i4(1,2,3,4); x=ci4(g);} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + "var g=0; function f() {var x=i4(1,2,3,4); x=g|0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var g=0.; function f() {var x=i4(1,2,3,4); x=+g;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var f32=glob.Math.fround; var g=f32(0.); function f() {var x=i4(1,2,3,4); x=f32(g);} return f"); + +// Unsigned SIMD globals are not allowed. +assertAsmTypeFail('glob', USE_ASM + U32 + "var g=u4(0,0,0,0); function f() {var x=u4(1,2,3,4); x=g;} return f"); + +assertAsmTypeFail('glob', USE_ASM + F32 + "var g=0; function f() {var x=f4(0.,0.,0.,0.); x=g|0;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "var g=0.; function f() {var x=f4(0.,0.,0.,0.); x=+g;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "var f32=glob.Math.fround; var g=f32(0.); function f() {var x=f4(0.,0.,0.,0.); x=f32(g);} return f"); + +CheckI4('var x=i4(1,2,3,4)', '', [1, 2, 3, 4]); +CheckI4('var _=42; var h=i4(5,5,5,5); var __=13.37; var x=i4(4,7,9,2);', '', [4,7,9,2]); + +CheckF4('var x=f4(1.,2.,3.,4.)', '', [1, 2, 3, 4]); +CheckF4('var _=42; var h=f4(5.,5.,5.,5.); var __=13.37; var x=f4(4.,13.37,9.,-0.);', '', [4, 13.37, 9, -0]); +CheckF4('var x=f4(1,2,3,4)', '', [1, 2, 3, 4]); + +CheckB4('var x=b4(1,0,3,0)', '', [true, false, true, false]); +CheckB4('var _=42; var h=b4(5,0,5,5); var __=13.37; var x=b4(0,0,9,2);', '', [false, false, true, true]); + +// Write +assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); function f() {var x=4; g=x|0;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); function f() {var x=4.; g=+x;} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); var f32=glob.Math.fround; function f() {var x=f32(4.); g=f32(x);} return f"); + +assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4; g=x|0;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4.; g=+x;} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); var f32=glob.Math.fround; function f() {var x=f32(4.); g=f32(x);} return f"); + +assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CI32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); g=ci4(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CF32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); g=cf4(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); g=cf4(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); g=ci4(x);} return f"); + +CheckI4('var x=i4(0,0,0,0);', 'x=i4(1,2,3,4)', [1,2,3,4]); +CheckF4('var x=f4(0.,0.,0.,0.);', 'x=f4(5.,3.,4.,2.)', [5,3,4,2]); +CheckB4('var x=b4(0,0,0,0);', 'x=b4(0,0,1,1)', [false, false, true, true]); + +CheckI4('var x=i4(0,0,0,0); var y=42; var z=3.9; var w=13.37', 'x=i4(1,2,3,4); y=24; z=4.9; w=23.10;', [1,2,3,4]); +CheckF4('var x=f4(0,0,0,0); var y=42; var z=3.9; var w=13.37', 'x=f4(1,2,3,4); y=24; z=4.9; w=23.10;', [1,2,3,4]); +CheckB4('var x=b4(0,0,0,0); var y=42; var z=3.9; var w=13.37', 'x=b4(1,0,0,0); y=24; z=4.9; w=23.10;', [true, false, false, false]); + +// 1.3.6.2 Imported globals +// Read +var Int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: SIMD.Int32x4(1,2,3,4)})(); +assertEq(SIMD.Int32x4.extractLane(Int32x4, 0), 1); +assertEq(SIMD.Int32x4.extractLane(Int32x4, 1), 2); +assertEq(SIMD.Int32x4.extractLane(Int32x4, 2), 3); +assertEq(SIMD.Int32x4.extractLane(Int32x4, 3), 4); + +for (var v of [1, {}, "totally legit SIMD variable", SIMD.Float32x4(1,2,3,4)]) + assertCaught(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: v}); + +// Unsigned SIMD globals are not allowed. +assertAsmTypeFail('glob', 'ffi', USE_ASM + U32 + CU32 + "var g=cu4(ffi.g); function f() {} return f"); + +var Float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: SIMD.Float32x4(1,2,3,4)})(); +assertEq(SIMD.Float32x4.extractLane(Float32x4, 0), 1); +assertEq(SIMD.Float32x4.extractLane(Float32x4, 1), 2); +assertEq(SIMD.Float32x4.extractLane(Float32x4, 2), 3); +assertEq(SIMD.Float32x4.extractLane(Float32x4, 3), 4); + +for (var v of [1, {}, "totally legit SIMD variable", SIMD.Int32x4(1,2,3,4)]) + assertCaught(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: v}); + +var Bool32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + "var g=cb4(ffi.g); function f() {return cb4(g)} return f"), this, {g: SIMD.Bool32x4(false, false, false, true)})(); +assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 0), false); +assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 1), false); +assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 2), false); +assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 3), true); + +for (var v of [1, {}, "totally legit SIMD variable", SIMD.Int32x4(1,2,3,4)]) + assertCaught(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + "var g=cb4(ffi.g); function f() {return cb4(g)} return f"), this, {g: v}); + +// Write +var Int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {g=i4(4,5,6,7); return ci4(g)} return f"), this, {g: SIMD.Int32x4(1,2,3,4)})(); +assertEq(SIMD.Int32x4.extractLane(Int32x4, 0), 4); +assertEq(SIMD.Int32x4.extractLane(Int32x4, 1), 5); +assertEq(SIMD.Int32x4.extractLane(Int32x4, 2), 6); +assertEq(SIMD.Int32x4.extractLane(Int32x4, 3), 7); + +var Float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {g=f4(4.,5.,6.,7.); return cf4(g)} return f"), this, {g: SIMD.Float32x4(1,2,3,4)})(); +assertEq(SIMD.Float32x4.extractLane(Float32x4, 0), 4); +assertEq(SIMD.Float32x4.extractLane(Float32x4, 1), 5); +assertEq(SIMD.Float32x4.extractLane(Float32x4, 2), 6); +assertEq(SIMD.Float32x4.extractLane(Float32x4, 3), 7); + +var Bool32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + "var g=cb4(ffi.g); function f() {g=b4(1,1,0,0); return cb4(g)} return f"), this, {g: SIMD.Bool32x4(1,1,1,0)})(); +assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 0), true); +assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 1), true); +assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 2), false); +assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 3), false); + +// 2. SIMD operations +// 2.1 Compilation +assertAsmTypeFail('glob', USE_ASM + "var add = Int32x4.add; return {}"); +assertAsmTypeFail('glob', USE_ASM + I32A + I32 + "return {}"); +assertAsmTypeFail('glob', USE_ASM + "var g = 3; var add = g.add; return {}"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var func = i4.doTheHarlemShake; return {}"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var div = i4.div; return {}"); +assertAsmTypeFail('glob', USE_ASM + "var f32 = glob.Math.fround; var i4a = f32.add; return {}"); +// Operation exists, but in a different type. +assertAsmTypeFail('glob', USE_ASM + I32 + "var func = i4.fromUint32x4; return {}"); + +// 2.2 Linking +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {}); +assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {SIMD: Math.fround}); + +var oldInt32x4Add = SIMD.Int32x4.add; +var code = asmCompile('glob', USE_ASM + I32 + I32A + "return {}"); +for (var v of [42, Math.fround, SIMD.Float32x4.add, function(){}, SIMD.Int32x4.mul]) { + SIMD.Int32x4.add = v; + assertAsmLinkFail(code, {SIMD: {Int32x4: SIMD.Int32x4}}); +} +SIMD.Int32x4.add = oldInt32x4Add; // finally replace the add function with the original one +assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {SIMD: {Int32x4: SIMD.Int32x4}})(), undefined); + +// 2.3. Binary arithmetic operations +// 2.3.1 Additions +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a();} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(x, x, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(13, 37);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(23.10, 19.89);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(x, 42);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(x, 13.37);} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); var y=4; x=i4a(x, y);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(0,0,0,0); var y=4; x=i4a(y, y);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(0,0,0,0); var y=4; y=i4a(x, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + U32 + "function f() {var x=i4(0,0,0,0); var y=u4(1,2,3,4); y=i4a(x, y);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); x=i4a(x, y);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=i4a(x, y);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=i4a(x, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=f4a(x, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=f4a(x, y);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); x=f4a(y, y);} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + 'function f() {var x=i4(1,2,3,4); var y=0; y=i4a(x,x)|0} return f'); +assertAsmTypeFail('glob', USE_ASM + I32 + I32A + 'function f() {var x=i4(1,2,3,4); var y=0.; y=+i4a(x,x)} return f'); + +CheckI4(I32A, 'var z=i4(1,2,3,4); var y=i4(0,1,0,3); var x=i4(0,0,0,0); x=i4a(z,y)', [1,3,3,7]); +CheckI4(I32A, 'var x=i4(2,3,4,5); var y=i4(0,1,0,3); x=i4a(x,y)', [2,4,4,8]); +CheckI4(I32A, 'var x=i4(1,2,3,4); x=i4a(x,x)', [2,4,6,8]); +CheckI4(I32A, 'var x=i4(' + INT32_MAX + ',2,3,4); var y=i4(1,1,0,3); x=i4a(x,y)', [INT32_MIN,3,3,7]); +CheckI4(I32A, 'var x=i4(' + INT32_MAX + ',2,3,4); var y=i4(1,1,0,3); x=ci4(i4a(x,y))', [INT32_MIN,3,3,7]); + +CheckU4(U32A, 'var z=u4(1,2,3,4); var y=u4(0,1,0,3); var x=u4(0,0,0,0); x=u4a(z,y)', [1,3,3,7]); +CheckU4(U32A, 'var x=u4(2,3,4,5); var y=u4(0,1,0,3); x=u4a(x,y)', [2,4,4,8]); +CheckU4(U32A, 'var x=u4(1,2,3,4); x=u4a(x,x)', [2,4,6,8]); + +CheckF4(F32A, 'var x=f4(1,2,3,4); x=f4a(x,x)', [2,4,6,8]); +CheckF4(F32A, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4a(x,y)', [5,5,8,6]); +CheckF4(F32A, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4a(x,y)', [Math.fround(13.37) + 4,5,8,6]); +CheckF4(F32A, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4a(x,y))', [Math.fround(13.37) + 4,5,8,6]); + +// 2.3.2. Subtracts +CheckI4(I32S, 'var x=i4(1,2,3,4); var y=i4(-1,1,0,2); x=i4s(x,y)', [2,1,3,2]); +CheckI4(I32S, 'var x=i4(5,4,3,2); var y=i4(1,2,3,4); x=i4s(x,y)', [4,2,0,-2]); +CheckI4(I32S, 'var x=i4(1,2,3,4); x=i4s(x,x)', [0,0,0,0]); +CheckI4(I32S, 'var x=i4(' + INT32_MIN + ',2,3,4); var y=i4(1,1,0,3); x=i4s(x,y)', [INT32_MAX,1,3,1]); +CheckI4(I32S, 'var x=i4(' + INT32_MIN + ',2,3,4); var y=i4(1,1,0,3); x=ci4(i4s(x,y))', [INT32_MAX,1,3,1]); + +CheckU4(U32S, 'var x=u4(1,2,3,4); var y=u4(-1,1,0,2); x=u4s(x,y)', [2,1,3,2]); +CheckU4(U32S, 'var x=u4(5,4,3,2); var y=u4(1,2,3,4); x=u4s(x,y)', [4,2,0,-2>>>0]); +CheckU4(U32S, 'var x=u4(1,2,3,4); x=u4s(x,x)', [0,0,0,0]); +CheckU4(U32S, 'var x=u4(' + INT32_MIN + ',2,3,4); var y=u4(1,1,0,3); x=u4s(x,y)', [INT32_MAX,1,3,1]); +CheckU4(U32S, 'var x=u4(' + INT32_MIN + ',2,3,4); var y=u4(1,1,0,3); x=cu4(u4s(x,y))', [INT32_MAX,1,3,1]); + +CheckF4(F32S, 'var x=f4(1,2,3,4); x=f4s(x,x)', [0,0,0,0]); +CheckF4(F32S, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4s(x,y)', [-3,-1,-2,2]); +CheckF4(F32S, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4s(x,y)', [Math.fround(13.37) - 4,-1,-2,2]); +CheckF4(F32S, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4s(x,y))', [Math.fround(13.37) - 4,-1,-2,2]); + +{ + // Bug 1216099 + let code = ` + "use asm"; + var f4 = global.SIMD.Float32x4; + var f4sub = f4.sub; + const zerox4 = f4(0.0, 0.0, 0.0, 0.0); + function f() { + var newVelx4 = f4(0.0, 0.0, 0.0, 0.0); + var newVelTruex4 = f4(0.0,0.0,0.0,0.0); + newVelTruex4 = f4sub(zerox4, newVelx4); + } + // return statement voluntarily missing + `; + assertAsmTypeFail('global', code); +} + +// 2.3.3. Multiplications / Divisions +assertAsmTypeFail('glob', USE_ASM + I32 + "var f4d=i4.div; function f() {} return f"); + +CheckI4(I32M, 'var x=i4(1,2,3,4); var y=i4(-1,1,0,2); x=i4m(x,y)', [-1,2,0,8]); +CheckI4(I32M, 'var x=i4(5,4,3,2); var y=i4(1,2,3,4); x=i4m(x,y)', [5,8,9,8]); +CheckI4(I32M, 'var x=i4(1,2,3,4); x=i4m(x,x)', [1,4,9,16]); +(function() { + var m = INT32_MIN, M = INT32_MAX, imul = Math.imul; + CheckI4(I32M, `var x=i4(${m},${m}, ${M}, ${M}); var y=i4(2,-3,4,-5); x=i4m(x,y)`, + [imul(m, 2), imul(m, -3), imul(M, 4), imul(M, -5)]); + CheckI4(I32M, `var x=i4(${m},${m}, ${M}, ${M}); var y=i4(${m}, ${M}, ${m}, ${M}); x=i4m(x,y)`, + [imul(m, m), imul(m, M), imul(M, m), imul(M, M)]); +})(); + +CheckF4(F32M, 'var x=f4(1,2,3,4); x=f4m(x,x)', [1,4,9,16]); +CheckF4(F32M, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [4,6,15,8]); +CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [Math.fround(13.37) * 4,6,15,8]); +CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4m(x,y))', [Math.fround(13.37) * 4,6,15,8]); + +var f32x4 = SIMD.Float32x4(0, NaN, -0, NaN); +var another = SIMD.Float32x4(NaN, -1, -0, NaN); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32M + CF32 + "function f(x, y) {x=cf4(x); y=cf4(y); x=f4m(x,y); return cf4(x);} return f"), this)(f32x4, another), [NaN, NaN, 0, NaN]); + +CheckF4(F32D, 'var x=f4(1,2,3,4); x=f4d(x,x)', [1,1,1,1]); +CheckF4(F32D, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4d(x,y)', [1/4,2/3,3/5,2]); +CheckF4(F32D, 'var x=f4(13.37,1,1,4); var y=f4(4,0,-0.,2); x=f4d(x,y)', [Math.fround(13.37) / 4,+Infinity,-Infinity,2]); + +var f32x4 = SIMD.Float32x4(0, 0, -0, NaN); +var another = SIMD.Float32x4(0, -0, 0, 0); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32D + CF32 + "function f(x,y) {x=cf4(x); y=cf4(y); x=f4d(x,y); return cf4(x);} return f"), this)(f32x4, another), [NaN, NaN, NaN, NaN]); + +// Unary arithmetic operators +function CheckUnaryF4(op, checkFunc, assertFunc) { + var _ = asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + 'var op=f4.' + op + '; function f(x){x=cf4(x); return cf4(op(x)); } return f'), this); + return function(input) { + var simd = SIMD.Float32x4(input[0], input[1], input[2], input[3]); + + var exp = input.map(Math.fround).map(checkFunc).map(Math.fround); + var obs = _(simd); + assertEqX4(obs, exp, assertFunc); + } +} + +function CheckUnaryI4(op, checkFunc) { + var _ = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + 'var op=i4.' + op + '; function f(x){x=ci4(x); return ci4(op(x)); } return f'), this); + return function(input) { + var simd = SIMD.Int32x4(input[0], input[1], input[2], input[3]); + assertEqX4(_(simd), input.map(checkFunc).map(function(x) { return x | 0})); + } +} + +function CheckUnaryU4(op, checkFunc) { + var _ = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32U32 + U32 + U32I32 + + 'var op=u4.' + op + '; function f(x){x=ci4(x); return ci4(i4u4(op(u4i4(x)))); } return f'), this); + return function(input) { + var simd = SIMD.Int32x4(input[0], input[1], input[2], input[3]); + var res = SIMD.Uint32x4.fromInt32x4Bits(_(simd)); + assertEqX4(res, input.map(checkFunc).map(function(x) { return x >>> 0 })); + } +} + +function CheckUnaryB4(op, checkFunc) { + var _ = asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + 'var op=b4.' + op + '; function f(x){x=cb4(x); return cb4(op(x)); } return f'), this); + return function(input) { + var simd = SIMD.Bool32x4(input[0], input[1], input[2], input[3]); + assertEqX4(_(simd), input.map(checkFunc).map(function(x) { return !!x})); + } +} + +CheckUnaryI4('neg', function(x) { return -x })([1, -2, INT32_MIN, INT32_MAX]); +CheckUnaryI4('not', function(x) { return ~x })([1, -2, INT32_MIN, INT32_MAX]); + +CheckUnaryU4('neg', function(x) { return -x })([1, -2, INT32_MIN, INT32_MAX]); +CheckUnaryU4('not', function(x) { return ~x })([1, -2, INT32_MIN, INT32_MAX]); + +var CheckNotB = CheckUnaryB4('not', function(x) { return !x }); +CheckNotB([true, false, true, true]); +CheckNotB([true, true, true, true]); +CheckNotB([false, false, false, false]); + +var CheckAbs = CheckUnaryF4('abs', Math.abs); +CheckAbs([1, 42.42, 0.63, 13.37]); +CheckAbs([NaN, -Infinity, Infinity, 0]); + +var CheckNegF = CheckUnaryF4('neg', function(x) { return -x }); +CheckNegF([1, 42.42, 0.63, 13.37]); +CheckNegF([NaN, -Infinity, Infinity, 0]); + +var CheckSqrt = CheckUnaryF4('sqrt', function(x) { return Math.sqrt(x); }); +CheckSqrt([1, 42.42, 0.63, 13.37]); +CheckSqrt([NaN, -Infinity, Infinity, 0]); + +// ReciprocalApproximation and reciprocalSqrtApproximation give approximate results +function assertNear(a, b) { + if (a !== a && b === b) + throw 'Observed NaN, expected ' + b; + if (Math.abs(a - b) > 1e-3) + throw 'More than 1e-3 between ' + a + ' and ' + b; +} +var CheckRecp = CheckUnaryF4('reciprocalApproximation', function(x) { return 1 / x; }, assertNear); +CheckRecp([1, 42.42, 0.63, 13.37]); +CheckRecp([NaN, -Infinity, Infinity, 0]); + +var CheckRecp = CheckUnaryF4('reciprocalSqrtApproximation', function(x) { return 1 / Math.sqrt(x); }, assertNear); +CheckRecp([1, 42.42, 0.63, 13.37]); +CheckRecp([NaN, -Infinity, Infinity, 0]); + +// Min/Max +assertAsmTypeFail('glob', USE_ASM + I32 + "var f4m=i4.min; function f() {} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var f4d=i4.max; function f() {} return f"); + +const F32MIN = 'var min = f4.min;' +const F32MAX = 'var max = f4.max;' + +CheckF4(F32MIN, 'var x=f4(1,2,3,4); x=min(x,x)', [1,2,3,4]); +CheckF4(F32MIN, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=min(x,y)', [4,2,3,2]); +CheckF4(F32MIN + FROUND + 'var Infinity = glob.Infinity;', 'var x=f4(0,0,0,0); var y=f4(2310,3,5,0); x=f4(f32(+Infinity),f32(-Infinity),f32(3),f32(-0.)); x=min(x,y)', [2310,-Infinity,3,-0]); + +CheckF4(F32MIN, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=min(x,y)', [0,-0,-0,-0]); +CheckF4(F32MIN + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=min(x,y)', [NaN, NaN, NaN, 0]); + +CheckF4(F32MAX, 'var x=f4(1,2,3,4); x=max(x,x)', [1,2,3,4]); +CheckF4(F32MAX, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=max(x,y)', [13.37, 3, 5, 4]); +CheckF4(F32MAX + FROUND + 'var Infinity = glob.Infinity;', 'var x=f4(0,0,0,0); var y=f4(2310,3,5,0); x=f4(f32(+Infinity),f32(-Infinity),f32(3),f32(-0.)); x=max(x,y)', [+Infinity,3,5,0]); + +CheckF4(F32MAX, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=max(x,y)', [0,0,0,-0]); +CheckF4(F32MAX + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=max(x,y)', [NaN, NaN, NaN, 0]); + +const F32MINNUM = 'var min = f4.minNum;' +const F32MAXNUM = 'var max = f4.maxNum;' + +CheckF4(F32MINNUM, 'var x=f4(1,2,3,4); x=min(x,x)', [1,2,3,4]); +CheckF4(F32MINNUM, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=min(x,y)', [4,2,3,2]); +CheckF4(F32MINNUM + FROUND + 'var Infinity = glob.Infinity;', 'var x=f4(0,0,0,0); var y=f4(2310,3,5,0); x=f4(f32(+Infinity),f32(-Infinity),f32(3),f32(-0.)); x=min(x,y)', [2310,-Infinity,3,-0]); + +CheckF4(F32MINNUM, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=min(x,y)', [0,-0,-0,-0]); +CheckF4(F32MINNUM + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=min(x,y)', [NaN, 0, 0, 0]); + +CheckF4(F32MAXNUM, 'var x=f4(1,2,3,4); x=max(x,x)', [1,2,3,4]); +CheckF4(F32MAXNUM, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=max(x,y)', [13.37, 3, 5, 4]); +CheckF4(F32MAXNUM + FROUND + 'var Infinity = glob.Infinity;', 'var x=f4(0,0,0,0); var y=f4(2310,3,5,0); x=f4(f32(+Infinity),f32(-Infinity),f32(3),f32(-0.)); x=max(x,y)', [+Infinity,3,5,0]); + +CheckF4(F32MAXNUM, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=max(x,y)', [0,0,0,-0]); +CheckF4(F32MAXNUM + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=max(x,y)', [NaN, 0, 0, 0]); + +// ReplaceLane +const RLF = 'var r = f4.replaceLane;'; + +assertAsmTypeFail('glob', USE_ASM + F32 + RLF + "function f() {var x = f4(1,2,3,4); x = r(x, 0, 1);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + RLF + "function f() {var x = f4(1,2,3,4); x = r(x, 0, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(x, 4, f32(1));} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(x, f32(0), f32(1));} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(1, 0, f32(1));} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(1, 0., f32(1));} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(f32(1), 0, f32(1));} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); var l = 0; x = r(x, l, f32(1));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); var y = i4(1,2,3,4); x = r(y, 0, f32(1));} return f"); + +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 0, f32(13.37));', [Math.fround(13.37), 2, 3, 4]); +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 1, f32(13.37));', [1, Math.fround(13.37), 3, 4]); +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 2, f32(13.37));', [1, 2, Math.fround(13.37), 4]); +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, f32(13.37));', [1, 2, 3, Math.fround(13.37)]); +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, f32(13.37) + f32(6.63));', [1, 2, 3, Math.fround(Math.fround(13.37) + Math.fround(6.63))]); + +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 0, 13.37);', [Math.fround(13.37), 2, 3, 4]); +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 1, 13.37);', [1, Math.fround(13.37), 3, 4]); +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 2, 13.37);', [1, 2, Math.fround(13.37), 4]); +CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, 13.37);', [1, 2, 3, Math.fround(13.37)]); + +const RLI = 'var r = i4.replaceLane;'; +CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 0, 42);', [42, 2, 3, 4]); +CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 1, 42);', [1, 42, 3, 4]); +CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 2, 42);', [1, 2, 42, 4]); +CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 3, 42);', [1, 2, 3, 42]); + +const RLU = 'var r = u4.replaceLane;'; +CheckU4(RLU, 'var x = u4(1,2,3,4); x = r(x, 0, 42);', [42, 2, 3, 4]); +CheckU4(RLU, 'var x = u4(1,2,3,4); x = r(x, 1, 42);', [1, 42, 3, 4]); +CheckU4(RLU, 'var x = u4(1,2,3,4); x = r(x, 2, 42);', [1, 2, 42, 4]); +CheckU4(RLU, 'var x = u4(1,2,3,4); x = r(x, 3, 42);', [1, 2, 3, 42]); + +const RLB = 'var r = b4.replaceLane;'; +CheckB4(RLB, 'var x = b4(1,1,0,0); x = r(x, 0, 0);', [false, true, false, false]); +CheckB4(RLB, 'var x = b4(1,1,0,0); x = r(x, 1, 0);', [true, false, false, false]); +CheckB4(RLB, 'var x = b4(1,1,0,0); x = r(x, 2, 2);', [true, true, true, false]); +CheckB4(RLB, 'var x = b4(1,1,0,0); x = r(x, 3, 1);', [true, true, false, true]); + +// Comparisons +// Comparison operators produce Bool32x4 vectors. +const T = true; +const F = false; + +const EQI32 = 'var eq = i4.equal'; +const NEI32 = 'var ne = i4.notEqual'; +const LTI32 = 'var lt = i4.lessThan;'; +const LEI32 = 'var le = i4.lessThanOrEqual'; +const GTI32 = 'var gt = i4.greaterThan;'; +const GEI32 = 'var ge = i4.greaterThanOrEqual'; + +CheckB4(I32+EQI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=eq(a,b)', [F, F, F, F]); +CheckB4(I32+EQI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=eq(a,b)', [F, F, F, F]); +CheckB4(I32+EQI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=eq(a,b)', [T, F, F, F]); + +CheckB4(I32+NEI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=ne(a,b)', [T, T, T, T]); +CheckB4(I32+NEI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=ne(a,b)', [T, T, T, T]); +CheckB4(I32+NEI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=ne(a,b)', [F, T, T, T]); + +CheckB4(I32+LTI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=lt(a,b)', [F, F, F, F]); +CheckB4(I32+LTI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=lt(a,b)', [T, T, T, T]); +CheckB4(I32+LTI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=lt(a,b)', [F, T, T, F]); + +CheckB4(I32+LEI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=le(a,b)', [F, F, F, F]); +CheckB4(I32+LEI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=le(a,b)', [T, T, T, T]); +CheckB4(I32+LEI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=le(a,b)', [T, T, T, F]); + +CheckB4(I32+GTI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=gt(a,b)', [T, T, T, T]); +CheckB4(I32+GTI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=gt(a,b)', [F, F, F, F]); +CheckB4(I32+GTI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=gt(a,b)', [F, F, F, T]); + +CheckB4(I32+GEI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=ge(a,b)', [T, T, T, T]); +CheckB4(I32+GEI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=ge(a,b)', [F, F, F, F]); +CheckB4(I32+GEI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=ge(a,b)', [T, F, F, T]); + +const EQU32 = 'var eq = u4.equal'; +const NEU32 = 'var ne = u4.notEqual'; +const LTU32 = 'var lt = u4.lessThan;'; +const LEU32 = 'var le = u4.lessThanOrEqual'; +const GTU32 = 'var gt = u4.greaterThan;'; +const GEU32 = 'var ge = u4.greaterThanOrEqual'; + +CheckB4(U32+EQU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=eq(a,b)', [F, F, F, F]); +CheckB4(U32+EQU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=eq(a,b)', [F, F, F, F]); +CheckB4(U32+EQU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=eq(a,b)', [T, F, F, F]); + +CheckB4(U32+NEU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=ne(a,b)', [T, T, T, T]); +CheckB4(U32+NEU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=ne(a,b)', [T, T, T, T]); +CheckB4(U32+NEU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=ne(a,b)', [F, T, T, T]); + +CheckB4(U32+LTU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=lt(a,b)', [T, F, F, F]); +CheckB4(U32+LTU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=lt(a,b)', [F, T, T, T]); +CheckB4(U32+LTU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=lt(a,b)', [F, T, T, F]); + +CheckB4(U32+LEU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=le(a,b)', [T, F, F, F]); +CheckB4(U32+LEU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=le(a,b)', [F, T, T, T]); +CheckB4(U32+LEU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=le(a,b)', [T, T, T, F]); + +CheckB4(U32+GTU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=gt(a,b)', [F, T, T, T]); +CheckB4(U32+GTU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=gt(a,b)', [T, F, F, F]); +CheckB4(U32+GTU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=gt(a,b)', [F, F, F, T]); + +CheckB4(U32+GEU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=ge(a,b)', [F, T, T, T]); +CheckB4(U32+GEU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=ge(a,b)', [T, F, F, F]); +CheckB4(U32+GEU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=ge(a,b)', [T, F, F, T]); + +const LTF32 = 'var lt=f4.lessThan;'; +const LEF32 = 'var le=f4.lessThanOrEqual;'; +const GTF32 = 'var gt=f4.greaterThan;'; +const GEF32 = 'var ge=f4.greaterThanOrEqual;'; +const EQF32 = 'var eq=f4.equal;'; +const NEF32 = 'var ne=f4.notEqual;'; + +assertAsmTypeFail('glob', USE_ASM + F32 + "var lt=f4.lessThan; function f() {var x=f4(1,2,3,4); var y=f4(5,6,7,8); x=lt(x,y);} return f"); + +CheckB4(F32+LTF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=lt(y,z)', [F, F, F, F]); +CheckB4(F32+LTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=lt(y,z)', [T, T, T, T]); +CheckB4(F32+LTF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=lt(y,z)', [F, T, T, F]); +CheckB4(F32+LTF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=lt(y,z);', [F, F, F, F]); + +CheckB4(F32+LEF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=le(y,z)', [F, F, F, F]); +CheckB4(F32+LEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=le(y,z)', [T, T, T, T]); +CheckB4(F32+LEF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=le(y,z)', [T, T, T, F]); +CheckB4(F32+LEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=le(y,z);', [T, T, F, F]); + +CheckB4(F32+EQF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=eq(y,z)', [F, F, F, F]); +CheckB4(F32+EQF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=eq(y,z)', [F, F, F, F]); +CheckB4(F32+EQF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=eq(y,z)', [T, F, F, F]); +CheckB4(F32+EQF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=eq(y,z);', [T, T, F, F]); + +CheckB4(F32+NEF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=ne(y,z)', [T, T, T, T]); +CheckB4(F32+NEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=ne(y,z)', [T, T, T, T]); +CheckB4(F32+NEF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=ne(y,z)', [F, T, T, T]); +CheckB4(F32+NEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=ne(y,z);', [F, F, T, T]); + +CheckB4(F32+GTF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=gt(y,z)', [T, T, T, T]); +CheckB4(F32+GTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=gt(y,z)', [F, F, F, F]); +CheckB4(F32+GTF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=gt(y,z)', [F, F, F, T]); +CheckB4(F32+GTF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=gt(y,z);', [F, F, F, F]); + +CheckB4(F32+GEF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=ge(y,z)', [T, T, T, T]); +CheckB4(F32+GEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=ge(y,z)', [F, F, F, F]); +CheckB4(F32+GEF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=ge(y,z)', [T, F, F, T]); +CheckB4(F32+GEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=ge(y,z);', [T, T, F, F]); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + LTI32 + B32 + ANYB4 + 'function f(x){x=ci4(x); var y=i4(-1,0,4,5); var b=b4(0,0,0,0); b=lt(x,y); return anyt(b)|0;} return f'), this); +assertEq(f(SIMD.Int32x4(1,2,3,4)), 1); +assertEq(f(SIMD.Int32x4(1,2,4,5)), 0); +assertEq(f(SIMD.Int32x4(1,2,3,5)), 1); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + LTI32 + B32 + ALLB4 + 'function f(x){x=ci4(x); var y=i4(-1,0,4,5); var b=b4(0,0,0,0); b=lt(x,y); return allt(b)|0;} return f'), this); +assertEq(f(SIMD.Int32x4(-2,-2,3,4)), 1); +assertEq(f(SIMD.Int32x4(1,2,4,5)), 0); +assertEq(f(SIMD.Int32x4(1,2,3,5)), 0); + +// Conversions operators +const CVTIF = 'var cvt=f4.fromInt32x4;'; +const CVTFI = 'var cvt=i4.fromFloat32x4;'; +const CVTUF = 'var cvt=f4.fromUint32x4;'; +const CVTFU = 'var cvt=u4.fromFloat32x4;'; + +assertAsmTypeFail('glob', USE_ASM + I32 + "var cvt=i4.fromInt32x4; return {}"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var cvt=i4.fromUint32x4; return {}"); +assertAsmTypeFail('glob', USE_ASM + U32 + "var cvt=u4.fromInt32x4; return {}"); +assertAsmTypeFail('glob', USE_ASM + U32 + "var cvt=u4.fromUint32x4; return {}"); +assertAsmTypeFail('glob', USE_ASM + F32 + "var cvt=f4.fromFloat32x4; return {}"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f"); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + CI32 + CVTIF + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(x); return cf4(y);} return f'), this); +assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4]); +assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MIN), Math.fround(INT32_MAX), -1]); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + U32 + U32I32 + F32 + CF32 + CI32 + CVTUF + + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(u4i4(x)); return cf4(y);} return f'), this); +assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4]); +assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MAX+1), Math.fround(INT32_MAX), Math.fround(UINT32_MAX)]); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + CVTFI + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); y=cvt(x); return ci4(y);} return f'), this); +assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4]); +// Test that INT32_MIN (exactly representable as an float32) and the first +// integer representable as an float32 can be converted. +assertEqX4(f(SIMD.Float32x4(INT32_MIN, INT32_MAX - 64, -0, 0)), [INT32_MIN, INT32_MAX - 64, 0, 0].map(Math.fround)); +// Test boundaries: first integer less than INT32_MIN and representable as a float32 +assertThrowsInstanceOf(() => f(SIMD.Float32x4(INT32_MIN - 129, 0, 0, 0)), RangeError); +// INT_MAX + 1 +assertThrowsInstanceOf(() => f(SIMD.Float32x4(Math.pow(2, 31), 0, 0, 0)), RangeError); +// Special values +assertThrowsInstanceOf(() => f(SIMD.Float32x4(NaN, 0, 0, 0)), RangeError); +assertThrowsInstanceOf(() => f(SIMD.Float32x4(Infinity, 0, 0, 0)), RangeError); +assertThrowsInstanceOf(() => f(SIMD.Float32x4(-Infinity, 0, 0, 0)), RangeError); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + U32 + I32U32 + F32 + CF32 + CVTFU + + 'function f(x){x=cf4(x); var y=u4(0,0,0,0); y=cvt(x); return ci4(i4u4(y));} return f'), this); +assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4]); +// TODO: Test negative numbers > -1. They should truncate to 0. See https://github.com/tc39/ecmascript_simd/issues/315 +assertEqX4(SIMD.Uint32x4.fromInt32x4Bits(f(SIMD.Float32x4(0xffffff00, INT32_MAX+1, -0, 0))), + [0xffffff00, INT32_MAX+1, 0, 0].map(Math.fround)); +// Test boundaries: -1 or less. +assertThrowsInstanceOf(() => f(SIMD.Float32x4(-1, 0, 0, 0)), RangeError); +assertThrowsInstanceOf(() => f(SIMD.Float32x4(Math.pow(2, 32), 0, 0, 0)), RangeError); +// Special values +assertThrowsInstanceOf(() => f(SIMD.Float32x4(NaN, 0, 0, 0)), RangeError); +assertThrowsInstanceOf(() => f(SIMD.Float32x4(Infinity, 0, 0, 0)), RangeError); +assertThrowsInstanceOf(() => f(SIMD.Float32x4(-Infinity, 0, 0, 0)), RangeError); + +// Cast operators +const CVTIFB = 'var cvt=f4.fromInt32x4Bits;'; +const CVTFIB = 'var cvt=i4.fromFloat32x4Bits;'; + +var cast = (function() { + var i32 = new Int32Array(1); + var f32 = new Float32Array(i32.buffer); + + function fromInt32Bits(x) { + i32[0] = x; + return f32[0]; + } + + function fromFloat32Bits(x) { + f32[0] = x; + return i32[0]; + } + + return { + fromInt32Bits, + fromFloat32Bits + } +})(); + +assertAsmTypeFail('glob', USE_ASM + I32 + "var cvt=i4.fromInt32x4; return {}"); +assertAsmTypeFail('glob', USE_ASM + F32 + "var cvt=f4.fromFloat32x4; return {}"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f"); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CVTIFB + CF32 + CI32 + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(x); return cf4(y);} return f'), this); +assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits)); +assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits)); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32A + CVTIFB + CF32 + CI32 + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); var z=f4(1,1,1,1); y=cvt(x); y=f4a(y, z); return cf4(y)} return f'), this); +assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits).map((x) => x+1)); +assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits).map((x) => x+1)); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + CVTFIB + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); y=cvt(x); return ci4(y);} return f'), this); +assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits)); +assertEqX4(f(SIMD.Float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits)); + +var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + I32A + CVTFIB + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); var z=i4(1,1,1,1); y=cvt(x); y=i4a(y,z); return ci4(y);} return f'), this); +assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits).map((x) => x+1)); +assertEqX4(f(SIMD.Float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits).map((x) => x+1)); + +// Bitwise ops +const ANDI32 = 'var andd=i4.and;'; +const ORI32 = 'var orr=i4.or;'; +const XORI32 = 'var xorr=i4.xor;'; + +CheckI4(ANDI32, 'var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=andd(x,y)', [42 & 2, 1337 & 4, -1 & 7, 13 & 15]); +CheckI4(ORI32, ' var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=orr(x,y)', [42 | 2, 1337 | 4, -1 | 7, 13 | 15]); +CheckI4(XORI32, 'var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=xorr(x,y)', [42 ^ 2, 1337 ^ 4, -1 ^ 7, 13 ^ 15]); + +const ANDU32 = 'var andd=u4.and;'; +const ORU32 = 'var orr=u4.or;'; +const XORU32 = 'var xorr=u4.xor;'; + +CheckU4(ANDU32, 'var x=u4(42,1337,-1,13); var y=u4(2, 4, 7, 15); x=andd(x,y)', [42 & 2, 1337 & 4, (-1 & 7) >>> 0, 13 & 15]); +CheckU4(ORU32, ' var x=u4(42,1337,-1,13); var y=u4(2, 4, 7, 15); x=orr(x,y)', [42 | 2, 1337 | 4, (-1 | 7) >>> 0, 13 | 15]); +CheckU4(XORU32, 'var x=u4(42,1337,-1,13); var y=u4(2, 4, 7, 15); x=xorr(x,y)', [42 ^ 2, 1337 ^ 4, (-1 ^ 7) >>> 0, 13 ^ 15]); + +const ANDB32 = 'var andd=b4.and;'; +const ORB32 = 'var orr=b4.or;'; +const XORB32 = 'var xorr=b4.xor;'; + +CheckB4(ANDB32, 'var x=b4(1,0,1,0); var y=b4(1,1,0,0); x=andd(x,y)', [true, false, false, false]); +CheckB4(ORB32, ' var x=b4(1,0,1,0); var y=b4(1,1,0,0); x=orr(x,y)', [true, true, true, false]); +CheckB4(XORB32, 'var x=b4(1,0,1,0); var y=b4(1,1,0,0); x=xorr(x,y)', [false, true, true, false]); + +// No bitwise ops on Float32x4. +const ANDF32 = 'var andd=f4.and;'; +const ORF32 = 'var orr=f4.or;'; +const XORF32 = 'var xorr=f4.xor;'; +const NOTF32 = 'var nott=f4.not;'; + +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + ANDF32 + 'function f() {var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=andd(x,y);} return f'); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + ORF32 + 'function f() {var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=orr(x,y);} return f'); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + XORF32 + 'function f() {var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=xorr(x,y);} return f'); +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + NOTF32 + 'function f() {var x=f4(42, 13.37,-1.42, 23.10); x=nott(x);} return f'); + +// Logical ops +const LSHI = 'var lsh=i4.shiftLeftByScalar;' +const RSHI = 'var rsh=i4.shiftRightByScalar;' + +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return ci4(lsh(x,f32(42)));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return ci4(lsh(x,42));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + LSHI + "function f() {var x=i4(1,2,3,4); return ci4(lsh(x,42.0));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + LSHI + "function f() {var x=i4(1,2,3,4); return ci4(lsh(x,f32(42)));} return f"); + +var input = 'i4(0, 1, ' + INT32_MIN + ', ' + INT32_MAX + ')'; +var vinput = [0, 1, INT32_MIN, INT32_MAX]; + +function Lsh(i) { return function(x) { return (x << (i & 31)) | 0 } } +function Rsh(i) { return function(x) { return (x >> (i & 31)) | 0 } } + +var asmLsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + LSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(lsh(v, x+y))} return f;'), this) +var asmRsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + RSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(rsh(v, x+y))} return f;'), this) + +for (var i = 1; i < 64; i++) { + CheckI4(LSHI, 'var x=' + input + '; x=lsh(x, ' + i + ')', vinput.map(Lsh(i))); + CheckI4(RSHI, 'var x=' + input + '; x=rsh(x, ' + i + ')', vinput.map(Rsh(i))); + + assertEqX4(asmLsh(i, 3), vinput.map(Lsh(i + 3))); + assertEqX4(asmRsh(i, 3), vinput.map(Rsh(i + 3))); +} + +// Same thing for Uint32x4. +const LSHU = 'var lsh=u4.shiftLeftByScalar;' +const RSHU = 'var rsh=u4.shiftRightByScalar;' + +input = 'u4(0, 1, 0x80008000, ' + INT32_MAX + ')'; +vinput = [0, 1, 0x80008000, INT32_MAX]; + +function uLsh(i) { return function(x) { return (x << (i & 31)) >>> 0 } } +function uRsh(i) { return function(x) { return (x >>> (i & 31)) } } + +// Need to bitcast to Int32x4 before returning result. +asmLsh = asmLink(asmCompile('glob', USE_ASM + U32 + CU32 + LSHU + I32 + CI32 + I32U32 + + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(i4u4(lsh(v, x+y)));} return f;'), this) +asmRsh = asmLink(asmCompile('glob', USE_ASM + U32 + CU32 + RSHU + I32 + CI32 + I32U32 + + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(i4u4(rsh(v, x+y)));} return f;'), this) + +for (var i = 1; i < 64; i++) { + // Constant shifts. + CheckU4(LSHU, 'var x=' + input + '; x=lsh(x, ' + i + ')', vinput.map(uLsh(i))); + CheckU4(RSHU, 'var x=' + input + '; x=rsh(x, ' + i + ')', vinput.map(uRsh(i))); + + // Dynamically computed shifts. The asm function returns a Int32x4. + assertEqX4(SIMD.Uint32x4.fromInt32x4Bits(asmLsh(i, 3)), vinput.map(uLsh(i + 3))); + assertEqX4(SIMD.Uint32x4.fromInt32x4Bits(asmRsh(i, 3)), vinput.map(uRsh(i + 3))); +} + +// Select +const I32SEL = 'var i4sel = i4.select;' +const U32SEL = 'var u4sel = u4.select;' +const F32SEL = 'var f4sel = f4.select;' + +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var x=f4(1,2,3,4); return ci4(i4sel(x,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=f4(1,2,3,4); var x=i4(1,2,3,4); return ci4(i4sel(m,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=f4(1,2,3,4); var x=f4(1,2,3,4); return ci4(i4sel(m,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); return ci4(i4sel(m,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=i4(1,2,3,4); return ci4(i4sel(m,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=f4(1,2,3,4); return ci4(i4sel(m,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=f4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=i4(1,2,3,4); var y=f4(5,6,7,8); return ci4(i4sel(m,x,y));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return ci4(i4sel(m,x,y));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=i4(1,2,3,4); var y=b4(5,6,7,8); return ci4(i4sel(m,x,y));} return f"); + +assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); return cf4(f4sel(x,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); var x=i4(1,2,3,4); return cf4(f4sel(m,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); var x=f4(1,2,3,4); return cf4(f4sel(m,x,x));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); var y=i4(5,6,7,8); return cf4(f4sel(m,x,y));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(1,2,3,4); var x=i4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y));} return f"); + +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + CI32 + I32SEL + "function f() {var m=b4(0,0,0,0); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,1,1,1); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + CI32 + I32SEL + "function f() {var m=b4(0,1,0,1); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + CI32 + I32SEL + "function f() {var m=b4(0,0,1,1); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]); + +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + F32 + CF32 + F32SEL + "function f() {var m=b4(0,0,0,0); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + F32 + CF32 + F32SEL + "function f() {var m=b4(1,1,1,1); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + F32 + CF32 + F32SEL + "function f() {var m=b4(0,1,0,1); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + F32 + CF32 + F32SEL + "function f() {var m=b4(0,0,1,1); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]); + +CheckU4(B32 + U32SEL, "var m=b4(0,0,0,0); var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=u4sel(m,x,y);", [5, 6, 7, 8]); +CheckU4(B32 + U32SEL, "var m=b4(1,1,1,1); var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=u4sel(m,x,y);", [1, 2, 3, 4]); +CheckU4(B32 + U32SEL, "var m=b4(0,1,0,1); var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=u4sel(m,x,y);", [5, 2, 7, 4]); +CheckU4(B32 + U32SEL, "var m=b4(0,0,1,1); var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=u4sel(m,x,y);", [5, 6, 3, 4]); + +// Splat +const I32SPLAT = 'var splat=i4.splat;' +const U32SPLAT = 'var splat=u4.splat;' +const F32SPLAT = 'var splat=f4.splat;' +const B32SPLAT = 'var splat=b4.splat;' + +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); var p=f4(1.,2.,3.,4.); p=splat(f32(1));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1, 2)} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat()} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(m);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1.0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + FROUND + "function f() {var m=i4(1,2,3,4); m=splat(f32(1.0));} return f"); + +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SPLAT + 'function f(){return ci4(splat(42));} return f'), this)(), [42, 42, 42, 42]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + B32SPLAT + 'function f(){return cb4(splat(42));} return f'), this)(), [true, true, true, true]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + B32SPLAT + 'function f(){return cb4(splat(0));} return f'), this)(), [false, false, false, false]); +CheckU4(B32 + U32SPLAT, "var x=u4(1,2,3,4); x=splat(0);", [0, 0, 0, 0]); +CheckU4(B32 + U32SPLAT, "var x=u4(1,2,3,4); x=splat(0xaabbccdd);", [0xaabbccdd, 0xaabbccdd, 0xaabbccdd, 0xaabbccdd]); + +const l33t = Math.fround(13.37); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1)));} return f'), this)(), [1, 1, 1, 1]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(1.0));} return f'), this)(), [1, 1, 1, 1]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1 >>> 0)));} return f'), this)(), [1, 1, 1, 1]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(13.37)));} return f'), this)(), [l33t, l33t, l33t, l33t]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(13.37));} return f'), this)(), [l33t, l33t, l33t, l33t]); + +var i32view = new Int32Array(heap); +var f32view = new Float32Array(heap); +i32view[0] = 42; +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + CI32 + I32SPLAT + 'var i32=new glob.Int32Array(heap); function f(){return ci4(splat(i32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]); +f32view[0] = 42; +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + F32SPLAT + 'var f32=new glob.Float32Array(heap); function f(){return cf4(splat(f32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]); +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1) + f32(2)));} return f'), this, {}, heap)(), [3, 3, 3, 3]); + +// Dead code +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + 'function f(){var x=i4(1,2,3,4); return ci4(x); x=i4(5,6,7,8); return ci4(x);} return f'), this)(), [1, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + EXTI4 + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); c=e(x,0)|0; return ci4(x);} return f'), this)(), [1, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32A + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); x=i4a(x,x); return ci4(x);} return f'), this)(), [1, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32S + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); x=i4s(x,x); return ci4(x);} return f'), this)(), [1, 2, 3, 4]); + +// Swizzle +assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, -1, 0, 0, 0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, 4, 0, 0, 0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, 0.0, 0, 0, 0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, 0, 0, 0, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); var y=42; x=swizzle(x, 0, 0, 0, y);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "var swizzle=i4.swizzle; function f() {var x=f4(1,2,3,4); x=swizzle(x, 0, 0, 0, 0);} return f"); + +function swizzle(arr, lanes) { + return [arr[lanes[0]], arr[lanes[1]], arr[lanes[2]], arr[lanes[3]]]; +} + +var before = Date.now(); +for (var i = 0; i < Math.pow(4, 4); i++) { + var lanes = [i & 3, (i >> 2) & 3, (i >> 4) & 3, (i >> 6) & 3]; + CheckI4('var swizzle=i4.swizzle;', 'var x=i4(1,2,3,4); x=swizzle(x, ' + lanes.join(',') + ')', swizzle([1,2,3,4], lanes)); + CheckU4('var swizzle=u4.swizzle;', 'var x=u4(1,2,3,4); x=swizzle(x, ' + lanes.join(',') + ')', swizzle([1,2,3,4], lanes)); + CheckF4('var swizzle=f4.swizzle;', 'var x=f4(1,2,3,4); x=swizzle(x, ' + lanes.join(',') + ')', swizzle([1,2,3,4], lanes)); +} +DEBUG && print('time for checking all swizzles:', Date.now() - before); + +// Shuffle +assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, y, -1, 0, 0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, y, 8, 0, 0, 0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, y, 0.0, 0, 0, 0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, 0, 0, 0, 0, 0);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, y, 0, 0, 0, x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); var z=42; x=shuffle(x, y, 0, 0, 0, z);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "var shuffle=i4.shuffle; function f() {var x=f4(1,2,3,4); x=shuffle(x, x, 0, 0, 0, 0);} return f"); + +function shuffle(lhs, rhs, lanes) { + return [(lanes[0] < 4 ? lhs : rhs)[lanes[0] % 4], + (lanes[1] < 4 ? lhs : rhs)[lanes[1] % 4], + (lanes[2] < 4 ? lhs : rhs)[lanes[2] % 4], + (lanes[3] < 4 ? lhs : rhs)[lanes[3] % 4]]; +} + +before = Date.now(); + +const LANE_SELECTORS = [ + // Four of lhs or four of rhs, equivalent to swizzle + [0, 1, 2, 3], + [4, 5, 6, 7], + [0, 2, 3, 1], + [4, 7, 4, 6], + // One of lhs, three of rhs + [0, 4, 5, 6], + [4, 0, 5, 6], + [4, 5, 0, 6], + [4, 5, 6, 0], + // Two of lhs, two of rhs + // in one shufps + [1, 2, 4, 5], + [4, 5, 1, 2], + // in two shufps + [7, 0, 5, 2], + [0, 7, 5, 2], + [0, 7, 2, 5], + [7, 0, 2, 5], + // Three of lhs, one of rhs + [7, 0, 1, 2], + [0, 7, 1, 2], + [0, 1, 7, 2], + [0, 1, 2, 7], + // Impl-specific special cases for swizzle + [2, 3, 2, 3], + [0, 1, 0, 1], + [0, 0, 1, 1], + [2, 2, 3, 3], + // Impl-specific special cases for shuffle (case and swapped case) + [2, 3, 6, 7], [6, 7, 2, 3], + [0, 1, 4, 5], [4, 5, 0, 1], + [0, 4, 1, 5], [4, 0, 5, 1], + [2, 6, 3, 7], [6, 2, 7, 3], + [4, 1, 2, 3], [0, 5, 6, 7], + // Insert one element from rhs into lhs keeping other elements unchanged + [7, 1, 2, 3], + [0, 7, 2, 3], + [0, 1, 7, 2], + // These are effectively vector selects + [0, 5, 2, 3], + [0, 1, 6, 3], + [4, 5, 2, 3], + [4, 1, 6, 3] +]; + +for (var lanes of LANE_SELECTORS) { + CheckI4('var shuffle=i4.shuffle;', 'var x=i4(1,2,3,4); var y=i4(5,6,7,8); x=shuffle(x, y, ' + lanes.join(',') + ')', shuffle([1,2,3,4], [5,6,7,8], lanes)); + CheckU4('var shuffle=u4.shuffle;', 'var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=shuffle(x, y, ' + lanes.join(',') + ')', shuffle([1,2,3,4], [5,6,7,8], lanes)); + CheckF4('var shuffle=f4.shuffle;', 'var x=f4(1,2,3,4); var y=f4(5,6,7,8); x=shuffle(x, y, ' + lanes.join(',') + ')', shuffle([1,2,3,4], [5,6,7,8], lanes)); +} +DEBUG && print('time for checking all shuffles:', Date.now() - before); + +// 3. Function calls +// 3.1. No math builtins +assertAsmTypeFail('glob', USE_ASM + I32 + "var fround=glob.Math.fround; function f() {var x=i4(1,2,3,4); return +fround(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var sin=glob.Math.sin; function f() {var x=i4(1,2,3,4); return +sin(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var ceil=glob.Math.ceil; function f() {var x=i4(1,2,3,4); return +ceil(x);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var pow=glob.Math.pow; function f() {var x=i4(1,2,3,4); return +pow(1.0, x);} return f"); + +assertAsmTypeFail('glob', USE_ASM + I32 + "var fround=glob.Math.fround; function f() {var x=i4(1,2,3,4); x=i4(fround(3));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var sin=glob.Math.sin; function f() {var x=i4(1,2,3,4); x=i4(sin(3.0));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var ceil=glob.Math.sin; function f() {var x=i4(1,2,3,4); x=i4(ceil(3.0));} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + "var pow=glob.Math.pow; function f() {var x=i4(1,2,3,4); x=i4(pow(1.0, 2.0));} return f"); + +// 3.2. FFI calls +// Can't pass SIMD arguments to FFI +assertAsmTypeFail('glob', 'ffi', USE_ASM + I32 + "var func=ffi.func; function f() {var x=i4(1,2,3,4); func(x);} return f"); +assertAsmTypeFail('glob', 'ffi', USE_ASM + U32 + "var func=ffi.func; function f() {var x=u4(1,2,3,4); func(x);} return f"); +assertAsmTypeFail('glob', 'ffi', USE_ASM + F32 + "var func=ffi.func; function f() {var x=f4(1,2,3,4); func(x);} return f"); +assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + "var func=ffi.func; function f() {var x=b4(1,2,3,4); func(x);} return f"); + +// Can't have FFI return SIMD values +assertAsmTypeFail('glob', 'ffi', USE_ASM + I32 + "var func=ffi.func; function f() {var x=i4(1,2,3,4); x=i4(func());} return f"); +assertAsmTypeFail('glob', 'ffi', USE_ASM + U32 + "var func=ffi.func; function f() {var x=u4(1,2,3,4); x=i4(func());} return f"); +assertAsmTypeFail('glob', 'ffi', USE_ASM + F32 + "var func=ffi.func; function f() {var x=f4(1,2,3,4); x=f4(func());} return f"); +assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + "var func=ffi.func; function f() {var x=b4(1,2,3,4); x=b4(func());} return f"); + +// 3.3 Internal calls +// asm.js -> asm.js +// Retrieving values from asm.js +var code = USE_ASM + I32 + CI32 + I32A + EXTI4 + ` + var check = ffi.check; + + function g() { + var i = 0; + var y = i4(0,0,0,0); + var tmp = i4(0,0,0,0); var z = i4(1,1,1,1); + var w = i4(5,5,5,5); + for (; (i|0) < 30; i = i + 1 |0) + y = i4a(z, y); + y = i4a(w, y); + check(e(y,0) | 0, e(y,1) | 0, e(y,2) | 0, e(y,3) | 0); + return ci4(y); + } + + function f(x) { + x = ci4(x); + var y = i4(0,0,0,0); + y = ci4(g()); + check(e(y,0) | 0, e(y,1) | 0, e(y,2) | 0, e(y,3) | 0); + return ci4(x); + } + return f; +`; + +var v4 = SIMD.Int32x4(1,2,3,4); +function check(x, y, z, w) { + assertEq(x, 35); + assertEq(y, 35); + assertEq(z, 35); + assertEq(w, 35); +} +var ffi = {check}; +assertEqX4(asmLink(asmCompile('glob', 'ffi', code), this, ffi)(v4), [1,2,3,4]); + +// Passing arguments from asm.js to asm.js +var code = USE_ASM + I32 + CI32 + I32A + EXTI4 + ` + var assertEq = ffi.assertEq; + + function internal([args]) { + [coerc] + assertEq(e([last],0) | 0, [i] | 0); + assertEq(e([last],1) | 0, [i] + 1 |0); + assertEq(e([last],2) | 0, [i] + 2 |0); + assertEq(e([last],3) | 0, [i] + 3 |0); + } + + function external() { + [decls] + internal([args]); + } + return external; +`; + +var ffi = {assertEq}; +var args = ''; +var decls = ''; +var coerc = ''; +for (var i = 1; i < 10; ++i) { + var j = i; + args += ((i > 1) ? ', ':'') + 'x' + i; + decls += 'var x' + i + ' = i4(' + j++ + ', ' + j++ + ', ' + j++ + ', ' + j++ + ');\n'; + coerc += 'x' + i + ' = ci4(x' + i + ');\n'; + last = 'x' + i; + var c = code.replace(/\[args\]/g, args) + .replace(/\[last\]/g, last) + .replace(/\[decls\]/i, decls) + .replace(/\[coerc\]/i, coerc) + .replace(/\[i\]/g, i); + asmLink(asmCompile('glob', 'ffi', c), this, ffi)(); +} + +// Bug 1240524 +assertAsmTypeFail(USE_ASM + B32 + 'var x = b4(0, 0, 0, 0); frd(x);'); + +// Passing boolean results to extern functions. +// Verify that these functions are typed correctly. +function isone(x) { return (x===1)|0 } +var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + ANYB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(anyt(i)|0)|0; } return f'), this, {isone:isone}); +assertEq(f(SIMD.Bool32x4(0,0,1,0)), 1) +assertEq(f(SIMD.Bool32x4(0,0,0,0)), 0) +assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + CB32 + ANYB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(anyt(i))|0; } return f'); + +var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + ALLB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(allt(i)|0)|0; } return f'), this, {isone:isone}); +assertEq(f(SIMD.Bool32x4(1,1,1,1)), 1) +assertEq(f(SIMD.Bool32x4(0,1,0,0)), 0) +assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + CB32 + ALLB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(allt(i))|0; } return f'); + +var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + EXTB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(e(i,2)|0)|0; } return f'), this, {isone:isone}); +assertEq(f(SIMD.Bool32x4(1,1,1,1)), 1) +assertEq(f(SIMD.Bool32x4(0,1,0,0)), 0) +assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + CB32 + EXTB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(e(i,2))|0; } return f'); + +// Stress-test for register spilling code and stack depth checks +var code = ` + "use asm"; + var i4 = glob.SIMD.Int32x4; + var i4a = i4.add; + var e = i4.extractLane; + var assertEq = ffi.assertEq; + function g() { + var x = i4(1,2,3,4); + var y = i4(2,3,4,5); + var z = i4(0,0,0,0); + z = i4a(x, y); + assertEq(e(z,0) | 0, 3); + assertEq(e(z,1) | 0, 5); + assertEq(e(z,2) | 0, 7); + assertEq(e(z,3) | 0, 9); + } + return g +` +asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)(); + +(function() { + var code = ` + "use asm"; + var i4 = glob.SIMD.Int32x4; + var i4a = i4.add; + var e = i4.extractLane; + var assertEq = ffi.assertEq; + var one = ffi.one; + + // Function call with arguments on the stack (1 on x64, 3 on x86) + function h(x1, x2, x3, x4, x5, x6, x7) { + x1=x1|0 + x2=x2|0 + x3=x3|0 + x4=x4|0 + x5=x5|0 + x6=x6|0 + x7=x7|0 + return x1 + x2 |0 + } + + function g() { + var x = i4(1,2,3,4); + var y = i4(2,3,4,5); + var z = i4(0,0,0,0); + var w = 1; + z = i4a(x, y); + w = w + (one() | 0) | 0; + assertEq(e(z,0) | 0, 3); + assertEq(e(z,1) | 0, 5); + assertEq(e(z,2) | 0, 7); + assertEq(e(z,3) | 0, 9); + h(1, 2, 3, 4, 42, 42, 42)|0 + return w | 0; + } + return g + `; + + asmLink(asmCompile('glob', 'ffi', code), this, {assertEq: assertEq, one: () => 1})(); +})(); + +// Function calls with mixed arguments on the stack (SIMD and scalar). In the +// worst case (x64), we have 6 int arg registers and 8 float registers. +(function() { + var code = ` + "use asm"; + var i4 = glob.SIMD.Int32x4; + var e = i4.extractLane; + var ci4 = i4.check; + function h( + // In registers: + gpr1, gpr2, gpr3, gpr4, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, + // On the stack: + sint1, ssimd1, sdouble1, ssimd2, sint2, sint3, sint4, ssimd3, sdouble2 + ) + { + gpr1=gpr1|0; + gpr2=gpr2|0; + gpr3=gpr3|0; + gpr4=gpr4|0; + + xmm1=+xmm1; + xmm2=+xmm2; + xmm3=+xmm3; + xmm4=+xmm4; + xmm5=+xmm5; + xmm6=+xmm6; + xmm7=+xmm7; + xmm8=+xmm8; + + sint1=sint1|0; + ssimd1=ci4(ssimd1); + sdouble1=+sdouble1; + ssimd2=ci4(ssimd2); + sint2=sint2|0; + sint3=sint3|0; + sint4=sint4|0; + ssimd3=ci4(ssimd3); + sdouble2=+sdouble2; + + return (e(ssimd1,0)|0) + (e(ssimd2,1)|0) + (e(ssimd3,2)|0) + sint2 + gpr3 | 0; + } + + function g() { + var simd1 = i4(1,2,3,4); + var simd2 = i4(5,6,7,8); + var simd3 = i4(9,10,11,12); + return h(1, 2, 3, 4, + 1., 2., 3., 4., 5., 6., 7., 8., + 5, simd1, 9., simd2, 6, 7, 8, simd3, 10.) | 0; + } + return g + `; + + assertEq(asmLink(asmCompile('glob', 'ffi', code), this)(), 1 + 6 + 11 + 6 + 3); +})(); + +// Check that the interrupt callback doesn't erase high components of simd +// registers: + +// WARNING: must be the last test in this file +(function() { + var iters = 2000000; + var code = ` + "use asm"; + var i4 = glob.SIMD.Int32x4; + var i4a = i4.add; + var ci4 = i4.check; + function _() { + var i = 0; + var n = i4(0,0,0,0); + var one = i4(1,1,1,1); + for (; (i>>>0) < ` + iters + `; i=(i+1)>>>0) { + n = i4a(n, one); + } + return ci4(n); + } + return _;`; + // This test relies on the fact that setting the timeout will call the + // interrupt callback at fixed intervals, even before the timeout. + timeout(1000); + var x4 = asmLink(asmCompile('glob', code), this)(); + assertEq(SIMD.Int32x4.extractLane(x4,0), iters); + assertEq(SIMD.Int32x4.extractLane(x4,1), iters); + assertEq(SIMD.Int32x4.extractLane(x4,2), iters); + assertEq(SIMD.Int32x4.extractLane(x4,3), iters); +})(); + +} catch(e) { + print('Stack:', e.stack) + print('Error:', e) + throw e; +} diff --git a/js/src/jit-test/tests/asm.js/testSource.js b/js/src/jit-test/tests/asm.js/testSource.js new file mode 100644 index 000000000..b44c52a6b --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testSource.js @@ -0,0 +1,398 @@ +setCachingEnabled(true); + +(function() { +/* + * NO ARGUMENT + */ + +function f0() { + "use asm"; + function g() {} + return g; + +} + +var bodyOnly = '"use asm";\n\ + function g() {}\n\ + return g;\n'; + +var funcBody = 'function f0() {\n\ + "use asm";\n\ + function g() {}\n\ + return g;\n\n\ +}'; + +assertEq(f0.toString(), funcBody); +assertEq(f0.toSource(), funcBody); + +var f0 = function() { + "use asm"; + function g() {} + return g; + +} + +funcBody1 = funcBody.replace('function f0','function '); +assertEq(f0.toString(), funcBody1); +assertEq(f0.toSource(), '(' + funcBody1 + ')'); + +var g = function g0() { + "use asm"; + function g() {} + return g; + +} + +funcBody2 = funcBody.replace('function f0', 'function g0'); +assertEq(g.toString(), funcBody2); +assertEq(g.toSource(), '(' + funcBody2 + ')'); + +f0 = new Function(bodyOnly); +assertEq(f0.toString(), "function anonymous() {\n" + bodyOnly + "\n}"); +assertEq(f0.toSource(), "(function anonymous() {\n" + bodyOnly + "\n})"); + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var m = new Function(bodyOnly); + assertEq(isAsmJSModuleLoadedFromCache(m), true); + assertEq(m.toString(), "function anonymous() {\n" + bodyOnly + "\n}"); + assertEq(m.toSource(), "(function anonymous() {\n" + bodyOnly + "\n})"); +} + +})(); + +(function() { +/* + * ONE ARGUMENT + */ +function f1(glob) { + "use asm"; + function g() {} + return g; + +} + +var bodyOnly = '"use asm";\n\ + function g() {}\n\ + return g;\n'; + +var funcBody = 'function f1(glob) {\n\ + "use asm";\n\ + function g() {}\n\ + return g;\n\n\ +}'; + +assertEq(f1.toString(), funcBody); +assertEq(f1.toSource(), funcBody); + +f1 = function(glob) { + "use asm"; + function g() {} + return g; + +} + +funcBody1 = funcBody.replace('function f1', 'function '); +assertEq(f1.toString(), funcBody1); +assertEq(f1.toSource(), '(' + funcBody1 + ')'); + +var g = function g0(glob) { + "use asm"; + function g() {} + return g; + +} + +funcBody2 = funcBody.replace('function f1', 'function g0'); +assertEq(g.toString(), funcBody2); +assertEq(g.toSource(), '(' + funcBody2 + ')'); + +f1 = new Function('glob', bodyOnly); +assertEq(f1.toString(), "function anonymous(glob) {\n" + bodyOnly + "\n}"); +assertEq(f1.toSource(), "(function anonymous(glob) {\n" + bodyOnly + "\n})"); + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var m = new Function('glob', bodyOnly); + assertEq(isAsmJSModuleLoadedFromCache(m), true); + assertEq(m.toString(), "function anonymous(glob) {\n" + bodyOnly + "\n}"); + assertEq(m.toSource(), "(function anonymous(glob) {\n" + bodyOnly + "\n})"); +} + +})(); + + +(function() { +/* + * TWO ARGUMENTS + */ +function f2(glob, ffi) { + "use asm"; + function g() {} + return g; + +} + +var bodyOnly = '"use asm";\n\ + function g() {}\n\ + return g;\n'; + +var funcBody = 'function f2(glob, ffi) {\n\ + "use asm";\n\ + function g() {}\n\ + return g;\n\n\ +}'; + +assertEq(f2.toString(), funcBody); +assertEq(f2.toSource(), funcBody); + +f2 = function (glob, ffi) { + "use asm"; + function g() {} + return g; + +} + +funcBody1 = funcBody.replace('function f2', 'function '); +assertEq(f2.toString(), funcBody1); +assertEq(f2.toSource(), '(' + funcBody1 + ')'); + +var g = function g0(glob, ffi) { + "use asm"; + function g() {} + return g; + +} + +var funcBody2 = funcBody.replace('function f2', 'function g0'); +assertEq(g.toString(), funcBody2); +assertEq(g.toSource(), '(' + funcBody2 + ')'); + +f2 = new Function('glob', 'ffi', bodyOnly); +assertEq(f2.toString(), "function anonymous(glob, ffi) {\n" + bodyOnly + "\n}"); +assertEq(f2.toSource(), "(function anonymous(glob, ffi) {\n" + bodyOnly + "\n})"); + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var m = new Function('glob', 'ffi', bodyOnly); + assertEq(isAsmJSModuleLoadedFromCache(m), true); + assertEq(m.toString(), "function anonymous(glob, ffi) {\n" + bodyOnly + "\n}"); + assertEq(m.toSource(), "(function anonymous(glob, ffi) {\n" + bodyOnly + "\n})"); +} + +})(); + + +(function() { +/* + * THREE ARGUMENTS + */ +function f3(glob, ffi, heap) { + "use asm"; + function g() {} + return g; + +} + +var bodyOnly = '"use asm";\n\ + function g() {}\n\ + return g;\n'; + +var funcBody = 'function f3(glob, ffi, heap) {\n\ + "use asm";\n\ + function g() {}\n\ + return g;\n\n\ +}'; + +assertEq(f3.toString(), funcBody); +assertEq(f3.toSource(), funcBody); + +f3 = function (glob, ffi, heap) { + "use asm"; + function g() {} + return g; + +} + +funcBody1 = funcBody.replace('function f3', 'function '); +assertEq(f3.toString(), funcBody1); +assertEq(f3.toSource(), '(' + funcBody1 + ')'); + +var g = function g0(glob, ffi, heap) { + "use asm"; + function g() {} + return g; + +} + +funcBody2 = funcBody.replace('function f3', 'function g0'); +assertEq(g.toString(), funcBody2); +assertEq(g.toSource(), '(' + funcBody2 + ')'); + +f3 = new Function('glob', 'ffi', 'heap', bodyOnly); +assertEq(f3.toString(), "function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n}"); +assertEq(f3.toSource(), "(function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n})"); + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var m = new Function('glob', 'ffi', 'heap', bodyOnly); + assertEq(isAsmJSModuleLoadedFromCache(m), true); + assertEq(m.toString(), "function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n}"); + assertEq(m.toSource(), "(function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n})"); +} + +})(); + +/* Modules in "use strict" context */ +(function() { + +var funcSource = + `function (glob, ffi, heap) { + "use asm"; + function g() {} + return g; + }`; + +var f4 = eval("\"use strict\";\n(" + funcSource + ")"); + +var expectedToString = funcSource; +var expectedToSource = '(' + expectedToString + ')' + +assertEq(f4.toString(), expectedToString); +assertEq(f4.toSource(), expectedToSource); + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var f5 = eval("\"use strict\";\n(" + funcSource + ")"); + assertEq(isAsmJSModuleLoadedFromCache(f5), true); + assertEq(f5.toString(), expectedToString); + assertEq(f5.toSource(), expectedToSource); +} +})(); + +/* Functions */ +(function() { + +var noSrc = "function noArgument() {\n\ + return 42;\n\ +}" +var oneSrc = "function oneArgument(x) {\n\ + x = x | 0;\n\ + return x + 1 | 0;\n\ +}"; +var twoSrc = "function twoArguments(x, y) {\n\ + x = x | 0;\n\ + y = y | 0;\n\ + return x + y | 0;\n\ +}"; +var threeSrc = "function threeArguments(a, b, c) {\n\ + a = +a;\n\ + b = +b;\n\ + c = +c;\n\ + return +(+(a * b) + c);\n\ +}"; + +var funcBody = '\n\ + "use asm";\n' + + noSrc + '\n' + + oneSrc + '\n' + + twoSrc + '\n' + + threeSrc + '\n' + + 'return {\n\ + no: noArgument,\n\ + one: oneArgument,\n\ + two: twoArguments,\n\ + three: threeArguments\n\ + }'; + +var g = new Function(funcBody); +var moduleG = g(); + +function checkFuncSrc(m) { + assertEq(m.no.toString(), noSrc); + assertEq(m.no.toSource(), noSrc); + + assertEq(m.one.toString(), oneSrc); + assertEq(m.one.toSource(), oneSrc); + + assertEq(m.two.toString(), twoSrc); + assertEq(m.two.toSource(), twoSrc); + + assertEq(m.three.toString(), threeSrc); + assertEq(m.three.toSource(), threeSrc); +} +checkFuncSrc(moduleG); + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var g2 = new Function(funcBody); + assertEq(isAsmJSModuleLoadedFromCache(g2), true); + m = g2(); + checkFuncSrc(m); + + var moduleDecl = 'function g3() {' + funcBody + '}'; + eval(moduleDecl); + m = g3(); + assertEq(isAsmJSModuleLoadedFromCache(g3), false); + checkFuncSrc(m); + + eval('var x = 42;' + moduleDecl); + m = g3(); + assertEq(isAsmJSModuleLoadedFromCache(g3), true); + checkFuncSrc(m); +} + +})(); + +/* Functions in "use strict" context */ +(function () { + +var funcCode = 'function g(x) {\n\ + x=x|0;\n\ + return x + 1 | 0;}'; +var moduleCode = 'function () {\n\ + "use asm";\n' + funcCode + '\n\ + return g;\n\ + }', + useStrict = '"use strict";'; + +var f5 = eval(useStrict + ";\n(" + moduleCode + "())"); + +var expectedToString = funcCode; +var expectedToSource = expectedToString + +assertEq(f5.toString(), expectedToString); +assertEq(f5.toSource(), expectedToSource); + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var mf5 = eval("\"use strict\";\n(" + moduleCode + ")"); + assertEq(isAsmJSModuleLoadedFromCache(mf5), true); + var f5 = mf5(); + assertEq(f5.toString(), expectedToString); + assertEq(f5.toSource(), expectedToSource); +} + +})(); + +/* Functions in "use strict" context with dynamic linking failure */ +(function () { + +var funcCode = 'function g(x) {\n\ + x=x|0;\n\ + return x + 1 | 0;}'; +var moduleCode = 'function (glob) {\n\ + "use asm";\n\ + var fround = glob.Math.fround;\n\ + ' + funcCode + '\n\ + return g;\n\ + }', + useStrict = '"use strict";'; + +var f6 = eval(useStrict + ";\n(" + moduleCode + "({Math:{}}))"); + +assertEq(f6.toString(), funcCode); +assertEq(f6.toSource(), funcCode); + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var mf6 = eval("\"use strict\";\n(" + moduleCode + ")"); + assertEq(isAsmJSModuleLoadedFromCache(mf6), true); + var f6 = mf6({Math:{}}); + assertEq(f6.toString(), funcCode); + assertEq(f6.toSource(), funcCode); +} + +})(); diff --git a/js/src/jit-test/tests/asm.js/testStackWalking.js b/js/src/jit-test/tests/asm.js/testStackWalking.js new file mode 100644 index 000000000..dfda4d8c9 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testStackWalking.js @@ -0,0 +1,98 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +function matchStack(stackString, stackArray) +{ + var match = 0; + for (name of stackArray) { + match = stackString.indexOf(name, match); + if (match === -1) + throw name + " not found in the stack " + stack; + } +} + +var stack; +function dumpStack() +{ + stack = new Error().stack +} + +setJitCompilerOption("ion.warmup.trigger", 10); +setJitCompilerOption("baseline.warmup.trigger", 0); +setJitCompilerOption("offthread-compilation.enable", 0); +setCachingEnabled(true); + +var callFFI = asmCompile('global', 'ffis', USE_ASM + "var ffi=ffis.ffi; function f() { return ffi()|0 } return f"); + +var f = asmLink(callFFI, null, {ffi:dumpStack}); +for (var i = 0; i < 15; i++) { + stack = null; + f(); + matchStack(stack, ['dumpStack', 'f']); +} + +if (isAsmJSCompilationAvailable() && isCachingEnabled()) { + var callFFI = asmCompile('global', 'ffis', USE_ASM + "var ffi=ffis.ffi; function f() { return ffi()|0 } return f"); + assertEq(isAsmJSModuleLoadedFromCache(callFFI), true); + stack = null; + f(); + matchStack(stack, ['dumpStack', 'f']); +} + +var f1 = asmLink(callFFI, null, {ffi:dumpStack}); +var f2 = asmLink(callFFI, null, {ffi:function middle() { f1() }}); +stack = null; +(function outer() { f2() })(); +matchStack(stack, ["dumpStack", "f", "middle", "f"]); + +function returnStackDumper() { return { valueOf:function() { stack = new Error().stack } } } +var f = asmLink(callFFI, null, {ffi:returnStackDumper}); +for (var i = 0; i < 15; i++) { + stack = null; + f(); + matchStack(stack, ['valueOf', 'f']); +} + +var caught = false; +try { + stack = null; + asmLink(asmCompile(USE_ASM + "function asmRec() { asmRec() } return asmRec"))(); +} catch (e) { + caught = true; + matchStack(e.stack, ['asmRec', 'asmRec', 'asmRec', 'asmRec']); +} +assertEq(caught, true); + +var caught = false; +try { + callFFI(null, {ffi:Object.defineProperty})(); +} catch (e) { + caught = true; +} +assertEq(caught, true); + +asmLink(callFFI, null, {ffi:eval})(); +asmLink(callFFI, null, {ffi:Function})(); +asmLink(callFFI, null, {ffi:Error})(); + +var manyCalls = asmCompile('global', 'ffis', + USE_ASM + + "var ffi=ffis.ffi;\ + function f1(a,b,c,d,e,f,g,h,i,j,k) { \ + a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0; \ + ffi(); \ + return (a+b+c+d+e+f+g+h+i+j+k)|0; \ + } \ + function f2() { \ + return f1(1,2,3,4,5,6,7,8,f1(1,2,3,4,5,6,7,8,9,10,11)|0,10,11)|0; \ + } \ + function f3() { return 13 } \ + function f4(i) { \ + i=i|0; \ + return TBL[i&3]()|0; \ + } \ + var TBL=[f3, f3, f2, f3]; \ + return f4;"); +stack = null; +assertEq(asmLink(manyCalls, null, {ffi:dumpStack})(2), 123); +matchStack(stack, ['dumpStack', 'f1', 'f2', 'f4']); diff --git a/js/src/jit-test/tests/asm.js/testStealing.js b/js/src/jit-test/tests/asm.js/testStealing.js new file mode 100644 index 000000000..f05c81b17 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testStealing.js @@ -0,0 +1,19 @@ +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +if (!isAsmJSCompilationAvailable()) + quit(); + +var code = USE_ASM + "var i32 = new stdlib.Int32Array(buf); function f() { return i32[0]|0 } return f"; + +var ab = new ArrayBuffer(BUF_MIN); +new Int32Array(ab)[0] = 42; + +var f = asmLink(asmCompile('stdlib', 'ffi', 'buf', code), this, null, ab); +assertEq(f(), 42); + +assertThrowsInstanceOf(() => detachArrayBuffer(ab), Error); +assertEq(f(), 42); + +assertThrowsInstanceOf(() => serialize(ab, [ab]), Error); +assertEq(f(), 42); diff --git a/js/src/jit-test/tests/asm.js/testTimeout1.js b/js/src/jit-test/tests/asm.js/testTimeout1.js new file mode 100644 index 000000000..9f3013c63 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testTimeout1.js @@ -0,0 +1,8 @@ +// |jit-test| exitstatus: 6; + +load(libdir + "asm.js"); + +var g = asmLink(asmCompile(USE_ASM + "function f() {} function g() { while(1) { f() } } return g")); +timeout(1); +g(); +assertEq(true, false); diff --git a/js/src/jit-test/tests/asm.js/testTimeout2.js b/js/src/jit-test/tests/asm.js/testTimeout2.js new file mode 100644 index 000000000..4ba2d2624 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testTimeout2.js @@ -0,0 +1,8 @@ +// |jit-test| exitstatus: 6; + +load(libdir + "asm.js"); + +var g = asmLink(asmCompile(USE_ASM + "function g() { while(1) {} } return g")); +timeout(1); +g(); +assertEq(true, false); diff --git a/js/src/jit-test/tests/asm.js/testTimeout3.js b/js/src/jit-test/tests/asm.js/testTimeout3.js new file mode 100644 index 000000000..4f7df0a5e --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testTimeout3.js @@ -0,0 +1,8 @@ +// |jit-test| exitstatus: 6; + +load(libdir + "asm.js"); + +var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if (!i) return; f((i-1)|0); f((i-1)|0); f((i-1)|0); f((i-1)|0); f((i-1)|0); } return f")); +timeout(1); +f(100); +assertEq(true, false); diff --git a/js/src/jit-test/tests/asm.js/testTimeout4.js b/js/src/jit-test/tests/asm.js/testTimeout4.js new file mode 100644 index 000000000..4cbe53179 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testTimeout4.js @@ -0,0 +1,8 @@ +// |jit-test| exitstatus: 6; + +load(libdir + "asm.js"); + +var g = asmLink(asmCompile(USE_ASM + "function f(d) { d=+d; d=d*.1; d=d/.4; return +d } function g() { while(1) { +f(1.1) } } return g")); +timeout(1); +g(); +assertEq(true, false); diff --git a/js/src/jit-test/tests/asm.js/testTimeout5.js b/js/src/jit-test/tests/asm.js/testTimeout5.js new file mode 100644 index 000000000..02524e4ec --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testTimeout5.js @@ -0,0 +1,12 @@ +// |jit-test| exitstatus: 6; + +load(libdir + "asm.js"); + +enableSPSProfiling(); + +var f = asmLink(asmCompile('glob', 'ffis', 'buf', USE_ASM + "function f() { var i=0; while (1) { i=(i+1)|0 } } return f")); +timeout(1); +if (getBuildConfiguration()["arm-simulator"]) + enableSingleStepProfiling(); +f(); +assertEq(true, false); diff --git a/js/src/jit-test/tests/asm.js/testTimeout6.js b/js/src/jit-test/tests/asm.js/testTimeout6.js new file mode 100644 index 000000000..4ae0a037e --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testTimeout6.js @@ -0,0 +1,12 @@ +// |jit-test| exitstatus: 6; + +load(libdir + "asm.js"); + +enableSPSProfiling(); + +var f = asmLink(asmCompile('glob', 'ffis', 'buf', USE_ASM + "function g() { var i=0; while (1) { i=(i+1)|0 } } function f() { g() } return f")); +timeout(1); +if (getBuildConfiguration()["arm-simulator"]) + enableSingleStepProfiling(); +f(); +assertEq(true, false); diff --git a/js/src/jit-test/tests/asm.js/testUseAsmWarnings.js b/js/src/jit-test/tests/asm.js/testUseAsmWarnings.js new file mode 100644 index 000000000..46a15d752 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testUseAsmWarnings.js @@ -0,0 +1,14 @@ +load(libdir + "asm.js"); + +assertAsmDirectiveFail("'use asm'"); +assertAsmDirectiveFail("eval('\"use asm\";');"); +assertAsmDirectiveFail("{ eval('\"use asm\";'); }"); +assertAsmDirectiveFail("if (Math) { 'use asm'; }"); +assertAsmDirectiveFail("function f(){ { 'use asm'; } }"); +assertAsmDirectiveFail("function f(){ ; 'use asm'; } }"); +assertAsmDirectiveFail("function f(){ 1; 'use asm'; } }"); +assertAsmDirectiveFail("function f(){ var x; 'use asm'; } }"); +assertAsmDirectiveFail("function f(){ if (Math) { 'use asm'; } }"); +assertAsmDirectiveFail("(function(){ eval('\"use asm\";') })()"); +assertAsmDirectiveFail("new Function('{\"use asm\";}')"); +assertAsmDirectiveFail("new Function('if (Math){\"use asm\";}')"); diff --git a/js/src/jit-test/tests/asm.js/testX86ByteStore.js b/js/src/jit-test/tests/asm.js/testX86ByteStore.js new file mode 100644 index 000000000..05556a5d9 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testX86ByteStore.js @@ -0,0 +1,77 @@ +load(libdir + "asm.js"); + +var body = +' "use asm";\ + var i8=new global.Int8Array(buffer);\ + function g(i,j,k) {\ + i=i|0;\ + j=j|0;\ + k=k|0;\ + var a=0,b=0,c=0,d=0,e=0,f=0;\ + a=(i+j)|0;\ + b=(k+j)|0;\ + c=(i+k)|0;\ + b=(a+b)|0;\ + d=(b+c+i+j)|0;\ + e=(a+j+c)|0;\ + f=(a+i+k)|0;\ + i8[i] = f;\ + return (a+b+c+d+e+f)|0;\ + }\ + return g;'; + +var buf=new ArrayBuffer(BUF_MIN); +var g = asmLink(asmCompile('global','foreign','buffer',body), this, null, buf); +assertEq(g(1,2,3), 46); +assertEq(new Int8Array(buf)[1], 7); + +var body = +' "use asm";\ + var i8=new global.Int8Array(buffer);\ + function g(i,j,k) {\ + i=i|0;\ + j=j|0;\ + k=k|0;\ + var a=0,b=0,c=0,d=0,e=0,f=0;\ + a=(i+j)|0;\ + b=(k+j)|0;\ + c=(i+k)|0;\ + b=(a+b)|0;\ + d=(b+c+i+j)|0;\ + e=(a+j+c)|0;\ + f=(a+i+k)|0;\ + i8[i] = e;\ + return (a+b+c+d+e+f)|0;\ + }\ + return g;'; + +var buf=new ArrayBuffer(BUF_MIN); +var g = asmLink(asmCompile('global','foreign','buffer',body), this, null, buf); +assertEq(g(1,2,3), 46); +assertEq(new Int8Array(buf)[1], 9); + +var body = +' "use asm";\ + var i8=new global.Int8Array(buffer);\ + function g(i,j,k) {\ + i=i|0;\ + j=j|0;\ + k=k|0;\ + var a=0,b=0,c=0,d=0,e=0,f=0,g=0;\ + a=(i+j)|0;\ + b=(k+j)|0;\ + c=(i+k)|0;\ + b=(a+b)|0;\ + d=(b+c+i+j)|0;\ + e=(a+j+c)|0;\ + f=(a+i+k)|0;\ + g=(f+j+b)|0;\ + i8[i] = g;\ + return (a+b+c+d+e+f+g)|0;\ + }\ + return g;'; + +var buf=new ArrayBuffer(BUF_MIN); +var g = asmLink(asmCompile('global','foreign','buffer',body), this, null, buf); +assertEq(g(1,2,3), 63); +assertEq(new Int8Array(buf)[1], 17); diff --git a/js/src/jit-test/tests/asm.js/testZOOB.js b/js/src/jit-test/tests/asm.js/testZOOB.js new file mode 100644 index 000000000..ae59611d6 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testZOOB.js @@ -0,0 +1,232 @@ +// |jit-test| +load(libdir + "asm.js"); +load(libdir + "asserts.js"); + +if (!isAsmJSCompilationAvailable()) + quit(); + +var ab = new ArrayBuffer(BUF_MIN); + +// Compute a set of interesting indices. +indices = [0] +for (var i of [4,1024,BUF_MIN,Math.pow(2,30),Math.pow(2,31),Math.pow(2,32),Math.pow(2,33)]) { + for (var j of [-2,-1,0,1,2]) { + for (var k of [1,-1]) + indices.push((i+j)*k); + } +} + +function testInt(ctor, shift, scale, disp) { + var arr = new ctor(ab); + + var c = asmCompile('glob', 'imp', 'b', + USE_ASM + + 'var arr=new glob.' + ctor.name + '(b); ' + + 'function load(i) {i=i|0; return arr[((i<<' + scale + ')+' + disp + ')>>' + shift + ']|0 } ' + + 'function store(i,j) {i=i|0;j=j|0; arr[((i<<' + scale + ')+' + disp + ')>>' + shift + '] = j } ' + + 'function storeZero(i) {i=i|0; arr[((i<<' + scale + ')+' + disp + ')>>' + shift + '] = 0 } ' + + 'function storeNegOne(i) {i=i|0; arr[((i<<' + scale + ')+' + disp + ')>>' + shift + '] = -1 } ' + + 'return { load: load, store: store, storeZero: storeZero, storeNegOne: storeNegOne }'); + var f = asmLink(c, this, null, ab); + + var v = arr[0]; + arr[0] = -1; + var negOne = arr[0]|0; + arr[0] = v; + + for (var i of indices) { + var index = ((i<<scale)+disp)>>shift; + v = arr[index]|0; + + // Loads + assertEq(f.load(i), v); + + // Stores of immediates + arr[index] = 1; + f.storeZero(i); + assertEq(arr[index]|0, 0); + f.storeNegOne(i); + assertEq(arr[index]|0, index>>>0 < arr.length ? negOne : 0); + + // Stores + arr[index] = ~v; + f.store(i, v); + assertEq(arr[index]|0, v); + } +} + +function testFloat(ctor, shift, scale, disp, coercion) { + var arr = new ctor(ab); + + var c = asmCompile('glob', 'imp', 'b', + USE_ASM + + 'var arr=new glob.' + ctor.name + '(b); ' + + 'var toF = glob.Math.fround; ' + + 'function load(i) {i=i|0; return ' + coercion + '(arr[((i<<' + scale + ')+' + disp + ')>>' + shift + ']) } ' + + 'function store(i,j) {i=i|0;j=+j; arr[((i<<' + scale + ')+' + disp + ')>>' + shift + '] = j } ' + + 'return { load: load, store: store }'); + var f = asmLink(c, this, null, ab); + + for (var i of indices) { + var index = ((i<<scale)+disp)>>shift; + var v = +arr[index]; + + // Loads + assertEq(f.load(i), v); + + // Stores + arr[index] = ~v; + f.store(i, v); + assertEq(+arr[index], v); + } +} + +function testFloat32(ctor, shift, scale, disp) { + testFloat(ctor, shift, scale, disp, "toF"); +} +function testFloat64(ctor, shift, scale, disp) { + testFloat(ctor, shift, scale, disp, "+"); +} + +function assertEqX4(observed, expected) { + assertEq(observed.x, expected.x); + assertEq(observed.y, expected.y); + assertEq(observed.z, expected.z); + assertEq(observed.w, expected.w); +} + +function testSimdX4(ctor, shift, scale, disp, simdName, simdCtor) { + var arr = new ctor(ab); + + var c = asmCompile('glob', 'imp', 'b', + USE_ASM + + 'var arr=new glob.' + ctor.name + '(b); ' + + 'var SIMD_' + simdName + ' = glob.SIMD.' + simdName + '; ' + + 'var SIMD_' + simdName + '_check = SIMD_' + simdName + '.check; ' + + 'var SIMD_' + simdName + '_load = SIMD_' + simdName + '.load; ' + + 'var SIMD_' + simdName + '_load2 = SIMD_' + simdName + '.load2; ' + + 'var SIMD_' + simdName + '_load1 = SIMD_' + simdName + '.load1; ' + + 'var SIMD_' + simdName + '_store = SIMD_' + simdName + '.store; ' + + 'var SIMD_' + simdName + '_store2 = SIMD_' + simdName + '.store2; ' + + 'var SIMD_' + simdName + '_store1 = SIMD_' + simdName + '.store1; ' + + 'function load(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' + + 'function load2(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load2(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' + + 'function load1(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load1(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' + + 'function store(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' + + 'function store2(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store2(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' + + 'function store1(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store1(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' + + 'return { load: load, load2: load2, load1: load1, store: store, store2 : store2, store1 : store1 }'); + var f = asmLink(c, this, null, ab); + + const RuntimeError = WebAssembly.RuntimeError; + + for (var i of indices) { + var index = ((i<<scale)+disp)>>shift; + + var v, v2, v1; + var t = false, t2 = false, t1 = false; + try { v = simdCtor.load(arr, index); } + catch (e) { + assertEq(e instanceof RangeError, true); + t = true; + } + try { v2 = simdCtor.load2(arr, index); } + catch (e) { + assertEq(e instanceof RangeError, true); + t2 = true; + } + try { v1 = simdCtor.load1(arr, index); } + catch (e) { + assertEq(e instanceof RangeError, true); + t1 = true; + } + + // Loads + var l, l2, l1; + var r = false, r2 = false, r1 = false; + try { l = f.load(i); } + catch (e) { + assertEq(e instanceof RuntimeError, true); + r = true; + } + try { l2 = f.load2(i); } + catch (e) { + assertEq(e instanceof RuntimeError, true); + r2 = true; + } + try { l1 = f.load1(i); } + catch (e) { + assertEq(e instanceof RuntimeError, true); + r1 = true; + } + assertEq(t, r); + assertEq(t2, r2); + assertEq(t1, r1); + if (!t) assertEqX4(v, l); + if (!t2) assertEqX4(v2, l2); + if (!t1) assertEqX4(v1, l1); + + // Stores + if (!t) { + simdCtor.store(arr, index, simdCtor.neg(v)); + f.store(i, v); + assertEqX4(simdCtor.load(arr, index), v); + } else + assertThrowsInstanceOf(() => f.store(i, simdCtor()), RuntimeError); + if (!t2) { + simdCtor.store2(arr, index, simdCtor.neg(v2)); + f.store2(i, v2); + assertEqX4(simdCtor.load2(arr, index), v2); + } else + assertThrowsInstanceOf(() => f.store2(i, simdCtor()), RuntimeError); + if (!t1) { + simdCtor.store1(arr, index, simdCtor.neg(v1)); + f.store1(i, v1); + assertEqX4(simdCtor.load1(arr, index), v1); + } else + assertThrowsInstanceOf(() => f.store1(i, simdCtor()), RuntimeError); + } +} + +function testFloat32x4(ctor, shift, scale, disp) { + testSimdX4(ctor, shift, scale, disp, 'Float32x4', SIMD.Float32x4); +} +function testInt32x4(ctor, shift, scale, disp) { + testSimdX4(ctor, shift, scale, disp, 'Int32x4', SIMD.Int32x4); +} + +function test(tester, ctor, shift) { + var arr = new ctor(ab); + for (var i = 0; i < arr.length; i++) + arr[i] = Math.imul(i, Math.imul((i & 1), 2) - 1); + for (scale of [0,1,2,3]) { + for (disp of [0,1,2,8,Math.pow(2,30),Math.pow(2,31)-1,Math.pow(2,31),Math.pow(2,32)-1]) + tester(ctor, shift, scale, disp); + } + for (var i = 0; i < arr.length; i++) { + var v = arr[i]; + arr[i] = Math.imul(i, Math.imul((i & 1), 2) - 1); + assertEq(arr[i], v); + } +} + +test(testInt, Int8Array, 0); +test(testInt, Uint8Array, 0); +test(testInt, Int16Array, 1); +test(testInt, Uint16Array, 1); +test(testInt, Int32Array, 2); +test(testInt, Uint32Array, 2); +test(testFloat32, Float32Array, 2); +test(testFloat64, Float64Array, 3); +if (typeof SIMD !== 'undefined' && isSimdAvailable()) { + // Avoid pathological --ion-eager compile times due to bails in loops + setJitCompilerOption('ion.warmup.trigger', 1000000); + + // Use a fresh ArrayBuffer so prepareForAsmJS can allocated a guard page + // which SIMD.js needs. Since the original ArrayBuffer was prepared for + // asm.js that didn't use SIMD.js, it has no guard page (on 32-bit). + ab = new ArrayBuffer(BUF_MIN); + + test(testInt32x4, Uint8Array, 0); + test(testFloat32x4, Uint8Array, 0); +} |