diff options
Diffstat (limited to 'js/src/jit-test/tests/asm.js/testZOOB.js')
-rw-r--r-- | js/src/jit-test/tests/asm.js/testZOOB.js | 232 |
1 files changed, 232 insertions, 0 deletions
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); +} |