summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/builtin-modules
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/wasm/builtin-modules')
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/directives.txt1
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/i8vecmul.js39
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/CommonTestSetup.js27
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8MultiplyAndAddBias.js81
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareA.js62
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareB.js66
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBFromQuantizedTransposed.js66
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBFromTransposed.js66
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8PrepareBias.js69
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/I8SelectColumnsOfB.js77
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/integer-gemm/directives.txt1
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/js-string/basic.js316
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/js-string/directives.txt1
-rw-r--r--js/src/jit-test/tests/wasm/builtin-modules/oom-test.js6
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);
+});