diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/jit-test/tests/wasm/bigint/bigint.js | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.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/bigint/bigint.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/bigint/bigint.js | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/bigint/bigint.js b/js/src/jit-test/tests/wasm/bigint/bigint.js new file mode 100644 index 0000000000..79e7e416b1 --- /dev/null +++ b/js/src/jit-test/tests/wasm/bigint/bigint.js @@ -0,0 +1,468 @@ +// Used to ensure tests will trigger Wasm Jit stub code. +var threshold = 2 * getJitCompilerOptions()["ion.warmup.trigger"] + 10; +function testWithJit(f) { + for (var i = 0; i < threshold; i++) { + f(); + } +} + +function testRet() { + var f = wasmEvalText(`(module + (func (export "f") (result i64) (i64.const 66)) + )`).exports.f; + + testWithJit(() => { + assertEq(typeof f(), "bigint", "should return a bigint"); + assertEq(f(), 66n, "should return the correct value"); + }); +} + +function testId() { + var exports = wasmEvalText(`(module + (func (export "f") (param i64 i64) (result i64) + (local.get 0) + ) + (func (export "f2") (param i64 i64) (result i64) + (local.get 1) + ) + )`).exports; + var f = exports.f; + var f2 = exports.f2; + + testWithJit(() => { + assertEq(f(0n, 1n), 0n); + assertEq(f(-0n, 1n), -0n); + assertEq(f(123n, 1n), 123n); + assertEq(f(-123n, 1n), -123n); + assertEq(f(2n ** 63n, 1n), -(2n ** 63n)); + assertEq(f(2n ** 64n + 123n, 1n), 123n); + assertEq(f("5", 1n), 5n); + assertEq(f(true, 1n), 1n); + assertEq(f(false, 1n), 0n); + assertEq(f({ toString() { return "5"; }, }, 1n), 5n); + assertEq(f({ valueOf() { return 5n; }, }, 1n), 5n); + + assertEq(f2(1n, 0n), 0n); + assertEq(f2(1n, -0n), -0n); + assertEq(f2(1n, 123n), 123n); + assertEq(f2(1n, -123n), -123n); + assertEq(f2(1n, 2n ** 63n), -(2n ** 63n)); + assertEq(f2(1n, 2n ** 64n + 123n), 123n); + assertEq(f2(1n, "5"), 5n); + assertEq(f2(1n, true), 1n); + assertEq(f2(1n, false), 0n); + assertEq(f2(1n, { toString() { return "5"; }, }), 5n); + assertEq(f2(1n, { valueOf() { return 5n; }, }), 5n); + }); +} + +function testNonBigIntArgs() { + var f = wasmEvalText(`(module + (func (export "f") (param i64) (result i64) + (local.get 0) + ) + )`).exports.f; + + assertErrorMessage(() => f(5), TypeError, "can't convert 5 to BigInt"); + assertErrorMessage(() => f({ valueOf() { return 5; }, }), + TypeError, + "can't convert 5 to BigInt"); + assertErrorMessage(() => f(5.3), TypeError, "can't convert 5.3 to BigInt"); + assertErrorMessage(() => f(), TypeError, "can't convert undefined to BigInt"); + assertErrorMessage( + () => f(undefined), + TypeError, + "can't convert undefined to BigInt" + ); + assertErrorMessage(() => f(null), TypeError, "can't convert null to BigInt"); + assertErrorMessage( + () => f(Symbol("foo")), + TypeError, + 'can\'t convert Symbol("foo") to BigInt' + ); + assertErrorMessage(() => f({}), SyntaxError, "invalid BigInt syntax"); + assertErrorMessage(() => f({ valueof() { return "foo"; }, }), + SyntaxError, + "invalid BigInt syntax"); + assertErrorMessage(() => f("x"), SyntaxError, "invalid BigInt syntax"); +} + +function testIdPlus() { + var f = wasmEvalText(`(module + (func (export "f") (param i64) (result i64) + (i64.const 8) + (get_local 0) + (i64.add) + ) + )`).exports.f; + + testWithJit(() => { + assertEq(f(0n), 0n + 8n); + assertEq(f(147n), 147n + 8n); + }); +} + +// Test functions with many parameters to stress ABI cases. We want to test +// spilled arguments both under and over the Ion call inlining limit. +function testManyArgs() { + var f1 = wasmEvalText(`(module + (func (export "f") + (param i64 i64 i64 i64 i64 i64 i64 i64) + (result i64) + (get_local 0) + (get_local 1) + (get_local 2) + (get_local 3) + (get_local 4) + (get_local 5) + (get_local 6) + (get_local 7) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + ) + )`).exports.f; + + var f2 = wasmEvalText(`(module + (func (export "f") + (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) + (result i64) + (get_local 0) + (get_local 1) + (get_local 2) + (get_local 3) + (get_local 4) + (get_local 5) + (get_local 6) + (get_local 7) + (get_local 8) + (get_local 9) + (get_local 10) + (get_local 11) + (get_local 12) + (get_local 13) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + (i64.add) + ) + )`).exports.f; + + testWithJit(() => { + assertEq(f1(1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n), 8n); + assertEq(f2(1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n), 14n); + }); +} + +// Test import and re-export. +function testImportExport() { + var f1 = wasmEvalText( + `(module + (import "i64" "func" (func (param i64))) + (export "f" (func 0)) + )`, + { + i64: { + func(b) { + assertEq(b, 42n); + }, + }, + } + ).exports.f; + + var f2 = wasmEvalText( + `(module + (import "i64" "func" (func (param i64) (result i64))) + (export "f" (func 0)) + )`, + { + i64: { + func(n) { + return n + 1n; + }, + }, + } + ).exports.f; + + var f3 = wasmEvalText( + `(module + (import "" "i64" (func $i64 (param i64) (result i64))) + (func (export "f") (param i64) (result i64) + (get_local 0) + (call $i64)) + )`, + { + "": { + i64: n => { + return n + 1n; + }, + }, + } + ).exports.f; + + var f4 = wasmEvalText( + `(module + (import "i64" "func" (func (result i64))) + (export "f" (func 0)) + )`, + { i64: { func() {} } } + ).exports.f; + + testWithJit(() => { + assertEq(f1(42n), undefined); + assertEq(f2(42n), 43n); + assertEq(f3(42n), 43n); + assertErrorMessage(() => f4(42), TypeError, "can't convert undefined to BigInt"); + }); +} + +// Test that a mixture of I64 and other argument types works. +function testMixedArgs() { + var f = wasmEvalText(`(module + (func (export "f") + (param i64 f32 f64 i32 i64) + (result i64) + (get_local 1) + (i64.trunc_s/f32) + (get_local 2) + (i64.trunc_s/f64) + (i64.add) + (get_local 3) + (i64.extend_i32_u) + (i64.add) + (get_local 0) + (i64.add) + (get_local 4) + (i64.add) + ) + )`).exports.f; + + testWithJit(() => { + assertEq(f(1n, 1.3, 1.7, 1, 1n), 5n); + }); +} + +function testGlobalImport() { + var exports = wasmEvalText( + `(module + (import "g" "a" (global $a i64)) + (import "g" "b" (global $b i64)) + (import "g" "c" (global $c i64)) + + (export "a" (global $a)) + (export "b" (global $b)) + (export "c" (global $c)) + )`, + { g: { a: 1n, b: 2n ** 63n, c: -100n } } + ).exports; + + testWithJit(() => { + assertEq(exports.a.value, 1n); + assertEq(exports.b.value, -(2n ** 63n)); + assertEq(exports.c.value, -100n); + }); +} + +function testMutableGlobalImport() { + var exports = wasmEvalText( + `(module + (import "g" "a" (global $a (mut i64))) + (import "g" "b" (global $b (mut i64))) + + (export "a" (global $a)) + (export "b" (global $b)) + )`, + { + g: { + a: new WebAssembly.Global({ value: "i64", mutable: true }, 1n), + b: new WebAssembly.Global({ value: "i64", mutable: true }, "2"), + }, + } + ).exports; + + testWithJit(() => { + assertEq(exports.a.value, 1n); + assertEq(exports.b.value, 2n); + }); +} + +function testMutableGlobalImportLiteral() { + assertErrorMessage( + () => + wasmEvalText( + `(module + (import "g" "a" (global $a (mut i64))) + )`, + { g: { a: 1n } } + ), + WebAssembly.LinkError, + "imported global mutability mismatch" + ); +} + +function testGlobalBadImportLiteral() { + assertErrorMessage( + () => + wasmEvalText( + `(module + (import "g" "a" (global $a i64)) + (export "a" (global $a)) + )`, + { g: { a: 1 } } + ), + WebAssembly.LinkError, + "import object field 'a' is not a BigInt" + ); + + assertErrorMessage( + () => + wasmEvalText( + `(module + (import "g" "a" (global $a i64)) + (export "a" (global $a)) + )`, + { g: { a: "foo" } } + ), + WebAssembly.LinkError, + "import object field 'a' is not a BigInt" + ); +} + +// This exercises error code paths that were added due to BigInt/I64 +// conversion, though the test does not directly deal with I64 types. +function testGlobalBadImportNumber() { + assertErrorMessage( + () => + wasmEvalText( + `(module + (import "g" "a" (global $a i32)) + (export "a" (global $a)) + )`, + { g: { a: 1n } } + ), + WebAssembly.LinkError, + "import object field 'a' is not a Number" + ); + + assertErrorMessage( + () => + wasmEvalText( + `(module + (import "g" "a" (global $a i32)) + (export "a" (global $a)) + )`, + { g: { a: "foo" } } + ), + WebAssembly.LinkError, + "import object field 'a' is not a Number" + ); +} + +function testI64Global() { + var global = new WebAssembly.Global({ value: "i64", mutable: true }); + + assertEq(global.value, 0n); // initial value + + global.value = 123n; + assertEq(global.value, 123n); + + global.value = 2n ** 63n; + assertEq(global.value, -(2n ** 63n)); + + global.value = "123"; + assertEq(global.value, 123n); +} + +function testI64GlobalValueOf() { + var argument = { value: "i64" }; + + // as literal + var global = new WebAssembly.Global(argument, { + valueOf() { + return 123n; + }, + }); + assertEq(global.value, 123n); + + // as string + var global2 = new WebAssembly.Global(argument, { + valueOf() { + return "123"; + }, + }); + assertEq(global.value, 123n); +} + +function testGlobalI64ValueWrongType() { + var argument = { value: "i64" }; + assertErrorMessage( + () => new WebAssembly.Global(argument, 666), + TypeError, + "can't convert 666 to BigInt" + ); + assertErrorMessage( + () => new WebAssembly.Global(argument, "foo"), + SyntaxError, + "invalid BigInt syntax" + ); + assertErrorMessage( + () => + new WebAssembly.Global(argument, { + valueOf() { + return 5; + }, + }), + TypeError, + "can't convert 5 to BigInt" + ); +} + +function testGlobalI64SetWrongType() { + var global = new WebAssembly.Global({ value: "i64", mutable: true }); + assertErrorMessage(() => (global.value = 1), TypeError, "can't convert 1 to BigInt"); + assertErrorMessage( + () => (global.value = "foo"), + SyntaxError, + "invalid BigInt syntax" + ); + assertErrorMessage( + () => + (global.value = { + valueOf() { + return 5; + }, + }), + TypeError, + "can't convert 5 to BigInt" + ); +} + +testRet(); +testId(); +testIdPlus(); +testNonBigIntArgs(); +testManyArgs(); +testImportExport(); +testMixedArgs(); +testGlobalImport(); +testMutableGlobalImport(); +testMutableGlobalImportLiteral(); +testGlobalBadImportLiteral(); +testGlobalBadImportNumber(); +testI64Global(); +testI64GlobalValueOf(); +testGlobalI64ValueWrongType(); +testGlobalI64SetWrongType(); |