diff options
Diffstat (limited to 'js/src/jit-test/tests/wasm/builtin-modules')
14 files changed, 878 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/builtin-modules/directives.txt b/js/src/jit-test/tests/wasm/builtin-modules/directives.txt new file mode 100644 index 0000000000..87d59ea13c --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/directives.txt @@ -0,0 +1 @@ +|jit-test| test-also=--wasm-compiler=optimizing; include:wasm.js diff --git a/js/src/jit-test/tests/wasm/builtin-modules/i8vecmul.js b/js/src/jit-test/tests/wasm/builtin-modules/i8vecmul.js new file mode 100644 index 0000000000..86336b5d33 --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/i8vecmul.js @@ -0,0 +1,39 @@ +let memory = new WebAssembly.Memory({initial: 1}); +let bytes = new Uint8Array(memory.buffer); + +let module = wasmBuiltinI8VecMul(); +let instance = new WebAssembly.Instance(module, { + "": {"memory": memory} +}); +let {i8vecmul} = instance.exports; + +// Test basic vector pairwise product +{ + // [0, 1, 2, 3] . [0, 2, 4, 6] = [0, 2, 8, 18] + for (let i = 0; i < 4; i++) { + bytes[i] = i; + bytes[4 + i] = i * 2; + } + i8vecmul( + /* dest */ 8, + /* src1 */ 0, + /* src2 */ 4, + /* len */ 4); + for (let i = 0; i < 4; i++) { + assertEq(bytes[8 + i], i * i * 2); + } +} + +// Test bounds checking +{ + assertErrorMessage(() => i8vecmul(PageSizeInBytes - 1, 0, 0, 2), WebAssembly.RuntimeError, /index out of bounds/); + assertErrorMessage(() => i8vecmul(0, PageSizeInBytes - 1, 0, 2), WebAssembly.RuntimeError, /index out of bounds/); + assertErrorMessage(() => i8vecmul(0, 0, PageSizeInBytes - 1, 2), WebAssembly.RuntimeError, /index out of bounds/); +} + +// Test linking of intrinsics +{ + let linkInstance = wasmEvalText(`(module + (import "" "i8vecmul" (func (param i32 i32 i32 i32))) + )`, {"": instance.exports}); +} diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/CommonTestSetup.js b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/CommonTestSetup.js new file mode 100644 index 0000000000..0b3455ba96 --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/CommonTestSetup.js @@ -0,0 +1,27 @@ +// |jit-test| skip-if:true; + +// This file contains all the code that is common to all integer gemm intrinsics' test scripts. + +// The test setup as string that is common to all integer gemm tests +export const COMMON_TEST_SETUP_AS_STRING = ` +const libdir=${JSON.stringify(libdir)}; load(libdir + "wasm.js"); +let memory = new WebAssembly.Memory({initial: 1, maximum: 1}); +let module = WebAssembly.mozIntGemm(); +if (!module) { + throw new Error(); +} +let instance = new WebAssembly.Instance(module, {"": {"memory": memory}}); + +const ARRAY_ALIGNMENT = 64; +const ROWS_A_MULTIPLIER = 1; +const COLUMNS_A_MULTIPLIER = 64; +const ROWS_B_MULTIPLIER = COLUMNS_A_MULTIPLIER; +const COLUMNS_B_MULTIPLIER = 8; +const SELECTED_COLUMNS_B_MULTIPLIER = 8; +` + +// Run the test +export function runTest(completeTestAsString) { + const testEnvironment = newGlobal({newCompartment: true, systemPrincipal: true}); + testEnvironment.evaluate(completeTestAsString); +} diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8MultiplyAndAddBias.js b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8MultiplyAndAddBias.js new file mode 100644 index 0000000000..d988bb2541 --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8MultiplyAndAddBias.js @@ -0,0 +1,81 @@ +// This file contains all the tests for int8_multiply_and_add_bias intrinsic. It depends +// on the CommonTestSetup.js script which contains the common functionality +// that is required for testing all the intrinsics. +const COMMON_TEST_SETUP_SCRIPT = "./CommonTestSetup.js" + +// All tests for this intrinsic as a string +const ALL_TESTS_AS_STRING =` +let {int8_multiply_and_add_bias} = instance.exports; + +const VALID = {inputA: 0, scaleA: 1.0, zeroPointA: 0.0, inputB: ARRAY_ALIGNMENT << 2, scaleB: 1.0, zeroPointB: 0.0, inputBiasPrepared: ARRAY_ALIGNMENT << 4, unquantMultiplier: -2.0, rowsA: ROWS_A_MULTIPLIER, width: ROWS_B_MULTIPLIER, colsB: COLUMNS_B_MULTIPLIER, output: ARRAY_ALIGNMENT << 5}; + +function testInvalidSize() { + let invalidSize; + + // rowsA: 0 + invalidSize = 0; + assertErrorMessage(() => int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, invalidSize, VALID.width, VALID.colsB, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // width: 0 + invalidSize = 0; + assertErrorMessage(() => int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, invalidSize, VALID.colsB, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // width: Not an integral multiple of ROWS_B_MULTIPLIER + invalidSize = ROWS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, invalidSize, VALID.colsB, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // colB: 0 + invalidSize = 0; + assertErrorMessage(() => int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, VALID.width, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // colB: Not an integral multiple of COLUMNS_B_MULTIPLIER + invalidSize = COLUMNS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, VALID.width, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); +} + +function testInvalidAlignment() { + let invalidAlignment = ARRAY_ALIGNMENT + 1; + + // inputA: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_multiply_and_add_bias(invalidAlignment, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, VALID.width, VALID.colsB, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // inputB: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, invalidAlignment, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, VALID.width, VALID.colsB, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testOutOfBounds() { + let outOfBound; + + // inputA: Out of Bounds + outOfBound = PageSizeInBytes - ARRAY_ALIGNMENT; + let rowsAForOutOfBound = ROWS_A_MULTIPLIER << 1; + assertErrorMessage(() => int8_multiply_and_add_bias(outOfBound, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, rowsAForOutOfBound, VALID.width, VALID.colsB, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // inputB: Out of Bounds + outOfBound = PageSizeInBytes - ARRAY_ALIGNMENT; + assertErrorMessage(() => int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, outOfBound, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, VALID.width, VALID.colsB, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // inputBias: Out of Bounds + outOfBound = PageSizeInBytes - VALID.colsB; + assertErrorMessage(() => int8_multiply_and_add_bias(outOfBound, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, outOfBound, VALID.unquantMultiplier, VALID.rowsA, VALID.width, VALID.colsB, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Out of Bounds + outOfBound = PageSizeInBytes - VALID.colsB; + assertErrorMessage(() => int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, VALID.width, VALID.colsB, outOfBound), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testSuccessfulCall() { + // We just test that with valid arguments the intrinsic executes without any error + int8_multiply_and_add_bias(VALID.inputA, VALID.scaleA, VALID.zeroPointA, VALID.inputB, VALID.scaleB, VALID.zeroPointB, VALID.inputBiasPrepared, VALID.unquantMultiplier, VALID.rowsA, VALID.width, VALID.colsB, VALID.output); +} + +testInvalidSize(); +testInvalidAlignment(); +testOutOfBounds(); +testSuccessfulCall(); +` + +// Run all the tests +import(COMMON_TEST_SETUP_SCRIPT).then((importedModule) => { + importedModule.runTest(importedModule.COMMON_TEST_SETUP_AS_STRING + ALL_TESTS_AS_STRING); +}); diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareA.js b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareA.js new file mode 100644 index 0000000000..a7f9f204f1 --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareA.js @@ -0,0 +1,62 @@ +// This file contains all the tests for int8_prepare_a intrinsic. It depends +// on the CommonTestSetup.js script which contains the common functionality +// that is required for testing all the intrinsics. +const COMMON_TEST_SETUP_SCRIPT = "./CommonTestSetup.js" + +// All tests for this intrinsic as a string +const ALL_TESTS_AS_STRING =` +let {int8_prepare_a} = instance.exports; + +const VALID = {input: 0, scale: 1.0, zeroPoint: 0.0, rows: ROWS_A_MULTIPLIER, cols: COLUMNS_A_MULTIPLIER, output: ARRAY_ALIGNMENT << 5}; + +function testInvalidSize() { + let invalidSize; + + // row: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_a(VALID.input, VALID.scale, VALID.zeroPoint, invalidSize, VALID.cols, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_a(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: Not an integral multiple of COLUMNS_A_MULTIPLIER + invalidSize = COLUMNS_A_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_a(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); +} + +function testInvalidAlignment() { + let invalidAlignment = ARRAY_ALIGNMENT + 1; + + // input: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_a(invalidAlignment, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_a(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, invalidAlignment), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testOutOfBounds() { + let outOfBound = PageSizeInBytes - ARRAY_ALIGNMENT; + + // input: Out of Bounds + assertErrorMessage(() => int8_prepare_a(outOfBound, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Out of Bounds + assertErrorMessage(() => int8_prepare_a(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, outOfBound), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testSuccessfulCall() { + // We just test that with valid arguments the intrinsic executes without any error + int8_prepare_a(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output); +} + +testInvalidSize(); +testInvalidAlignment(); +testOutOfBounds(); +testSuccessfulCall(); +` + +// Run all the tests +import(COMMON_TEST_SETUP_SCRIPT).then((importedModule) => { + importedModule.runTest(importedModule.COMMON_TEST_SETUP_AS_STRING + ALL_TESTS_AS_STRING); +}); diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareB.js b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareB.js new file mode 100644 index 0000000000..ca66a6af3c --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareB.js @@ -0,0 +1,66 @@ +// This file contains all the tests for int8_prepare_b intrinsic. It depends +// on the CommonTestSetup.js script which contains the common functionality +// that is required for testing all the intrinsics. +const COMMON_TEST_SETUP_SCRIPT = "./CommonTestSetup.js" + +// All tests for this intrinsic as a string +const ALL_TESTS_AS_STRING =` +let {int8_prepare_b} = instance.exports; + +const VALID = {input: 0, scale: 1.0, zeroPoint: 0.0, rows: ROWS_B_MULTIPLIER, cols: COLUMNS_B_MULTIPLIER, output: ARRAY_ALIGNMENT << 5}; + +function testInvalidSize() { + let invalidSize; + + // row: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_b(VALID.input, VALID.scale, VALID.zeroPoint, invalidSize, VALID.cols, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // row: Not an integral multiple of ROWS_B_MULTIPLIER + invalidSize = ROWS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_b(VALID.input, VALID.scale, VALID.zeroPoint, invalidSize, VALID.cols, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_b(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: Not an integral multiple of COLUMNS_B_MULTIPLIER + invalidSize = COLUMNS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_b(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); +} + +function testInvalidAlignment() { + let invalidAlignment = ARRAY_ALIGNMENT + 1; + + // input: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_b(invalidAlignment, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_b(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, invalidAlignment), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testOutOfBounds() { + let outOfBound = PageSizeInBytes - ARRAY_ALIGNMENT; + + // input: Out of Bounds + assertErrorMessage(() => int8_prepare_b(outOfBound, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Out of Bounds + assertErrorMessage(() => int8_prepare_b(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, outOfBound), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testSuccessfulCall() { + // We just test that with valid arguments the intrinsic executes without any error + int8_prepare_b(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output); +} + +testInvalidSize(); +testInvalidAlignment(); +testOutOfBounds(); +testSuccessfulCall(); +` + +// Run all the tests +import(COMMON_TEST_SETUP_SCRIPT).then((importedModule) => { + importedModule.runTest(importedModule.COMMON_TEST_SETUP_AS_STRING + ALL_TESTS_AS_STRING); +}); diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBFromQuantizedTransposed.js b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBFromQuantizedTransposed.js new file mode 100644 index 0000000000..191d5fdda0 --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBFromQuantizedTransposed.js @@ -0,0 +1,66 @@ +// This file contains all the tests for int8_prepare_b_from_quantized_transposed intrinsic. It depends +// on the CommonTestSetup.js script which contains the common functionality +// that is required for testing all the intrinsics. +const COMMON_TEST_SETUP_SCRIPT = "./CommonTestSetup.js" + +// All tests for this intrinsic as a string +const ALL_TESTS_AS_STRING =` +let {int8_prepare_b_from_quantized_transposed} = instance.exports; + +const VALID = {input: 0, rows: ROWS_B_MULTIPLIER, cols: COLUMNS_B_MULTIPLIER, output: ARRAY_ALIGNMENT << 5}; + +function testInvalidSize() { + let invalidSize; + + // row: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_b_from_quantized_transposed(VALID.input, invalidSize, VALID.cols, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // row: Not an integral multiple of ROWS_B_MULTIPLIER + invalidSize = ROWS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_b_from_quantized_transposed(VALID.input, invalidSize, VALID.cols, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_b_from_quantized_transposed(VALID.input, VALID.rows, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: Not an integral multiple of COLUMNS_B_MULTIPLIER + invalidSize = COLUMNS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_b_from_quantized_transposed(VALID.input, VALID.rows, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); +} + +function testInvalidAlignment() { + let invalidAlignment = ARRAY_ALIGNMENT + 1; + + // input: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_b_from_quantized_transposed(invalidAlignment, VALID.rows, VALID.cols, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_b_from_quantized_transposed(VALID.input, VALID.rows, VALID.cols, invalidAlignment), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testOutOfBounds() { + let outOfBound = PageSizeInBytes - ARRAY_ALIGNMENT; + + // input: Out of Bounds + assertErrorMessage(() => int8_prepare_b_from_quantized_transposed(outOfBound, VALID.rows, VALID.cols, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Out of Bounds + assertErrorMessage(() => int8_prepare_b_from_quantized_transposed(VALID.input, VALID.rows, VALID.cols, outOfBound), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testSuccessfulCall() { + // We just test that with valid arguments the intrinsic executes without any error + int8_prepare_b_from_quantized_transposed(VALID.input, VALID.rows, VALID.cols, VALID.output); +} + +testInvalidSize(); +testInvalidAlignment(); +testOutOfBounds(); +testSuccessfulCall(); +` + +// Run all the tests +import(COMMON_TEST_SETUP_SCRIPT).then((importedModule) => { + importedModule.runTest(importedModule.COMMON_TEST_SETUP_AS_STRING + ALL_TESTS_AS_STRING); +}); diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBFromTransposed.js b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBFromTransposed.js new file mode 100644 index 0000000000..e8e01f6b17 --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBFromTransposed.js @@ -0,0 +1,66 @@ +// This file contains all the tests for int8_prepare_b_from_transposed intrinsic. It depends +// on the CommonTestSetup.js script which contains the common functionality +// that is required for testing all the intrinsics. +const COMMON_TEST_SETUP_SCRIPT = "./CommonTestSetup.js" + +// All tests for this intrinsic as a string +const ALL_TESTS_AS_STRING =` +let {int8_prepare_b_from_transposed} = instance.exports; + +const VALID = {input: 0, scale: 1.0, zeroPoint: 0.0, rows: ROWS_B_MULTIPLIER, cols: COLUMNS_B_MULTIPLIER, output: ARRAY_ALIGNMENT << 5}; + +function testInvalidSize() { + let invalidSize; + + // row: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_b_from_transposed(VALID.input, VALID.scale, VALID.zeroPoint, invalidSize, VALID.cols, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // row: Not an integral multiple of ROWS_B_MULTIPLIER + invalidSize = ROWS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_b_from_transposed(VALID.input, VALID.scale, VALID.zeroPoint, invalidSize, VALID.cols, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_b_from_transposed(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: Not an integral multiple of COLUMNS_B_MULTIPLIER + invalidSize = COLUMNS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_b_from_transposed(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); +} + +function testInvalidAlignment() { + let invalidAlignment = ARRAY_ALIGNMENT + 1; + + // input: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_b_from_transposed(invalidAlignment, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_b_from_transposed(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, invalidAlignment), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testOutOfBounds() { + let outOfBound = PageSizeInBytes - ARRAY_ALIGNMENT; + + // input: Out of Bounds + assertErrorMessage(() => int8_prepare_b_from_transposed(outOfBound, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Out of Bounds + assertErrorMessage(() => int8_prepare_b_from_transposed(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, outOfBound), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testSuccessfulCall() { + // We just test that with valid arguments the intrinsic executes without any error + int8_prepare_b_from_transposed(VALID.input, VALID.scale, VALID.zeroPoint, VALID.rows, VALID.cols, VALID.output); +} + +testInvalidSize(); +testInvalidAlignment(); +testOutOfBounds(); +testSuccessfulCall(); +` + +// Run all the tests +import(COMMON_TEST_SETUP_SCRIPT).then((importedModule) => { + importedModule.runTest(importedModule.COMMON_TEST_SETUP_AS_STRING + ALL_TESTS_AS_STRING); +}); diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBias.js b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBias.js new file mode 100644 index 0000000000..49c0d3f87a --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBias.js @@ -0,0 +1,69 @@ +// This file contains all the tests for int8_prepare_bias intrinsic. It depends +// on the CommonTestSetup.js script which contains the common functionality +// that is required for testing all the intrinsics. +const COMMON_TEST_SETUP_SCRIPT = "./CommonTestSetup.js" + +// All tests for this intrinsic as a string +const ALL_TESTS_AS_STRING =` +let {int8_prepare_bias} = instance.exports; + +const VALID = {input: 0, scaleA: 1.0, zeroPointA: 0.0, scaleB: 1.0, zeroPointB: 0.0, rows: ROWS_B_MULTIPLIER, cols: COLUMNS_B_MULTIPLIER, inputBias: ARRAY_ALIGNMENT << 4, output: ARRAY_ALIGNMENT << 5}; + +function testInvalidSize() { + let invalidSize; + + // row: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_bias(VALID.input, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, invalidSize, VALID.cols, VALID.inputBias, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // row: Not an integral multiple of ROWS_B_MULTIPLIER + invalidSize = ROWS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_bias(VALID.input, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, invalidSize, VALID.cols, VALID.inputBias, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: 0 + invalidSize = 0; + assertErrorMessage(() => int8_prepare_bias(VALID.input, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, VALID.rows, invalidSize, VALID.inputBias, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: Not an integral multiple of COLUMNS_B_MULTIPLIER + invalidSize = COLUMNS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_prepare_bias(VALID.input, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, VALID.rows, invalidSize, VALID.inputBias, VALID.output), WebAssembly.RuntimeError, /unreachable/); +} + +function testInvalidAlignment() { + let invalidAlignment = ARRAY_ALIGNMENT + 1; + + // input: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_prepare_bias(invalidAlignment, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, VALID.rows, VALID.cols, VALID.inputBias, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testOutOfBounds() { + let outOfBound; + + // input: Out of Bounds + outOfBound = PageSizeInBytes - ARRAY_ALIGNMENT; + assertErrorMessage(() => int8_prepare_bias(outOfBound, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, VALID.rows, VALID.cols, VALID.inputBias, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // inputBias: Out of Bounds + outOfBound = PageSizeInBytes - VALID.cols; + assertErrorMessage(() => int8_prepare_bias(VALID.input, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, VALID.rows, VALID.cols, outOfBound, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Out of Bounds + outOfBound = PageSizeInBytes - VALID.cols; + assertErrorMessage(() => int8_prepare_bias(VALID.input, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, VALID.rows, VALID.cols, VALID.inputBias, outOfBound), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testSuccessfulCall() { + // We just test that with valid arguments the intrinsic executes without any error + int8_prepare_bias(VALID.input, VALID.scaleA, VALID.zeroPointA, VALID.scaleB, VALID.zeroPointB, VALID.rows, VALID.cols, VALID.inputBias, VALID.output); +} + +testInvalidSize(); +testInvalidAlignment(); +testOutOfBounds(); +testSuccessfulCall(); +` + +// Run all the tests +import(COMMON_TEST_SETUP_SCRIPT).then((importedModule) => { + importedModule.runTest(importedModule.COMMON_TEST_SETUP_AS_STRING + ALL_TESTS_AS_STRING); +}); diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8SelectColumnsOfB.js b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8SelectColumnsOfB.js new file mode 100644 index 0000000000..7d13e18c9b --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8SelectColumnsOfB.js @@ -0,0 +1,77 @@ +// This file contains all the tests for int8_select_columns_of_b intrinsic. It depends +// on the CommonTestSetup.js script which contains the common functionality +// that is required for testing all the intrinsics. +const COMMON_TEST_SETUP_SCRIPT = "./CommonTestSetup.js" + +// All tests for this intrinsic as a string +const ALL_TESTS_AS_STRING =` +let {int8_select_columns_of_b} = instance.exports; + +const VALID = {input: 0, rows: ROWS_B_MULTIPLIER, cols: COLUMNS_B_MULTIPLIER, colIndexList: ARRAY_ALIGNMENT << 3, sizeColIndexList: SELECTED_COLUMNS_B_MULTIPLIER, output: ARRAY_ALIGNMENT << 5}; + +function testInvalidSize() { + let invalidSize; + + // row: 0 + invalidSize = 0; + assertErrorMessage(() => int8_select_columns_of_b(VALID.input, invalidSize, VALID.cols, VALID.colIndexList, VALID.sizeColIndexList, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // row: Not an integral multiple of ROWS_B_MULTIPLIER + invalidSize = ROWS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_select_columns_of_b(VALID.input, invalidSize, VALID.cols, VALID.colIndexList, VALID.sizeColIndexList, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: 0 + invalidSize = 0; + assertErrorMessage(() => int8_select_columns_of_b(VALID.input, VALID.rows, invalidSize, VALID.colIndexList, VALID.sizeColIndexList, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // col: Not an integral multiple of COLUMNS_B_MULTIPLIER + invalidSize = COLUMNS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_select_columns_of_b(VALID.input, VALID.rows, invalidSize, VALID.colIndexList, VALID.sizeColIndexList, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // sizeColIndexList: 0 + invalidSize = 0; + assertErrorMessage(() => int8_select_columns_of_b(VALID.input, VALID.rows, VALID.cols, VALID.colIndexList, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); + + // sizeColIndexList: Not an integral multiple of SELECTED_COLUMNS_B_MULTIPLIER + invalidSize = SELECTED_COLUMNS_B_MULTIPLIER + 1; + assertErrorMessage(() => int8_select_columns_of_b(VALID.input, VALID.rows, VALID.cols, VALID.colIndexList, invalidSize, VALID.output), WebAssembly.RuntimeError, /unreachable/); +} + +function testInvalidAlignment() { + let invalidAlignment = ARRAY_ALIGNMENT + 1; + + // input: Not an integral multiple of ARRAY_ALIGNMENT + assertErrorMessage(() => int8_select_columns_of_b(invalidAlignment, VALID.rows, VALID.cols, VALID.colIndexList, VALID.sizeColIndexList, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testOutOfBounds() { + let outOfBound; + + // input: Out of Bounds + outOfBound = PageSizeInBytes - ARRAY_ALIGNMENT; + assertErrorMessage(() => int8_select_columns_of_b(outOfBound, VALID.rows, VALID.cols, VALID.colIndexList, VALID.sizeColIndexList, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // colIndexList: Out of Bounds + outOfBound = PageSizeInBytes - VALID.sizeColIndexList; + assertErrorMessage(() => int8_select_columns_of_b(outOfBound, VALID.rows, VALID.cols, outOfBound, VALID.sizeColIndexList, VALID.output), WebAssembly.RuntimeError, /index out of bounds/); + + // output: Out of Bounds + outOfBound = PageSizeInBytes - (VALID.rows * VALID.sizeColIndexList); + assertErrorMessage(() => int8_select_columns_of_b(VALID.input, VALID.rows, VALID.cols, VALID.colIndexList, VALID.sizeColIndexList, outOfBound), WebAssembly.RuntimeError, /index out of bounds/); +} + +function testSuccessfulCall() { + // We just test that with valid arguments the intrinsic executes without any error + int8_select_columns_of_b(VALID.input, VALID.rows, VALID.cols, VALID.colIndexList, VALID.sizeColIndexList, VALID.output); +} + +testInvalidSize(); +testInvalidAlignment(); +testOutOfBounds(); +testSuccessfulCall(); +` + +// Run all the tests +import(COMMON_TEST_SETUP_SCRIPT).then((importedModule) => { + importedModule.runTest(importedModule.COMMON_TEST_SETUP_AS_STRING + ALL_TESTS_AS_STRING); +}); diff --git a/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/directives.txt b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/directives.txt new file mode 100644 index 0000000000..46c9c504f4 --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/directives.txt @@ -0,0 +1 @@ +|jit-test| --wasm-moz-intgemm; skip-if: (!getBuildConfiguration("x64") && !getBuildConfiguration("x86") && !getBuildConfiguration("arm64")) || getBuildConfiguration("simulator") || !wasmMozIntGemmEnabled() diff --git a/js/src/jit-test/tests/wasm/builtin-modules/js-string/basic.js b/js/src/jit-test/tests/wasm/builtin-modules/js-string/basic.js new file mode 100644 index 0000000000..dce6204fee --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/js-string/basic.js @@ -0,0 +1,316 @@ +// |jit-test| skip-if: !wasmJSStringBuiltinsEnabled(); + +let testModule = wasmTextToBinary(`(module + (func + (import "wasm:js-string" "fromWTF16Array") + (param anyref i32 i32) + (result externref) + ) + (export "fromWTF16Array" (func 0)) + + (func + (import "wasm:js-string" "toWTF16Array") + (param externref anyref i32) + (result i32) + ) + (export "toWTF16Array" (func 1)) + + (func + (import "wasm:js-string" "fromCharCode") + (param i32) + (result externref) + ) + (export "fromCharCode" (func 2)) + + (func + (import "wasm:js-string" "fromCodePoint") + (param i32) + (result externref) + ) + (export "fromCodePoint" (func 3)) + + (func + (import "wasm:js-string" "charCodeAt") + (param externref i32) + (result i32) + ) + (export "charCodeAt" (func 4)) + + (func + (import "wasm:js-string" "codePointAt") + (param externref i32) + (result i32) + ) + (export "codePointAt" (func 5)) + + (func + (import "wasm:js-string" "length") + (param externref) + (result i32) + ) + (export "length" (func 6)) + + (func + (import "wasm:js-string" "concatenate") + (param externref externref) + (result externref) + ) + (export "concatenate" (func 7)) + + (func + (import "wasm:js-string" "substring") + (param externref i32 i32) + (result externref) + ) + (export "substring" (func 8)) + + (func + (import "wasm:js-string" "equals") + (param externref externref) + (result i32) + ) + (export "equals" (func 9)) + + (func + (import "wasm:js-string" "compare") + (param externref externref) + (result i32) + ) + (export "compare" (func 10)) +)`); + +let { + createArray, + arrayLength, + arraySet, + arrayGet +} = wasmEvalText(`(module + (type $i16Array (array (mut i16))) + (func (export "createArray") (param i32) (result anyref) + i32.const 0 + local.get 0 + array.new $i16Array + ) + (func (export "arrayLength") (param arrayref) (result i32) + local.get 0 + array.len + ) + (func (export "arraySet") (param (ref $i16Array) i32 i32) + local.get 0 + local.get 1 + local.get 2 + array.set $i16Array + ) + (func (export "arrayGet") (param (ref $i16Array) i32) (result i32) + local.get 0 + local.get 1 + array.get_u $i16Array + ) +)`).exports; + +function throwIfNotString(a) { + if (typeof a !== "string") { + throw new WebAssembly.RuntimeError(); + } +} +let polyFillImports = { + fromWTF16Array: (array, arrayStart, arrayCount) => { + arrayStart |= 0; + arrayCount |= 0; + let length = arrayLength(array); + if (BigInt(arrayStart) + BigInt(arrayCount) > BigInt(length)) { + throw new WebAssembly.RuntimeError(); + } + let result = ''; + for (let i = arrayStart; i < arrayStart + arrayCount; i++) { + result += String.fromCharCode(arrayGet(array, i)); + } + return result; + }, + toWTF16Array: (string, arr, arrayStart) => { + arrayStart |= 0; + throwIfNotString(string); + let arrLength = arrayLength(arr); + let stringLength = string.length; + if (BigInt(arrayStart) + BigInt(stringLength) > BigInt(arrLength)) { + throw new WebAssembly.RuntimeError(); + } + for (let i = 0; i < stringLength; i++) { + arraySet(arr, arrayStart + i, string[i].charCodeAt(0)); + } + return stringLength; + }, + fromCharCode: (charCode) => { + charCode |= 0; + return String.fromCharCode(charCode); + }, + fromCodePoint: (codePoint) => { + codePoint |= 0; + return String.fromCodePoint(codePoint); + }, + charCodeAt: (string, stringIndex) => { + stringIndex |= 0; + throwIfNotString(string); + if (stringIndex >= string.length) + throw new WebAssembly.RuntimeError(); + return string.charCodeAt(stringIndex); + }, + codePointAt: (string, stringIndex) => { + stringIndex |= 0; + throwIfNotString(string); + if (stringIndex >= string.length) + throw new WebAssembly.RuntimeError(); + return string.codePointAt(stringIndex); + }, + length: (string) => { + throwIfNotString(string); + return string.length; + }, + concatenate: (stringA, stringB) => { + throwIfNotString(stringA); + throwIfNotString(stringB); + return stringA + stringB; + }, + substring: (string, startIndex, endIndex) => { + startIndex |= 0; + endIndex |= 0; + throwIfNotString(string); + if (startIndex > string.length, + endIndex > string.length, + endIndex < startIndex) { + return ""; + } + return string.substring(startIndex, endIndex); + }, + equals: (stringA, stringB) => { + throwIfNotString(stringA); + throwIfNotString(stringB); + return stringA === stringB; + }, + compare: (stringA, stringB) => { + throwIfNotString(stringA); + throwIfNotString(stringB); + if (stringA < stringB) { + return -1; + } + return stringA === stringB ? 0 : 1; + }, +}; + +function assertSameBehavior(funcA, funcB, ...params) { + let resultA; + let errA = null; + try { + resultA = funcA(...params); + } catch (err) { + errA = err; + } + + let resultB; + let errB = null; + try { + resultB = funcB(...params); + } catch (err) { + errB = err; + } + + if (errA || errB) { + assertEq(errA === null, errB === null, errA ? errA.message : errB.message); + assertEq(Object.getPrototypeOf(errA), Object.getPrototypeOf(errB)); + assertEq(errA.message, errB.message); + } + assertEq(resultA, resultB); + + if (errA) { + throw errA; + } + return resultA; +} + +let builtinExports = new WebAssembly.Instance(new WebAssembly.Module(testModule, {builtins: ["js-string"]}), {}).exports; +let polyfillExports = new WebAssembly.Instance(new WebAssembly.Module(testModule), { 'wasm:js-string': polyFillImports }).exports; + +let testStrings = ["", "a", "1", "ab", "hello, world", "\n", "☺", "☺smiley", String.fromCodePoint(0x10000, 0x10001)]; +let testCharCodes = [1, 2, 3, 10, 0x7f, 0xff, 0xfffe, 0xffff]; +let testCodePoints = [1, 2, 3, 10, 0x7f, 0xff, 0xfffe, 0xffff, 0x10000, 0x10001]; + +for (let a of testCharCodes) { + assertSameBehavior( + builtinExports['fromCharCode'], + polyfillExports['fromCharCode'], + a + ); +} + +for (let a of testCodePoints) { + assertSameBehavior( + builtinExports['fromCodePoint'], + polyfillExports['fromCodePoint'], + a + ); +} + +for (let a of testStrings) { + let length = assertSameBehavior( + builtinExports['length'], + polyfillExports['length'], + a + ); + + for (let i = 0; i < length; i++) { + let charCode = assertSameBehavior( + builtinExports['charCodeAt'], + polyfillExports['charCodeAt'], + a, i + ); + } + for (let i = 0; i < length; i++) { + let charCode = assertSameBehavior( + builtinExports['codePointAt'], + polyfillExports['codePointAt'], + a, i + ); + } + + let array = createArray(length); + assertSameBehavior( + builtinExports['toWTF16Array'], + polyfillExports['toWTF16Array'], + a, array, 0 + ); + assertSameBehavior( + builtinExports['fromWTF16Array'], + polyfillExports['fromWTF16Array'], + array, 0, length + ); + + for (let i = 0; i < length; i++) { + for (let j = 0; j < length; j++) { + assertSameBehavior( + builtinExports['substring'], + polyfillExports['substring'], + a, i, j + ); + } + } +} + +for (let a of testStrings) { + for (let b of testStrings) { + assertSameBehavior( + builtinExports['concatenate'], + polyfillExports['concatenate'], + a, b + ); + assertSameBehavior( + builtinExports['equals'], + polyfillExports['equals'], + a, b + ); + assertSameBehavior( + builtinExports['compare'], + polyfillExports['compare'], + a, b + ); + } +} diff --git a/js/src/jit-test/tests/wasm/builtin-modules/js-string/directives.txt b/js/src/jit-test/tests/wasm/builtin-modules/js-string/directives.txt new file mode 100644 index 0000000000..8c5e6882eb --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/js-string/directives.txt @@ -0,0 +1 @@ +|jit-test| --wasm-gc; --wasm-js-string-builtins; test-also=--wasm-compiler=optimizing; include:wasm.js diff --git a/js/src/jit-test/tests/wasm/builtin-modules/oom-test.js b/js/src/jit-test/tests/wasm/builtin-modules/oom-test.js new file mode 100644 index 0000000000..32aa1b2515 --- /dev/null +++ b/js/src/jit-test/tests/wasm/builtin-modules/oom-test.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: !('oomTest' in this) + +oomTest(() => { + const module = wasmBuiltinI8VecMul(); + WebAssembly.Module.imports(module); +}); |