summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/extended-const
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/jit-test/tests/wasm/extended-const
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/wasm/extended-const')
-rw-r--r--js/src/jit-test/tests/wasm/extended-const/basic.js95
-rw-r--r--js/src/jit-test/tests/wasm/extended-const/directives.txt1
-rw-r--r--js/src/jit-test/tests/wasm/extended-const/disabled.js22
-rw-r--r--js/src/jit-test/tests/wasm/extended-const/pathological.js78
4 files changed, 196 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/extended-const/basic.js b/js/src/jit-test/tests/wasm/extended-const/basic.js
new file mode 100644
index 0000000000..bf0ce460d5
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/extended-const/basic.js
@@ -0,0 +1,95 @@
+// |jit-test| skip-if: !wasmExtendedConstEnabled()
+
+function testPrivateGlobal(valtype, expr, result) {
+ // Immutable private globals have a single cell for wasm.
+ let { get } = wasmEvalText(`(module
+ (global $global ${valtype} ${expr})
+ (func (export "get") (result ${valtype})
+ global.get $global
+ )
+ )`).exports;
+ assertEq(get(), result);
+}
+function testExportedGlobal(valtype, expr, result) {
+ // Immutable exported globals have a separate cell for wasm and the exported
+ // global object.
+ let { global, get } = wasmEvalText(`(module
+ (global $global (export "global") ${valtype} ${expr})
+ (func (export "get") (result ${valtype})
+ global.get $global
+ )
+ )`).exports;
+ assertEq(get(), result);
+ assertEq(global.value, result);
+}
+function testIndirectGlobal(valtype, expr, result) {
+ // Mutable exported globals share an indirect cell for wasm and the exported
+ // global object.
+ let { global } = wasmEvalText(`(module
+ (global (export "global") (mut ${valtype}) ${expr})
+ )`).exports;
+ assertEq(global.value, result);
+}
+
+// i32 tests
+
+const I32_SQ_OVERFLOW = 0xFFFF + 1;
+const MAX_I32 = 0xFFFF_FFFF;
+function testI32(expr, result) {
+ testPrivateGlobal('i32', expr, result);
+ testExportedGlobal('i32', expr, result);
+ testIndirectGlobal('i32', expr, result);
+}
+testI32('i32.const 1', 1);
+
+testI32('i32.const 1 i32.const 2 i32.add', 3);
+testI32(`i32.const ${MAX_I32} i32.const 1 i32.add`, 0);
+
+testI32('i32.const 1 i32.const 2 i32.sub', -1);
+testI32(`i32.const 1 i32.const 0 i32.sub`, 1);
+
+testI32('i32.const 1 i32.const 2 i32.mul', 2);
+testI32(`i32.const ${I32_SQ_OVERFLOW} i32.const ${I32_SQ_OVERFLOW} i32.mul`, 0);
+
+// i64 tests
+
+const I64_SQ_OVERFLOW = 0xFFFF_FFFFn + 1n;
+const MAX_I64 = 0xFFFF_FFFF_FFFF_FFFFn;
+function testI64(expr, result) {
+ testPrivateGlobal('i64', expr, result);
+ testExportedGlobal('i64', expr, result);
+ testIndirectGlobal('i64', expr, result);
+}
+testI64('i64.const 1', 1n);
+
+testI64('i64.const 1 i64.const 2 i64.add', 3n);
+testI64(`i64.const ${MAX_I64} i64.const 1 i64.add`, 0n);
+
+testI64('i64.const 1 i64.const 2 i64.sub', -1n);
+testI64(`i64.const 1 i64.const 0 i64.sub`, 1n);
+
+testI64('i64.const 1 i64.const 2 i64.mul', 2n);
+testI64(`i64.const ${I64_SQ_OVERFLOW} i64.const ${I64_SQ_OVERFLOW} i64.mul`, 0n);
+
+// test global.get
+
+function testGlobalGet(valtype, aExpr, bExpr, cExpr, cResult) {
+ let { a, b } = wasmEvalText(`(module
+ (global (export "a") ${valtype} ${aExpr})
+ (global (export "b") ${valtype} ${bExpr})
+ )`).exports;
+ let { c } = wasmEvalText(`(module
+ (global $a (import "" "a") ${valtype})
+ (global $b (import "" "b") ${valtype})
+ (global (export "c") ${valtype} ${cExpr})
+ )`, {"": {a, b}}).exports;
+ assertEq(c.value, cResult);
+}
+
+testGlobalGet('i32', 'i32.const 2', 'i32.const 3', 'global.get $a global.get $b i32.add', 5);
+testGlobalGet('i32', 'i32.const 2', 'i32.const 3', 'global.get $a global.get $b i32.sub', -1);
+testGlobalGet('i32', 'i32.const 2', 'i32.const 3', 'global.get $a global.get $b i32.mul', 6);
+
+testGlobalGet('i64', 'i64.const 2', 'i64.const 3', 'global.get $a global.get $b i64.add', 5n);
+testGlobalGet('i64', 'i64.const 2', 'i64.const 3', 'global.get $a global.get $b i64.sub', -1n);
+testGlobalGet('i64', 'i64.const 2', 'i64.const 3', 'global.get $a global.get $b i64.mul', 6n);
diff --git a/js/src/jit-test/tests/wasm/extended-const/directives.txt b/js/src/jit-test/tests/wasm/extended-const/directives.txt
new file mode 100644
index 0000000000..0d16de6524
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/extended-const/directives.txt
@@ -0,0 +1 @@
+|jit-test| --wasm-extended-const; test-also=--wasm-compiler=optimizing; test-also=--wasm-test-serialization; test-also=--wasm-compiler=baseline; test-also=--test-wasm-await-tier2; include:wasm.js
diff --git a/js/src/jit-test/tests/wasm/extended-const/disabled.js b/js/src/jit-test/tests/wasm/extended-const/disabled.js
new file mode 100644
index 0000000000..01e64f6c44
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/extended-const/disabled.js
@@ -0,0 +1,22 @@
+// |jit-test| skip-if: wasmExtendedConstEnabled()
+
+const { CompileError, validate } = WebAssembly;
+
+const DISABLED = /extended constant expressions not enabled|unrecognized opcode/;
+
+let tests = [
+ "(module (global i32 i32.const 0 i32.const 0 i32.add))",
+ "(module (global i32 i32.const 0 i32.const 0 i32.sub))",
+ "(module (global i32 i32.const 0 i32.const 0 i32.mul))",
+ "(module (global i64 i64.const 0 i64.const 0 i64.add))",
+ "(module (global i64 i64.const 0 i64.const 0 i64.sub))",
+ "(module (global i64 i64.const 0 i64.const 0 i64.mul))",
+];
+
+// Test that use of extended constants fails when disabled.
+
+for (let src of tests) {
+ let bin = wasmTextToBinary(src);
+ assertEq(validate(bin), false);
+ wasmCompilationShouldFail(bin, DISABLED);
+}
diff --git a/js/src/jit-test/tests/wasm/extended-const/pathological.js b/js/src/jit-test/tests/wasm/extended-const/pathological.js
new file mode 100644
index 0000000000..e3695f3625
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/extended-const/pathological.js
@@ -0,0 +1,78 @@
+// |jit-test| skip-if: !wasmExtendedConstEnabled()
+
+// Let's calculate zero in some elaborate ways.
+function testFancyZeroOffset(fancyZero, memType = 'i32') {
+ try {
+ const { mem } = wasmEvalText(`(module
+ (memory (export "mem") ${memType} 1)
+ (data (offset ${fancyZero}) "hi")
+ )`).exports;
+ const str = String.fromCharCode(...new Uint8Array(mem.buffer).slice(0, 2));
+ assertEq(str, 'hi');
+ } catch (e) {
+ const { getOffset } = wasmEvalText(`(module
+ (func (export "getOffset") (result ${memType})
+ ${fancyZero}
+ )
+ )`).exports;
+ console.log('Computed offset:', getOffset());
+ throw e;
+ }
+}
+
+// Do plus one minus one a thousand times
+testFancyZeroOffset('i32.const 0 ' + (
+ '(i32.add (i32.const 1)) '
+ + '(i32.sub (i32.const 1)) '
+).repeat(1000));
+
+// Do some jank fibonacci
+{
+ let fib = '(i32.const 1)\n'
+ let a = 1; let b = 1; let next;
+ for (let i = 0; i < 45; i++) {
+ fib += `(i32.const ${a})\n`;
+ fib += '(i32.add)\n';
+ next = a + b;
+ a = b;
+ b = next;
+ }
+ fib += `(i32.sub (i32.const ${next}))\n`;
+ testFancyZeroOffset(fib);
+}
+
+// Run the collatz conjecture as long as possible
+{
+ let val = 837799; // should reach 1 in 524 steps
+ let expr = `(i32.const ${val})\n`;
+ while (val != 1) {
+ if (val % 2 == 0) {
+ expr += `(i32.sub (i32.const ${val / 2}))\n`; // we can't divide in constant expressions lol
+ val /= 2;
+ } else {
+ expr += `(i32.mul (i32.const 3))\n`;
+ expr += `(i32.add (i32.const 1))\n`;
+ val = val * 3 + 1;
+ }
+ }
+ expr += `(i32.sub (i32.const 1))\n`;
+ testFancyZeroOffset(expr);
+}
+
+// The collatz conjecture would be even more fun with 64-bit numbers...
+if (wasmMemory64Enabled()) {
+ let val = 1899148184679; // should reach 1 in 1411 steps
+ let expr = `(i64.const ${val})\n`;
+ while (val != 1) {
+ if (val % 2 == 0) {
+ expr += `(i64.sub (i64.const ${val / 2}))\n`; // we can't divide in constant expressions lol
+ val /= 2;
+ } else {
+ expr += `(i64.mul (i64.const 3))\n`;
+ expr += `(i64.add (i64.const 1))\n`;
+ val = val * 3 + 1;
+ }
+ }
+ expr += `(i64.sub (i64.const 1))\n`;
+ testFancyZeroOffset(expr, 'i64');
+}