diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/src/jit-test/tests/wasm/gc/call-indirect-subtyping.js | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/wasm/gc/call-indirect-subtyping.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/gc/call-indirect-subtyping.js | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/gc/call-indirect-subtyping.js b/js/src/jit-test/tests/wasm/gc/call-indirect-subtyping.js new file mode 100644 index 0000000000..4301621a8c --- /dev/null +++ b/js/src/jit-test/tests/wasm/gc/call-indirect-subtyping.js @@ -0,0 +1,137 @@ +// |jit-test| test-also=--wasm-tail-calls; skip-if: !wasmGcEnabled() + +// Test that call_indirect will respect subtyping by defining a bunch of types +// and checking every combination of (expected, actual) type. +// +// NOTE: Several of these types are identical to each other to test +// canonicalization as well, and this causes some bloat in the 'subtypeOf' +// lists. +const TESTS = [ + { + // (type 0) (equivalent to 1) + type: `(type (sub (func)))`, + subtypeOf: [0, 1], + }, + { + // (type 1) (equivalent to 0) + type: `(rec (type (sub (func))))`, + subtypeOf: [0, 1], + }, + { + // (type 2) + type: `(rec (type (sub (func))) (type (sub (func))))`, + subtypeOf: [2], + }, + { + // (type 3) + // Hack entry of previous to capture that it actually defines + // two types in the recursion group. + type: undefined, + subtypeOf: [3], + }, + { + // (type 4) (equivalent to 7) + type: `(type (sub 0 (func)))`, + subtypeOf: [0, 1, 4, 7], + }, + { + // (type 5) (equivalent to 8) + type: `(type (sub 4 (func)))`, + subtypeOf: [0, 1, 4, 5, 7, 8], + }, + { + // (type 6) + type: `(type (sub 5 (func)))`, + subtypeOf: [0, 1, 4, 5, 6, 7, 8], + }, + { + // (type 7) (equivalent to 4) + type: `(type (sub 0 (func)))`, + subtypeOf: [0, 1, 4, 7], + }, + { + // (type 8) (equivalent to 5) + type: `(type (sub 7 (func)))`, + subtypeOf: [0, 1, 4, 5, 7, 8], + }, + { + // (type 9) - a final type that has an immediate form + type: `(type (func))`, + subtypeOf: [9], + } +]; + +// Build a module with all the types, functions with those types, and functions +// that call_indirect with those types, and a table with all the functions in +// it. +let typeSection = ''; +let importedFuncs = ''; +let definedFuncs = ''; +let callIndirectFuncs = ''; +let returnCallIndirectFuncs = ''; +let i = 0; +for (let {type} of TESTS) { + if (type) { + typeSection += type + '\n'; + } + importedFuncs += `(func \$import${i} (import "" "import${i}") (type ${i}))\n`; + definedFuncs += `(func \$define${i} (export "define${i}") (type ${i}))\n`; + callIndirectFuncs += `(func (export "call_indirect ${i}") (param i32) + (drop (ref.cast (ref ${i}) (table.get local.get 0))) + (call_indirect (type ${i}) local.get 0) + )\n`; + if (wasmTailCallsEnabled()) { + returnCallIndirectFuncs += `(func (export "return_call_indirect ${i}") (param i32) + (drop (ref.cast (ref ${i}) (table.get local.get 0))) + (return_call_indirect (type ${i}) local.get 0) + )\n`; + } + i++; +} +let moduleText = `(module + ${typeSection} + ${importedFuncs} + ${definedFuncs} + ${callIndirectFuncs} + ${returnCallIndirectFuncs} + (table + (export "table") + funcref + (elem ${TESTS.map((x, i) => `\$import${i} \$define${i}`).join(" ")}) + ) +)`; + +// Now go over every combination of (actual, expected). In this case the caller +// (which does the call_indirect) specifies expected and the callee will be the +// actual. +let imports = { + "": Object.fromEntries(TESTS.map((x, i) => [`import${i}`, () => {}])), +}; +let exports = wasmEvalText(moduleText, imports).exports; +for (let callerTypeIndex = 0; callerTypeIndex < TESTS.length; callerTypeIndex++) { + for (let calleeTypeIndex = 0; calleeTypeIndex < TESTS.length; calleeTypeIndex++) { + let calleeType = TESTS[calleeTypeIndex]; + + // If the callee (actual) is a subtype of caller (expected), then this + // should succeed. + let shouldPass = calleeType.subtypeOf.includes(callerTypeIndex); + + let calleeImportFuncIndex = calleeTypeIndex * 2; + let calleeDefinedFuncIndex = calleeTypeIndex * 2 + 1; + + // print(`expected (type ${callerTypeIndex}) (actual ${calleeTypeIndex})`); + let test = () => { + exports[`call_indirect ${callerTypeIndex}`](calleeImportFuncIndex) + exports[`call_indirect ${callerTypeIndex}`](calleeDefinedFuncIndex) + if (wasmTailCallsEnabled()) { + exports[`return_call_indirect ${callerTypeIndex}`](calleeImportFuncIndex) + exports[`return_call_indirect ${callerTypeIndex}`](calleeDefinedFuncIndex) + } + }; + if (shouldPass) { + test(); + } else { + assertErrorMessage(test, WebAssembly.RuntimeError, /mismatch|cast/); + } + } +} |