diff options
Diffstat (limited to 'js/src/jit-test/tests/wasm/regress')
90 files changed, 2569 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/regress/baseline-arm64-chunk-pop.js b/js/src/jit-test/tests/wasm/regress/baseline-arm64-chunk-pop.js new file mode 100644 index 0000000000..23aa5934a4 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-arm64-chunk-pop.js @@ -0,0 +1,31 @@ +var bin = wasmTextToBinary( + `(module + (func (export "f4786") (result i32) + (local i32 i64 i64 i64 f32) + i32.const 1 + tee_local 0 + local.get 0 + local.get 0 + local.get 0 + local.get 0 + local.get 0 + local.get 0 + local.get 0 + if (result i32) + local.get 0 + else + local.get 0 + tee_local 0 + local.get 0 + br_if 1 + end + drop + drop + drop + drop + drop + drop + drop))`); +var ins = new WebAssembly.Instance(new WebAssembly.Module(bin)); +ins.exports.f4786(); + diff --git a/js/src/jit-test/tests/wasm/regress/baseline-builtin-abi.js b/js/src/jit-test/tests/wasm/regress/baseline-builtin-abi.js new file mode 100644 index 0000000000..16de2dc400 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-builtin-abi.js @@ -0,0 +1,20 @@ +// Bug 1488515 - ABI issues on Android because both the baseline compiler and +// the builtin thunks converted between hardFP and softFP. + +var prog = wasmEvalText( + `(module + (func $f64div (export "test") (param $a f64) (param $b f64) (result f64) + (local $dummy0 i32) + (local $dummy1 i32) + (local $dummy2 i32) + (local $dummy3 i32) + (local $dummy4 i32) + (local $x f64) + (local $y f64) + (local $z f64) + (local.set $x (local.get $a)) + (local.set $y (local.get $b)) + (local.set $z (f64.floor (f64.div (local.get $x) (local.get $y)))) + (local.get $z)))`); + +assertEq(prog.exports.test(16096, 32), 503); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-bytereg.js b/js/src/jit-test/tests/wasm/regress/baseline-bytereg.js new file mode 100644 index 0000000000..8bdcc32618 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-bytereg.js @@ -0,0 +1,34 @@ +// Bug 1322450 is about the baseline compiler not properly handling a byte store +// from a wider datum on 32-bit x86 because it does not move the value to be +// stored to a valid byte register if it is in a 32-bit register that does not +// have a byte part (EDI/ESI/EBP). +// +// This test is white-box because it knows about the register allocation order: +// the two values pushed onto the stack occupy EAX and ECX, and the i64.store8 +// will use EDX for the index and (EDI or ESI or EBP) for the low register of +// the value to be stored. The i64.store8 instruction will then assert in the +// assembler. +// +// If the baseline compiler starts allocating registers in a different order +// then this test will be ineffective. + +wasmEvalText(`(module + (memory 1) + (func $run (param i64) (param i32) (param i32) + local.get 1 + local.get 2 + i32.add + + local.get 1 + local.get 2 + i32.add + + i32.const 0 + local.get 0 + i64.store8 + + drop + drop + ) + (export "run" (func $run)) +)`); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-extend8.js b/js/src/jit-test/tests/wasm/regress/baseline-extend8.js new file mode 100644 index 0000000000..6e637e97c9 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-extend8.js @@ -0,0 +1,34 @@ +// This attempts to test that we can do an 8-bit sign extend no matter what the +// source register. This test is arguably somewhat tied to the baseline +// compiler's register allocator, but is still appropriate for most simple +// register allocators. It works by filling an increasing number of registers +// with values so as eventually to force the source operand for extend8_s into a +// register that does not have a byte personality. + +for ( let i=0; i < 8; i++) { + let txt = + `(module + (func (export "f") (param i32) (result i32) + ${adds(i)} + (local.set 0 (i32.extend8_s (i32.add (local.get 0) (i32.const 1)))) + ${drops(i)} + (local.get 0)))`; + let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(txt))); + assertEq(ins.exports.f(254), -1); +} + +function adds(n) { + let s = "" + for ( let i=0; i < n; i++ ) + s += "(i32.add (local.get 0) (i32.const 1))\n"; + return s; +} + +function drops(n) { + let s = ""; + for ( let i=0; i < n; i++ ) + s += "drop\n"; + return s; +} + + diff --git a/js/src/jit-test/tests/wasm/regress/baseline-getglobal-scratch.js b/js/src/jit-test/tests/wasm/regress/baseline-getglobal-scratch.js new file mode 100644 index 0000000000..2f4d74b912 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-getglobal-scratch.js @@ -0,0 +1,58 @@ +new WebAssembly.Module(wasmTextToBinary(` +(module + (global $g (mut i32) (i32.const 42)) + (func (param $i i32) + local.get $i + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + unreachable + ) +) +`)); + +new WebAssembly.Module(wasmTextToBinary(` +(module + (global $g (mut i32) (i32.const 42)) + (func (param $i i32) + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + global.get $g + local.get $i + global.set $g + unreachable + ) +) +`)); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-i64-opt-cmp.js b/js/src/jit-test/tests/wasm/regress/baseline-i64-opt-cmp.js new file mode 100644 index 0000000000..eb6cafb8f0 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-i64-opt-cmp.js @@ -0,0 +1,16 @@ +// Bug 1404760: Optimized compare-and-branch with a preserved value would fail +// the baseline compiler on x86 debug builds (and would just generate bad code +// on non-debug builds) because of register starvation. + +wasmEvalText( + `(module + (func $run (param i64) (param i64) (result i64) + block (result i64) + i64.const 1 + (i64.lt_s (local.get 0) (local.get 1)) + br_if 0 + drop + i64.const 2 + end) + (export "run" (func $run)))` +); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-joinreg.js b/js/src/jit-test/tests/wasm/regress/baseline-joinreg.js new file mode 100644 index 0000000000..01bc3d5bbc --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-joinreg.js @@ -0,0 +1,16 @@ +// Bug 1322288 is about the floating join register not being reserved properly +// in the presence of boolean evaluation for control. The situation is that a +// conditional branch passes a floating point value to the join point; the join register +// must be available when it does that, but could have been allocated to the operands of +// the conditional expression of the control flow. +// +// This test is white-box: it depends on the floating join reg being among the first +// floating registers to be allocated. + +wasmEvalText(` +(module + (func $run + (drop (block (result f64) + (drop (br_if 0 (f64.const 1) (f64.eq (f64.const 1) (f64.const 0)))) + (drop (br 0 (f64.const 2)))))) + (export "run" (func $run)))`); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-many-results.js b/js/src/jit-test/tests/wasm/regress/baseline-many-results.js new file mode 100644 index 0000000000..ff4d9c35dd --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-many-results.js @@ -0,0 +1,63 @@ +// This provokes a crash in baseline if its Stk reservation logic is not up to +// snuff, bug 1675844. + +var txt = ` +(module + (type (;0;) (func (result f32 f32 i32))) + (func $main (type 0) (result f32 f32 i32) + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + memory.size + call $main + call $main + call $main + call_indirect (type 0) + call $main + call $main + call $main + call $main + call $main + call $main + memory.size + call $main + call $main + call $main + call_indirect (type 0) + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + call $main + memory.size) + (table (;0;) 62 255 funcref) + (memory (;0;) 15 18) + (export "t1" (table 0)) + (export "memory" (memory 0)))`; +assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(txt)), + WebAssembly.CompileError, + /(unused values not explicitly dropped)|(expected f32, found i32)/); + diff --git a/js/src/jit-test/tests/wasm/regress/baseline-nops-jumptable.js b/js/src/jit-test/tests/wasm/regress/baseline-nops-jumptable.js new file mode 100644 index 0000000000..e4388296fb --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-nops-jumptable.js @@ -0,0 +1,12 @@ +// |jit-test| --arm-asm-nop-fill=1 +var f = wasmEvalText(`(module (func (param i32) (result i32) + (block $0 + (block $1 + (block $2 + (block $default + (br_table $0 $1 $2 $default (local.get 0)))))) + (return (i32.const 0))) + (export "" (func 0)) +)`).exports[""]; + +f(0); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-pop-along-edge.js b/js/src/jit-test/tests/wasm/regress/baseline-pop-along-edge.js new file mode 100644 index 0000000000..650931c99a --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-pop-along-edge.js @@ -0,0 +1,66 @@ +// Bug 1316181 + +// There are locals with different values here to ensure that the +// local.get at the end picks up the right one even if the stack might +// have become unbalanced by a failure to adjust SP along the branch +// edge. The logic is that we use SP-relative addressing, and if the +// actual SP is not what the compiler thinks it is we will read +// something other than the expected value. + +var o = wasmEvalText( + `(module + (func (result i32) + (local $v0 i32) + (local $v1 i32) + (local $v2 i32) + (local $v3 i32) + (local $v4 i32) + (local $v5 i32) + (local $v6 i32) + (local $v7 i32) + (local $res i32) + (local.set $v0 (i32.const 0xDEADBEEF)) + (local.set $v1 (i32.const 0xFDEADBEE)) + (local.set $v2 (i32.const 0xEFDEADBE)) + (local.set $v3 (i32.const 0xEEFDEADB)) + (local.set $v4 (i32.const 0xBEEFDEAD)) + (local.set $v5 (i32.const 0xDBEEFDEA)) + (local.set $v6 (i32.const 0xADBEEFDE)) + (local.set $v7 (i32.const 0xEADBEEFD)) + (block $b + (local.set $res + (i32.add + (i32.add (i32.const 1) (i32.const 2)) + (i32.add + (i32.add (i32.const 3) (i32.const 4)) + (i32.add + (i32.add (i32.const 5) (i32.const 6)) + (i32.add + (i32.add (i32.const 7) (i32.const 8)) + (i32.add + (i32.add (i32.const 9) (i32.const 10)) + (i32.add + (i32.add (i32.const 11) (i32.const 12)) + (i32.add + (i32.add (i32.const 13) (i32.const 14)) + (i32.add + (i32.add (i32.const 15) (i32.const 16)) + (i32.add + (i32.add (i32.const 17) (i32.const 18)) + (i32.add + (i32.add (i32.const 19) (i32.const 20)) + (i32.add + (i32.add (i32.const 21) (i32.const 22)) + (i32.add + (i32.add (i32.const 23) (i32.const 24)) + (i32.add + (i32.add (i32.const 25) (i32.const 26)) + (i32.add + (i32.add (i32.const 27) (i32.const 28)) + (i32.add + (i32.add (i32.const 29) (i32.const 30)) + (br_if $b (i32.const 31) (i32.const 1))))))))))))))))))) + (return (local.get $v3))) + (export "a" (func 0)))`).exports; + +assertEq(o["a"](), 0xEEFDEADB|0); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-pop-before-capture.js b/js/src/jit-test/tests/wasm/regress/baseline-pop-before-capture.js new file mode 100644 index 0000000000..b3a41f6949 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-pop-before-capture.js @@ -0,0 +1,12 @@ +// Bug 1319415 + +var src = +`(module + (func (result i32) + i32.const 0 + i32.const 1 + br_if 0 + unreachable) + (export "run" (func 0)))`; + +wasmFullPass(src, 0); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-stack-height.js b/js/src/jit-test/tests/wasm/regress/baseline-stack-height.js new file mode 100644 index 0000000000..185a7c3069 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-stack-height.js @@ -0,0 +1 @@ +new WebAssembly.Module(os.file.readFile(scriptdir + "/baseline-stack-height.wasm", 'binary')); diff --git a/js/src/jit-test/tests/wasm/regress/baseline-stack-height.wasm b/js/src/jit-test/tests/wasm/regress/baseline-stack-height.wasm Binary files differnew file mode 100644 index 0000000000..cc25a1dac8 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/baseline-stack-height.wasm diff --git a/js/src/jit-test/tests/wasm/regress/brtable-conditionblock-folding.js b/js/src/jit-test/tests/wasm/regress/brtable-conditionblock-folding.js new file mode 100644 index 0000000000..6692a7473b --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/brtable-conditionblock-folding.js @@ -0,0 +1,17 @@ +assertEq(wasmEvalText(` +(module + (func $f (param $p i32) + block $out + i32.const 0 + if + i32.const 1 + tee_local $p + br_table $out $out + end + end + local.get $p + br_if 0 + ) + (export "f" (func $f)) +) +`).exports.f(42), undefined); diff --git a/js/src/jit-test/tests/wasm/regress/bug1300546.js b/js/src/jit-test/tests/wasm/regress/bug1300546.js new file mode 100644 index 0000000000..2897995deb --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1300546.js @@ -0,0 +1,28 @@ +try { + wasmEvalText(` + (module + (type $type0 (func)) + (func $func0 + (nop) + (f64.load offset=59 align=1 (i32.const 0)) + (memory.size) + (memory.size) + (memory.size) + (memory.size) + (memory.size) + (memory.size) + (memory.size) + (memory.size) + (i64.rem_s (i64.const 17) (i64.xor (i64.const 17) (i64.xor (i64.const 17) (i64.xor (i64.xor (i64.const 17) (i64.const 17)) (i64.xor (i64.const 17) (i64.const 17)))))) + + (i64.rem_s + (i64.const 17) + (i64.xor + (i64.rem_s (i64.const 17) (i64.const 17)) + (i64.xor (i64.rem_s (i64.const 17) (i64.const 17)) (i64.xor (i64.const 17) (i64.const 17))))) + ) + (memory 1 1) + ) + `); +} catch(e) { +} diff --git a/js/src/jit-test/tests/wasm/regress/bug1311019.js b/js/src/jit-test/tests/wasm/regress/bug1311019.js new file mode 100644 index 0000000000..3c5c39e352 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1311019.js @@ -0,0 +1,9 @@ +new WebAssembly.Module(wasmTextToBinary(`(module + (memory 1) + (func + (i64.trunc_s/f32 (f32.const 6.96875)) + (i32.load8_s (i32.const 0)) + (f32.const -7.66028056e-31) + (unreachable) + ) +)`)); diff --git a/js/src/jit-test/tests/wasm/regress/bug1392105.js b/js/src/jit-test/tests/wasm/regress/bug1392105.js new file mode 100644 index 0000000000..4752da8ddf --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1392105.js @@ -0,0 +1,8 @@ +// |jit-test| --arm-asm-nop-fill=1 + +var code = "(module "; +for (var i = 0; i < 100; i++) + code += "(func (param i32) (result i32) (i32.add (i32.const 1) (local.get 0))) "; +code += ")"; +var buf = wasmTextToBinary(code); +WebAssembly.compile(buf); diff --git a/js/src/jit-test/tests/wasm/regress/bug1440512.js b/js/src/jit-test/tests/wasm/regress/bug1440512.js new file mode 100644 index 0000000000..1997b34f7f --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1440512.js @@ -0,0 +1,216 @@ +// |jit-test| skip-if: !wasmDebuggingEnabled() +var g = newGlobal({newCompartment: true}); +var dbg = new g.Debugger(this); +var dbg = new Debugger; +var kWasmH0 = 0; +var kWasmH1 = 0x61; +var kWasmH2 = 0x73; +var kWasmH3 = 0x6d; +var kWasmV0 = 0x1; +var kWasmV1 = 0; +var kWasmV2 = 0; +var kWasmV3 = 0; +let kTypeSectionCode = 1; // Function signature declarations +let kImportSectionCode = 2; // Import declarations +let kFunctionSectionCode = 3; // Function declarations +let kExportSectionCode = 7; // Exports +let kCodeSectionCode = 10; // Function code +let kWasmFunctionTypeForm = 0x60; +let kWasmI32 = 0x7f; +let kExternalFunction = 0; +let kSig_i_i = makeSig([kWasmI32], [kWasmI32]); +function makeSig(params, results) { + return { + params: params, + results: results + }; +} +let kExprEnd = 0x0b; +let kExprGetLocal = 0x20; +class Binary extends Array { + emit_u8(val) { + this.push(val); + } + emit_u32v(val) { + while (true) { + let v = val & 0xff; + val = val >>> 7; + this.push(v); + break; + } + } + emit_bytes(data) { + for (let i = 0; i < data.length; i++) { + this.push(data[i] & 0xff); + } + } + emit_string(string) { + let string_utf8 = unescape(encodeURIComponent(string)); + this.emit_u32v(string_utf8.length); + for (let i = 0; i < string_utf8.length; i++) { + this.emit_u8(string_utf8.charCodeAt(i)); + } + } + emit_header() { + this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3); + } + emit_section(section_code, content_generator) { + this.emit_u8(section_code); + let section = new Binary; + content_generator(section); + this.emit_u32v(section.length); + for (var i = 0; i < section.length; i++) this.push(section[i]); + } +} +class WasmFunctionBuilder { + constructor(module, name, type_index) { + this.module = module; + } + exportAs(name) { + this.module.addExport(name, this.index); + } + addBody(body) { + this.body = body.slice(); + this.body.push(kExprEnd); + return this; + } +} +class WasmModuleBuilder { + constructor() { + this.types = []; + this.imports = []; + this.exports = []; + this.functions = []; + } + addType(type) { + this.types.push(type); + } + addFunction(name, type) { + let type_index = (typeof type) == "number" ? type : this.addType(type); + let func = new WasmFunctionBuilder(this, name, type_index); + this.functions.push(func); + return func; + } + addImport(module = "", name, type) { + this.imports.push({ + module: module, + name: name, + kind: kExternalFunction, + }); + } + addExport(name, index) { + this.exports.push({ + name: name, + }); + } + toArray(debug = false) { + let binary = new Binary; + let wasm = this; + binary.emit_header(); + if (wasm.types.length > 0) { + binary.emit_section(kTypeSectionCode, section => { + section.emit_u32v(wasm.types.length); + for (let type of wasm.types) { + section.emit_u8(kWasmFunctionTypeForm); + section.emit_u32v(type.params.length); + for (let param of type.params) { + section.emit_u8(param); + } + section.emit_u32v(type.results.length); + for (let result of type.results) { + section.emit_u8(result); + } + } + }); + binary.emit_section(kImportSectionCode, section => { + section.emit_u32v(wasm.imports.length); + for (let imp of wasm.imports) { + section.emit_string(imp.module); + section.emit_string(imp.name || ''); + section.emit_u8(imp.kind); + if (imp.kind == kExternalFunction) { + section.emit_u32v(imp.type); + } + } + }); + binary.emit_section(kFunctionSectionCode, section => { + section.emit_u32v(wasm.functions.length); + for (let func of wasm.functions) { + section.emit_u32v(func.type_index); + } + }); + } + var mem_export = (wasm.memory !== undefined && wasm.memory.exp); + var exports_count = wasm.exports.length + (mem_export ? 1 : 0); + if (exports_count > 0) { + binary.emit_section(kExportSectionCode, section => { + section.emit_u32v(exports_count); + for (let exp of wasm.exports) { + section.emit_string(exp.name); + section.emit_u8(exp.kind); + section.emit_u8(0); + } + }); + } + if (wasm.start_index !== undefined) { + } + if (wasm.functions.length > 0) { + binary.emit_section(kCodeSectionCode, section => { + section.emit_u32v(wasm.functions.length); + for (let func of wasm.functions) { + let local_decls = []; + let header = new Binary; + header.emit_u32v(local_decls.length); + section.emit_u32v(header.length + func.body.length); + section.emit_bytes(header); + section.emit_bytes(func.body); + } + }); + } + let num_function_names = 0; + let num_functions_with_local_names = 0; + if (num_function_names > 0 || num_functions_with_local_names > 0 || wasm.name !== undefined) { + binary.emit_section(kUnknownSectionCode, section => { + if (num_function_names > 0) { + } + }); + } + return binary; + } + toBuffer(debug = false) { + let bytes = this.toArray(debug); + let buffer = new ArrayBuffer(bytes.length); + let view = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; i++) { + let val = bytes[i]; + view[i] = val | 0; + } + return buffer; + } + toModule(debug = false) { + return new WebAssembly.Module(this.toBuffer(debug)); + } +} +const verifyHeap = gc; +function testProperties(obj) { + for (let i = 0; i < 3; i++) { + verifyHeap(); + } +} +(function ExportedFunctionTest() { + var builder = new WasmModuleBuilder(); + builder.addFunction("exp", kSig_i_i).addBody([ + kExprGetLocal, 0, + ]).exportAs("exp"); + let module1 = builder.toModule(); + let instance1 = new WebAssembly.Instance(module1); + let g = instance1.exports.exp; + testProperties(g); + builder.addImport("imp", "func", kSig_i_i); + let module2 = builder.toModule(); + let instance2 = new WebAssembly.Instance(module2, { + imp: { + func: g + } + }); +})(); diff --git a/js/src/jit-test/tests/wasm/regress/bug1450800.js b/js/src/jit-test/tests/wasm/regress/bug1450800.js new file mode 100644 index 0000000000..fb8493c102 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1450800.js @@ -0,0 +1,27 @@ +// |jit-test| skip-if: !this.gczeal || !WebAssembly.Global + +gczeal(9, 10); +function wasmEvalText(str, imports) { + let binary = wasmTextToBinary(str); + m = new WebAssembly.Module(binary); + return new WebAssembly.Instance(m, imports); +} +assertEq(wasmEvalText(`(module + (global (import "a" "b") i32) + (export "g" (global 0)) + (func (export "get") (result i32) global.get 0))`, + { a: { b: 42 }}).exports.get(), + 42); +for (let v of []) {} +function testInitExpr(type, initialValue, nextValue, coercion, assertFunc = assertEq) { + var module = wasmEvalText(`(module + (import "globals" "a" (global ${type})) + (global $glob_imm ${type} (global.get 0)) + (export "global_imm" (global $glob_imm)) + )`, { + globals: { + a: coercion(initialValue) + } + }).exports; +} +testInitExpr('i32', 13, 37, x => x | 0); diff --git a/js/src/jit-test/tests/wasm/regress/bug1467415.js b/js/src/jit-test/tests/wasm/regress/bug1467415.js new file mode 100644 index 0000000000..177e67ba08 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1467415.js @@ -0,0 +1,29 @@ + +// This exposed an alias analysis bug in the Wasm Ion machinery. It should +// compute 125 (88 + 37) but with the bug would compute 176 (88 + 88) instead. +// See bug 1467415. + +let mt = ` +(module + (import "m" "g" (global (mut i32))) + (import "m" "h" (global (mut i32))) + (memory 1 1) + (data (i32.const 0) "\\01\\00\\00\\00\\01\\00\\00\\00\\01\\00\\00\\00") + (func (export "f") (result i32) + (local i32) + (local i32) + (block (result i32) + (local.set 0 (global.get 0)) + (block (result i32) + (global.set 1 (i32.const 37)) + (block (result i32) + (local.set 1 (global.get 0)) + (i32.add (local.get 0) (local.get 1))))))) +`; + +let glob = new WebAssembly.Global({value:'i32', mutable:true}, 88); +let module = new WebAssembly.Module(wasmTextToBinary(mt)); +let ins = new WebAssembly.Instance(module, {m:{g:glob, h:glob}}); + +let shouldBe125 = ins.exports.f(); +assertEq(shouldBe125, 125); diff --git a/js/src/jit-test/tests/wasm/regress/bug1491322.js b/js/src/jit-test/tests/wasm/regress/bug1491322.js new file mode 100644 index 0000000000..ae3d6a0e73 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1491322.js @@ -0,0 +1,35 @@ +// |jit-test| skip-if: !wasmDebuggingEnabled() +var evalInFrame = (function(global) { + var dbgGlobal = newGlobal({newCompartment: true}); + var dbg = new dbgGlobal.Debugger(); + dbg.addDebuggee(global); +})(this); +const Module = WebAssembly.Module; +const Instance = WebAssembly.Instance; +var m = new Module(wasmTextToBinary(`(module + (import "" "foo" (func $foo (result i32))) + (import "" "bar" (func $bar (result i32))) + (table 3 funcref) + (func $baz (result i32) (i32.const 13)) + (elem (i32.const 0) $foo $bar $baz) + (export "tbl" (table 0)) +)`)); +var jsFun = () => 83; +var wasmFun = new Instance( + new Module( + wasmTextToBinary('(module (func (result i32) (i32.const 42)) (export "foo" (func 0)))') + ) +).exports.foo; +var e1 = new Instance(m, { + "": { + foo: jsFun, + bar: wasmFun + } +}).exports; +var e2 = new Instance(m, { + "": { + foo: jsFun, + bar: jsFun + } +}).exports; +e2.tbl.get(0); diff --git a/js/src/jit-test/tests/wasm/regress/bug1502886.js b/js/src/jit-test/tests/wasm/regress/bug1502886.js new file mode 100644 index 0000000000..a45bf774a4 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1502886.js @@ -0,0 +1,30 @@ +newGlobal({newCompartment: true}); +g = newGlobal({newCompartment: true}); +var dbg = Debugger(g); +gczeal(2, 100); +function f(x, initFunc) { + newGlobal({newCompartment: true}); + g.eval(` + var binary = wasmTextToBinary('${x}'); + new WebAssembly.Instance(new WebAssembly.Module(binary)); + `); + var wasmScript = dbg.findScripts().filter(s => s.format == 'wasm')[0]; + var offsets = wasmScript.getPossibleBreakpointOffsets(); + initFunc({ + wasmScript, + breakpoints: offsets + }) +}; +try { + f('(module (func nop nop) (export "" (func 0)))', + function({ + wasmScript, + breakpoints + }) { + breakpoints.forEach(function(offset) { + wasmScript.setBreakpoint(offset, s = {}); + }); + } + ); + f(); +} catch (e) {} diff --git a/js/src/jit-test/tests/wasm/regress/bug1507314.js b/js/src/jit-test/tests/wasm/regress/bug1507314.js new file mode 100644 index 0000000000..db07593d87 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1507314.js @@ -0,0 +1,6 @@ +// |jit-test| --no-sse4 +if (!wasmCachingEnabled()) + quit(0); + +var m = wasmCompileInSeparateProcess(wasmTextToBinary('(module (func (export "run") (result i32) (i32.const 42)))')); +assertEq(new WebAssembly.Instance(m).exports.run(), 42); diff --git a/js/src/jit-test/tests/wasm/regress/bug1533204.js b/js/src/jit-test/tests/wasm/regress/bug1533204.js new file mode 100644 index 0000000000..e901fd066b --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1533204.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: helperThreadCount() === 0 +enableOsiPointRegisterChecks(); +evalInWorker(` +function DiagModule(stdlib, foreign) { + "use asm"; + function diag() { + while(1) {} + } + return {}; +`); diff --git a/js/src/jit-test/tests/wasm/regress/bug1566992.js b/js/src/jit-test/tests/wasm/regress/bug1566992.js new file mode 100644 index 0000000000..52d2c0710c --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1566992.js @@ -0,0 +1,14 @@ +let { exports: { f } } = wasmEvalText(` +(module + (func (export "f") + (block + i64.const 0xfffffffe00000000 + i32.wrap_i64 + br_table 0 1 + ) + unreachable + ) +) +`); + +assertErrorMessage(f, WebAssembly.RuntimeError, /unreachable/); diff --git a/js/src/jit-test/tests/wasm/regress/bug1569137.js b/js/src/jit-test/tests/wasm/regress/bug1569137.js new file mode 100644 index 0000000000..fc0a4a3c39 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1569137.js @@ -0,0 +1,65 @@ +let { exports: { f } } = wasmEvalText(` +(module + (memory $0 1 1) + + (func (export "f") (result f32) + (local $0 i32) (local $1 f64) (local $2 i32) + + (set_local 0 (i32.const 134219779)) + (set_local 1 (f64.const 3810600700439633677210579e165)) + + (f32.floor + (loop $label$2 (result f32) + (br_if $label$2 + (i32.load offset=3 align=2 + (block $label$4 (result i32) + (drop + (if (result f64) + (br_if $label$4 + (i32.const 4883) + (i32.const -124) + ) + (f64.const 77) + (block (result f64) + (drop + (br_if $label$4 + (i32.const 4194304) + (i32.const -8192) + ) + ) + (return + (f32.const 4294967296) + ) + ) + ) + ) + (br_if $label$4 + (br_if $label$4 + (i32.const -90) + (br_if $label$4 + (br_if $label$4 + (local.get $2) + (i32.const -16) + ) + (i32.const 15656) + ) + ) + (block $label$18 (result i32) + (i32.eqz + (br_if $label$4 + (i32.const -1) + (i32.const 15) + ) + ) + ) + ) + ) + ) + ) + (f32.const 23) + ) + ) + ) +)`); + +f(); diff --git a/js/src/jit-test/tests/wasm/regress/bug1590920.js b/js/src/jit-test/tests/wasm/regress/bug1590920.js new file mode 100644 index 0000000000..1f92db1129 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1590920.js @@ -0,0 +1,11 @@ +let { exports } = new WebAssembly.Instance(new WebAssembly.Module( + wasmTextToBinary(` + (module + (func (export "g") + (drop + (block (result i32) + (i32.clz (i32.const 1)) + (if + (i32.const 1) + (return))))))`))); +exports.g(); diff --git a/js/src/jit-test/tests/wasm/regress/bug1678542.js b/js/src/jit-test/tests/wasm/regress/bug1678542.js new file mode 100644 index 0000000000..8c3f44fa6d --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1678542.js @@ -0,0 +1,11 @@ +var ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(` +(module + (global $g (export "g") (mut f64) (f64.const 0)) + (func $p (param f64) (result f64) (local.get 0)) + (func (export "f") (param f64) (result f64) + (global.set $g (f64.neg (local.get 0))) + (call $p (local.get 0))))`))); +assertEq(ins.exports.f(3), 3); +assertEq(ins.exports.g.value, -3); + + diff --git a/js/src/jit-test/tests/wasm/regress/bug1678785.js b/js/src/jit-test/tests/wasm/regress/bug1678785.js new file mode 100644 index 0000000000..b04ac8480b --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1678785.js @@ -0,0 +1,20 @@ + +// This exposed a bug in CL's aarch64 isel, in which the -4098 was +// incorrectly sign-extended out to 64 bits. + +let { exports } = new WebAssembly.Instance(new WebAssembly.Module( + wasmTextToBinary(` + (module + (type (;0;) (func)) + (type (;1;) (func (result i32))) + (type (;2;) (func (result i64))) + (func (;0;) (type 0) + i32.const -4098 + i32.load16_s offset=1 + drop) + (memory (;0;) 1) + (export "g" (func 0)))` ))); +try { + exports.g(); +} catch (e) {} + diff --git a/js/src/jit-test/tests/wasm/regress/bug1684861.js b/js/src/jit-test/tests/wasm/regress/bug1684861.js new file mode 100644 index 0000000000..4cb9bb2383 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1684861.js @@ -0,0 +1,54 @@ +const oob = /index out of bounds/; +const unaligned = /unaligned memory access/; +const RuntimeError = WebAssembly.RuntimeError; + +// Test memory.atomic.notify unaligned access. +const module = new WebAssembly.Module(wasmTextToBinary(`(module + (type (;0;) (func)) + (func $main (type 0) + i32.const -64 + i32.const -63 + memory.atomic.notify offset=1 + unreachable) + (memory (;0;) 4 4) + (export "main" (func $main)))`)); + +const instance = new WebAssembly.Instance(module); +assertErrorMessage(() => instance.exports.main(), RuntimeError, unaligned); + +// Test memory.atomic.notify oob access. +const module2 = new WebAssembly.Module(wasmTextToBinary(`(module + (type (;0;) (func)) + (func $main (type 0) + i32.const -64 + i32.const -63 + memory.atomic.notify offset=65536 + unreachable) + (memory (;0;) 4 4) + (export "main" (func $main)))`)); + +const instance2 = new WebAssembly.Instance(module2); +assertErrorMessage(() => instance2.exports.main(), RuntimeError, oob); + +// Test memory.atomic.wait32 and .wait64 unaligned access. +const module3 = new WebAssembly.Module(wasmTextToBinary(`(module + (type (;0;) (func)) + (func $wait32 (type 0) + i32.const -64 + i32.const 42 + i64.const 0 + memory.atomic.wait32 offset=1 + unreachable) + (func $wait64 (type 0) + i32.const -64 + i64.const 43 + i64.const 0 + memory.atomic.wait64 offset=3 + unreachable) + (memory (;0;) 4 4 shared) + (export "wait32" (func $wait32)) + (export "wait64" (func $wait64)))`)); + +const instance3 = new WebAssembly.Instance(module3); +assertErrorMessage(() => instance3.exports.wait32(), RuntimeError, unaligned); +assertErrorMessage(() => instance3.exports.wait64(), RuntimeError, unaligned); diff --git a/js/src/jit-test/tests/wasm/regress/bug1699647.js b/js/src/jit-test/tests/wasm/regress/bug1699647.js new file mode 100644 index 0000000000..499b88b36d --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1699647.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: !wasmSimdEnabled() || !getBuildConfiguration().x86 + +const module = new Uint8Array([ + 0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0, + 5,4,1,1,0,0,7,10,1,6,109,101,109,111,114,121,2,0,10,49, + 1,47,0,65,16,253,1,1,1,253,253,1,253,131,1,65,158,232, + 68,253,1,1,1,253,100,65,16,253,1,1,1,253,11,0,0,253,1,1, + 1,65,158,232,68,253,1,1,0,0,11,0,14,4,110,97,109,101,1, + 7,1,0,4,109,97,105,110]); +new WebAssembly.Module(module) diff --git a/js/src/jit-test/tests/wasm/regress/bug1700610.js b/js/src/jit-test/tests/wasm/regress/bug1700610.js new file mode 100644 index 0000000000..ce8b032074 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1700610.js @@ -0,0 +1,8 @@ +// |jit-test| skip-if: !wasmSimdEnabled() || !getBuildConfiguration().x86 + +const module = new Uint8Array([ + 0,97,115,109,1,0,0,0,1,6,1,96,1,127,1,111,3,2,1,0,5,4,1,1,0,0,10,38,1,36, + 0,65,1,253,4,0,81,253,21,1,253,4,0,81,253,21,0,253,1,0,81,253,21,1,253,4, + 0,81,253,21,0,50,0,0,0,11,0,14,4,110,97,109,101,1,7,1,0,4,109,97,105,110 +]); +new WebAssembly.Module(module) diff --git a/js/src/jit-test/tests/wasm/regress/bug1708124.js b/js/src/jit-test/tests/wasm/regress/bug1708124.js new file mode 100644 index 0000000000..dc035b02e5 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1708124.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: !('oomTest' in this) +// Ensure that trap reporting mechanism doesn't crash under OOM conditions. + +oomTest( + wasmEvalText( + `(module + (func (export "f") (result) + unreachable))` + ).exports.f +); diff --git a/js/src/jit-test/tests/wasm/regress/bug1713581.js b/js/src/jit-test/tests/wasm/regress/bug1713581.js new file mode 100644 index 0000000000..a7201ccb22 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1713581.js @@ -0,0 +1,13 @@ +function wasmEvalText(str, imports, options) { + let binary = wasmTextToBinary(str); + m = new WebAssembly.Module(binary, options); + return new WebAssembly.Instance(m, imports); +} +let ins = wasmEvalText(` + (module + (func (export "fill0") (param $r externref)) + ) +`); +for (let i53 = 0; i53 < 1000; i53++) { + ins.exports.fill0("hello") +} diff --git a/js/src/jit-test/tests/wasm/regress/bug1727284/directives.txt b/js/src/jit-test/tests/wasm/regress/bug1727284/directives.txt new file mode 100644 index 0000000000..82e51d5a01 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1727284/directives.txt @@ -0,0 +1 @@ +|jit-test| --fast-warmup; --ion-warmup-threshold=0; --wasm-compiler=optimizing; include:wasm.js diff --git a/js/src/jit-test/tests/wasm/regress/bug1727284/test.js b/js/src/jit-test/tests/wasm/regress/bug1727284/test.js new file mode 100644 index 0000000000..54d7350be9 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1727284/test.js @@ -0,0 +1,12 @@ +function test() { + let instance = wasmEvalText(` + (module + (global $g (mut externref) (ref.null extern)) + (func (export "set") (param externref) local.get 0 global.set $g) + ) + `).exports; + let obj = { field: null }; + instance.set(obj); + for (var v4 = 0; v4 < 10; v4++) {} +} +test(); diff --git a/js/src/jit-test/tests/wasm/regress/bug1747870.js b/js/src/jit-test/tests/wasm/regress/bug1747870.js new file mode 100644 index 0000000000..2625e965fb --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1747870.js @@ -0,0 +1,19 @@ +// |jit-test| skip-if: !wasmSimdEnabled() + +// This should not release-assert, which it could previously do on some 32-bit +// platforms due to the too-limited size of a bitfield. + +const MaxParams = 1000; // Per spec + +var params = ''; +for ( var i=0 ; i < MaxParams-1; i++ ) { + params += '(param v128) ' +} +params += '(param externref)' + +new WebAssembly.Module(wasmTextToBinary(` +(module + (func $f) + (func ${params} (result externref) + (call $f) + (local.get ${MaxParams-1})))`)); diff --git a/js/src/jit-test/tests/wasm/regress/bug1761850.js b/js/src/jit-test/tests/wasm/regress/bug1761850.js new file mode 100644 index 0000000000..609991bde4 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1761850.js @@ -0,0 +1,79 @@ +// Testing runtime execution of select + comparison operations. +// Normally they are folded into shorter/faster sequence than select alone. + +const floatOps = { + lt(a, b) { return a < b ? 0 : 1; }, + le(a, b) { return a <= b ? 0 : 1; }, + gt(a, b) { return a > b ? 0 : 1; }, + ge(a, b) { return a >= b ? 0 : 1; }, + eq(a, b) { return a === b ? 0 : 1; }, + ne(a, b) { return a !== b ? 0 : 1; }, +} + +for (let ty of ['f32', 'f64']) { + for (let op of ['lt', 'le', 'gt', 'ge', 'eq', 'ne']) { + const module = new WebAssembly.Module(wasmTextToBinary(`(module + (memory (export "memory") 1 1) + (func (export "test") (result i32) + i32.const 128 + i32.load8_u + i32.const 129 + i32.load8_u + i32.const 0 + ${ty}.load + i32.const ${ty == 'f32' ? 4 : 8} + ${ty}.load + ${ty}.${op} + select + ) + (data (i32.const 128) "\\00\\01"))`)); + const instance = new WebAssembly.Instance(module); + const arr = new (ty == 'f32' ? Float32Array : Float64Array)(instance.exports.memory.buffer); + for (let [a, b] of cross( + [0, 1, -1e100, Infinity, -Infinity, 1e100, -1e-10, 1/-Infinity, NaN] + )) { + arr[0] = a; arr[1] = b; + assertEq(instance.exports.test(), floatOps[op](arr[0], arr[1])) + } + } +} + +const intOps = { + lt(a, b) { return a < b ? 0 : 1; }, + le(a, b) { return a <= b ? 0 : 1; }, + gt(a, b) { return a > b ? 0 : 1; }, + ge(a, b) { return a >= b ? 0 : 1; }, + eq(a, b) { return a === b ? 0 : 1; }, + ne(a, b) { return a !== b ? 0 : 1; }, +} + +for (let [ty, signed] of [['i32', true], ['i32', false], ['i64', true], ['i64', false]]) { + for (let op of ['lt', 'le', 'gt', 'ge', 'eq', 'ne']) { + const module = new WebAssembly.Module(wasmTextToBinary(`(module + (memory (export "memory") 1 1) + (func (export "test") (result i32) + i32.const 128 + i32.load8_u + i32.const 129 + i32.load8_u + i32.const 0 + ${ty}.load + i32.const ${ty == 'i32' ? 4 : 8} + ${ty}.load + ${ty}.${op}${op[0] == 'l' || op[0] == 'g' ? (signed ? '_s' : '_u') : ''} + select + ) + (data (i32.const 128) "\\00\\01"))`)); + const instance = new WebAssembly.Instance(module); + const arr = new (ty == 'i32' ? (signed ? Int32Array : Uint32Array) : + (signed ? BigInt64Array : BigUint64Array)) + (instance.exports.memory.buffer); + const c = ty == 'i32' ? (a => a|0) : BigInt; + for (let [a, b] of cross( + [c(0), ~c(0), c(1), ~c(1), c(1) << c(8), ~c(1) << c(12)] + )) { + arr[0] = a; arr[1] = b; + assertEq(instance.exports.test(), intOps[op](arr[0], arr[1])) + } + } +} diff --git a/js/src/jit-test/tests/wasm/regress/bug1762899.js b/js/src/jit-test/tests/wasm/regress/bug1762899.js new file mode 100644 index 0000000000..3938c93a02 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1762899.js @@ -0,0 +1,34 @@ +var ins = wasmEvalText(` +(module + (func (export "copysign_f64") (param f64 f64) (result f64) + f64.const 0x1.921fb54442d18p+0 (;=1.5708;) + local.get 0 + f64.copysign + ) + (func (export "copysign_f32") (param f32 f32) (result f32) + f32.const 0x1.921fb54442d18p+0 (;=1.5708;) + local.get 0 + f32.copysign + ) + (func (export "copysign_f64_2") (param f64 f64) (result f64) + local.get 1 + f64.const 0x1.921fb54442d18p+0 (;=1.5708;) + f64.copysign + ) + (func (export "copysign_f32_2") (param f32 f32) (result f32) + local.get 1 + f32.const -0x1.921fb54442d18p+0 (;=1.5708;) + f32.copysign + ) + +) +`); + +assertEq(ins.exports.copysign_f64(1, 0), 1.5707963267948966); +assertEq(ins.exports.copysign_f64(-1, 0), -1.5707963267948966); +assertEq(ins.exports.copysign_f32(1, 0), 1.5707963705062866); +assertEq(ins.exports.copysign_f32(-1, 0), -1.5707963705062866); +assertEq(ins.exports.copysign_f64_2(0, 1), 1); +assertEq(ins.exports.copysign_f64_2(0, -1), 1); +assertEq(ins.exports.copysign_f32_2(0, 1), -1); +assertEq(ins.exports.copysign_f32_2(0, -1), -1); diff --git a/js/src/jit-test/tests/wasm/regress/bug1770335.js b/js/src/jit-test/tests/wasm/regress/bug1770335.js new file mode 100644 index 0000000000..569d7bd35e --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1770335.js @@ -0,0 +1,33 @@ +// |jit-test| skip-if: !wasmSimdEnabled() + +// Check if GVN indentifies two non-indentical shuffles. During value numbering +// the control field/data might look the same. Shuffle or permute kind, and +// operands order have to be taking into account during value numbering. +// If GVN fails to recognize the following shuffles as different, the v128.xor +// produces zero output. +var ins = wasmEvalText(`(module + (memory (export "memory") 1 1) + (func $test (param v128) (result v128) + local.get 0 + v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000 + i8x16.shuffle 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000 + local.get 0 + i8x16.shuffle 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + v128.xor + ) + (func (export "run") + i32.const 16 + i32.const 0 + v128.load + call $test + v128.store + ) +)`); + +const mem64 = new BigInt64Array(ins.exports.memory.buffer, 0, 4); +mem64[0] = 0x123456789n; +mem64[1] = -0xFDCBA000n; +ins.exports.run(); +assertEq(mem64[2], -0xFDCBA000n); +assertEq(mem64[3], 0x123456789n); diff --git a/js/src/jit-test/tests/wasm/regress/bug1836708.js b/js/src/jit-test/tests/wasm/regress/bug1836708.js new file mode 100644 index 0000000000..87b7483bd6 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/bug1836708.js @@ -0,0 +1,19 @@ +// Testing i64.mul in wasm with a 2 ** n +- 1 value as operand, which may +// be optimized in code generation. +var mulImmOperands = []; + +for (let i = 0n; i < 64n; i++) { + mulImmOperands.push(2n ** i - 1n); + mulImmOperands.push(2n ** i + 1n); +} + +for (const immVal of mulImmOperands) { + const ins = wasmEvalText(`(module + (func (export "mul_i64") (param i64) (result i64) + local.get 0 + i64.const ${immVal} + i64.mul + ))`); + + assertEq(ins.exports.mul_i64(42n), BigInt.asIntN(64, 42n * immVal)); +} diff --git a/js/src/jit-test/tests/wasm/regress/builtin-import-sigs.js b/js/src/jit-test/tests/wasm/regress/builtin-import-sigs.js new file mode 100644 index 0000000000..50aa2a41d1 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/builtin-import-sigs.js @@ -0,0 +1,15 @@ +var code = wasmTextToBinary(`(module + (import "" "builtin" (func $one)) + (import "" "builtin" (func $two (param i32))) + (import "" "builtin" (func $three (result i32))) + (import "" "builtin" (func $four (param f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32) (result f32))) + (func (export "run") + (call $one) + (call $two (i32.const 0)) + (drop (call $three)) + (drop (call $four (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0) (f32.const 0))) + ) +)`); +var m = new WebAssembly.Module(code); +var i = new WebAssembly.Instance(m, {'':{builtin:Math.sin}}); +i.exports.run(); diff --git a/js/src/jit-test/tests/wasm/regress/caller-property.js b/js/src/jit-test/tests/wasm/regress/caller-property.js new file mode 100644 index 0000000000..8b9a95a989 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/caller-property.js @@ -0,0 +1,7 @@ +const { g } = wasmEvalText(`(module (func $f) (export "g" (func $f)))`).exports; + +function testCaller() { + return g.caller; +} + +assertErrorMessage(testCaller, TypeError, /caller/); diff --git a/js/src/jit-test/tests/wasm/regress/current-memory-tls.js b/js/src/jit-test/tests/wasm/regress/current-memory-tls.js new file mode 100644 index 0000000000..6bd46b2b5f --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/current-memory-tls.js @@ -0,0 +1,95 @@ +// Bug 1341650: +// - when compiled with Ion, pass the TLS register to memory.size; +// - when compiled with Baseline, don't clobber the last stack slot when +// calling into memory.size/memory.grow; + +// This toy module starts with an empty memory, then tries to set values at different +// indexes, automatically growing memory when that would trigger an out of +// bounds access, for the exact right amount of pages. Note it's not made for +// efficiency, but optimizing it doesn't trigger the bugs mentioned above. + +let i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(` +(module + (memory $mem (export "mem") 0 65535) + + (func (export "cur_mem") (result i32) (memory.size)) + + (func $maybeGrow (param $i i32) (local $smem i32) + ;; get memory.size in number of bytes, not pages. + memory.size + i64.extend_u/i32 + i64.const 65536 + i64.mul + + ;; get the last byte index accessed by an int32 access. + local.get $i + i32.const 3 + i32.add + tee_local $i + i64.extend_u/i32 + + ;; if the memory is too small, grow it. + i64.le_u + if + ;; get the floor of the accessed *page* index. + local.get $i + i64.extend_u/i32 + i64.const 65536 + i64.div_u + + ;; subtract to that the size of the current memory in pages; + ;; that's the amount of pages we want to grow, minus one. + memory.size + i64.extend_u/i32 + + i64.sub + + ;; add 1 to that amount. + i64.const 1 + i64.add + + ;; get back to i32 and grow memory. + i32.wrap/i64 + memory.grow + drop + end + ) + + (func (export "set") (param $i i32) (param $v i32) + local.get $i + call $maybeGrow + local.get $i + local.get $v + i32.store + ) + + (func (export "get") (param $i i32) (result i32) + local.get $i + i32.load + ) +) +`))).exports; + +assertEq(i.cur_mem(), 0); + +i.set(0, 1); +assertEq(i.get(0), 1); + +assertEq(i.cur_mem(), 1); + +i.set(1234, 1); +assertEq(i.get(1234), 1); + +assertEq(i.cur_mem(), 1); + +i.set(65532, 1); +assertEq(i.get(65532), 1); + +assertErrorMessage(() => i.get(65533), WebAssembly.RuntimeError, /index out of bounds/); + +assertEq(i.cur_mem(), 1); + +i.set(65533, 1); +assertEq(i.get(65533), 1); + +assertEq(i.cur_mem(), 2); diff --git a/js/src/jit-test/tests/wasm/regress/debug-clone-segment.js b/js/src/jit-test/tests/wasm/regress/debug-clone-segment.js new file mode 100644 index 0000000000..f91f62df32 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/debug-clone-segment.js @@ -0,0 +1,36 @@ +// |jit-test| skip-if: !wasmDebuggingEnabled() +// +var mod = new WebAssembly.Module(wasmTextToBinary(` + (module + (func (export "func_0") (result i32) + call 0 + ) + ) +`)); + +var g = newGlobal({newCompartment: true}); +g.parent = this; +g.eval("(" + function() { + var dbg = Debugger(parent); + dbg.onEnterFrame = function(frame) {} +} + ")()"); + +processModule(mod); +processModule(mod); +processModule(mod); +processModule(mod); + +mod = new WebAssembly.Module(wasmTextToBinary(` +(module (export "func_0" (func $func1)) (func $func1)) +`)); + +processModule(mod); +processModule(mod); +processModule(mod); +processModule(mod); + +function processModule(module) { + try { + new WebAssembly.Instance(module).exports.func_0(); + } catch(ex) {} +} diff --git a/js/src/jit-test/tests/wasm/regress/debug-exception-in-fast-import.js b/js/src/jit-test/tests/wasm/regress/debug-exception-in-fast-import.js new file mode 100644 index 0000000000..bba37b38b0 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/debug-exception-in-fast-import.js @@ -0,0 +1,21 @@ +// |jit-test| skip-if: !wasmDebuggingEnabled() +g = newGlobal({newCompartment: true}); +g.parent = this; +g.eval("(" + function() { + Debugger(parent).onExceptionUnwind = function(frame) {} +} + ")()") + +o = {}; + +let { exports } = wasmEvalText(` + (module (import "" "inc" (func $imp)) (func) (func $start (call $imp)) (start $start) (export "" (func $start))) +`, { + "": { + inc: function() { o = o.p; } + } +}); + +// after instanciation, the start function has been executed and o is undefined. +// This second call will throw in the imported function: + +assertErrorMessage(exports[""], TypeError, /undefined/); diff --git a/js/src/jit-test/tests/wasm/regress/debug-osr.js b/js/src/jit-test/tests/wasm/regress/debug-osr.js new file mode 100644 index 0000000000..e8d3285ed4 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/debug-osr.js @@ -0,0 +1,16 @@ +// |jit-test| skip-if: !wasmDebuggingEnabled() +g = newGlobal({newCompartment: true}); +g.parent = this; +g.eval("(" + function() { + Debugger(parent).onExceptionUnwind = function(frame) { + frame.older + } +} + ")()"); + +let o = {}; + +let func = wasmEvalText(` + (module (import "" "inc" (func $imp)) (func) (func $start (call $imp)) (start $start) (export "" (func $start))) +`, { "": { inc: function() { o = o.set; } } }).exports[""]; + +assertErrorMessage(func, TypeError, /(is|of) undefined/); diff --git a/js/src/jit-test/tests/wasm/regress/directives.txt b/js/src/jit-test/tests/wasm/regress/directives.txt new file mode 100644 index 0000000000..8bb976be49 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/directives.txt @@ -0,0 +1 @@ +|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--test-wasm-await-tier2; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); include:wasm.js diff --git a/js/src/jit-test/tests/wasm/regress/enable-profiling-in-import.js b/js/src/jit-test/tests/wasm/regress/enable-profiling-in-import.js new file mode 100644 index 0000000000..dd17b2089f --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/enable-profiling-in-import.js @@ -0,0 +1,9 @@ +var module = new WebAssembly.Module(wasmTextToBinary(` + (module + (import "global" "func" (func)) + (func (export "f") + call 0 + ) + ) +`)); +new WebAssembly.Instance(module, { global: { func: enableGeckoProfiling } }).exports.f(); diff --git a/js/src/jit-test/tests/wasm/regress/frame-offset-stack-arg.js b/js/src/jit-test/tests/wasm/regress/frame-offset-stack-arg.js new file mode 100644 index 0000000000..6ab2834d79 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/frame-offset-stack-arg.js @@ -0,0 +1,38 @@ +// We have some register args and the rest are on the stack in the wasm->js +// call. This tests a case where the wrong frame offset was used (on ARM64, +// which is weird in this regard) to read the stack arg in an optimized callout +// stub. + +var loop_counter = 0; + +function f(a,b,c,d,e,f,g,h,i,j) { + assertEq(a, loop_counter); + assertEq(b, a+1); + assertEq(c, b+1); + assertEq(d, c+1); + assertEq(e, d+1); + assertEq(f, e+1); + assertEq(g, f+1); + assertEq(h, g+1); + assertEq(i, h+1); + assertEq(j, i+1); +} + +var bin = wasmTextToBinary( + `(module + (import "m" "f" (func $f (param i32) (param i32) (param i32) (param i32) (param i32) + (param i32) (param i32) (param i32) (param i32) (param i32))) + (func (export "test") (param $a i32) (param $b i32) (param $c i32) (param $d i32) (param $e i32) + (param $f i32) (param $g i32) (param $h i32) (param $i i32) (param $j i32) + (call $f (local.get $a) (local.get $b) (local.get $c) (local.get $d) (local.get $e) + (local.get $f) (local.get $g) (local.get $h) (local.get $i) (local.get $j))))`); + +var mod = new WebAssembly.Module(bin); +var ins = new WebAssembly.Instance(mod, {m:{f}}); + +// Enough iterations for the jit to kick in and the stub to become optimized. + +for ( let i=0; i < 100; i++ ) { + loop_counter = i; + ins.exports.test(i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9); +} diff --git a/js/src/jit-test/tests/wasm/regress/fuzzsafe-bug1645610.js b/js/src/jit-test/tests/wasm/regress/fuzzsafe-bug1645610.js new file mode 100644 index 0000000000..6bd88e95bc --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/fuzzsafe-bug1645610.js @@ -0,0 +1,15 @@ +// |jit-test| --fuzzing-safe; skip-if: this.getErrorNotes +// +// The meaning of the line above is that the test case is to be run only with +// --fuzzing-safe and only if that setting (or similar settings) is effectful. + +WebAssembly.Module.exports(new WebAssembly.Module(wasmTextToBinary(` +(module + (func (;0;)) + (func (;1;)) + (func (;2;)) + (func (;3;) (result i32) + i32.const 42) + (export "memo" (func 3)) + (export "main" (func 3))) +`))); diff --git a/js/src/jit-test/tests/wasm/regress/gvn-unremovable-phi.js b/js/src/jit-test/tests/wasm/regress/gvn-unremovable-phi.js new file mode 100644 index 0000000000..832215f4e6 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/gvn-unremovable-phi.js @@ -0,0 +1,20 @@ +wasmEvalText(`(module + (type $type0 (func (param i32))) + (func $f (param $p i32) + (local $x i32) (local $y i32) + loop $top + local.get $x + local.get $p + local.get $x + br_if $top + i32.const 1 + tee_local $p + local.get $y + local.set $x + i32.add + call $f + br_if $top + return + end + ) +)`); diff --git a/js/src/jit-test/tests/wasm/regress/imul64-ion-negative-power-of-two.js b/js/src/jit-test/tests/wasm/regress/imul64-ion-negative-power-of-two.js new file mode 100644 index 0000000000..0fe59546d7 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/imul64-ion-negative-power-of-two.js @@ -0,0 +1,11 @@ +new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(` +(module + (func (param i64)) + (func (export "f") + i64.const 2 + i64.const -9223372036854775808 + i64.mul + call 0 + ) +) +`))).exports.f(); diff --git a/js/src/jit-test/tests/wasm/regress/ion-callerfp-tag.js b/js/src/jit-test/tests/wasm/regress/ion-callerfp-tag.js new file mode 100644 index 0000000000..936fba24fd --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/ion-callerfp-tag.js @@ -0,0 +1,28 @@ +var lfModule = new WebAssembly.Module(wasmTextToBinary(` + (module + (import "global" "func" (func (result i32))) + (func (export "func_0") (result i32) + call 0 ;; calls the import, which is func #0 + ) + ) +`)); + +enableGeckoProfiling(); +WasmHelpers.startProfiling(); +setJitCompilerOption("ion.warmup.trigger", 20); + +Object.prototype[3] = 3; + +var imports = { + global: { + func: function() {} + } +} + +for (let i = 0; i < 100; ++i) { + for (dmod in imports) + for (dname in imports[dmod]) + if (imports[dmod][dname] == undefined) {} + instance = new WebAssembly.Instance(lfModule, imports); + print(i, instance.exports.func_0()); +} diff --git a/js/src/jit-test/tests/wasm/regress/ion-error-gc-fakeexitframe.js b/js/src/jit-test/tests/wasm/regress/ion-error-gc-fakeexitframe.js new file mode 100644 index 0000000000..5b184611d7 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/ion-error-gc-fakeexitframe.js @@ -0,0 +1,81 @@ +var lfLogBuffer = ` +//corefuzz-dcd-endofdata +for (var i = 0; gczeal(4,10); g(buffer)) + assertEq(assignParameterGetElement(42), 17); +//corefuzz-dcd-endofdata +//corefuzz-dcd-endofdata +//corefuzz-dcd-endofdata +g = newGlobal({newCompartment: true}); +g.parent = this +g.eval("Debugger(parent).onExceptionUnwind=(function(){})") +`; +lfLogBuffer = lfLogBuffer.split('\n'); + +gcPreserveCode(); + +var letext =`(module + (type $type0 (func (param i32 i64))) + (type $type1 (func (param i32) (result i64))) + (type $type2 (func (result i32))) + (memory 1) + (export "store" (func $func0)) + (export "load" (func $func1)) + (export "assert_0" (func $func2)) + (func $func0 (param $var0 i32) (param $var1 i64) + local.get $var0 + local.get $var1 + i64.store16 offset=16 + ) + (func $func1 (param $var0 i32) (result i64) + local.get $var0 + i64.load16_s offset=16 + ) + (func $func2 (result i32) + i32.const 65519 + i64.const -32768 + call $func0 + i32.const 1 + ) + (data (i32.const 0) + "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\t\\n\\0b\\0c\\0d\\0e\\0f" + ) + (data (i32.const 16) + "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff" + ) +)`; + +var binary = wasmTextToBinary(letext); +var module = new WebAssembly.Module(binary); + +var lfCodeBuffer = ""; +while (true) { + var line = lfLogBuffer.shift(); + if (line == null) { + break; + } else if (line == "//corefuzz-dcd-endofdata") { + processCode(lfCodeBuffer); + } else { + lfCodeBuffer += line + "\n"; + } +} + +if (lfCodeBuffer) processCode(lfCodeBuffer); + +function processCode(code) { + evaluate(code); + while (true) { + imports = {} + try { + instance = new WebAssembly.Instance(module, imports); + break; + } catch (exc) {} + } + for (let descriptor of WebAssembly.Module.exports(module)) { + switch (descriptor.kind) { + case "function": + try { + print(instance.exports[descriptor.name]()) + } catch (exc1) {} + } + } +} diff --git a/js/src/jit-test/tests/wasm/regress/ion-inlinedcall-resumepoint.js b/js/src/jit-test/tests/wasm/regress/ion-inlinedcall-resumepoint.js new file mode 100644 index 0000000000..9b9c8209bc --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/ion-inlinedcall-resumepoint.js @@ -0,0 +1,50 @@ +var invalidatedFunction = function() { return false; } + +var counter = 0; + +function maybeInvalidate(iplusk) { + if (iplusk === 0) { + // This should happen only once; it will invalidate the call frame of + // the ion() function, which should rewind to just after the wasm call + // (if it got its own resume point). + // Before the patch, the wasm call doesn't get its resume point, so + // it's repeated and the importedFunc() is called once too many. + counter++; + invalidatedFunction = function () { return true; }; + } +} + +function importedFunc(k) { + for (let i = 100; i --> 0 ;) { + maybeInvalidate(i + k); + } +} + +let { exports } = new WebAssembly.Instance( + new WebAssembly.Module( + wasmTextToBinary(` + (module + (func $imp (import "env" "importedFunc") (param i32)) + (func (export "exp") (param i32) + local.get 0 + call $imp + ) + ) + `) + ), { + env: { + importedFunc + } + } +); + +function ion(k) { + exports.exp(k); + invalidatedFunction(); +} + +for (let k = 100; k --> 0 ;) { + ion(k); +} + +assertEq(counter, 1); diff --git a/js/src/jit-test/tests/wasm/regress/ion-lazy-stubs-jit.js b/js/src/jit-test/tests/wasm/regress/ion-lazy-stubs-jit.js new file mode 100644 index 0000000000..f7592b14fb --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/ion-lazy-stubs-jit.js @@ -0,0 +1,13 @@ +(function coerceinplace() { + var { table } = wasmEvalText(`(module + (func $add (param i32) (param i32) (result i32) + local.get 0 + ) + (table (export "table") 10 funcref) + (elem (i32.const 0) $add) + )`).exports; + + for (var i = 0; i < 100; i++) { + table.get(0)((true).get++, i*2+1); + } +})(); diff --git a/js/src/jit-test/tests/wasm/regress/ion-many-results.js b/js/src/jit-test/tests/wasm/regress/ion-many-results.js new file mode 100644 index 0000000000..bc4df59e20 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/ion-many-results.js @@ -0,0 +1,17 @@ +// This provokes a crash in ion if its tempalloc reservation logic is not +// up to snuff, bug 1675844. + +for ( let i=100; i < 300; i++ ) { + let xs = new Array(i).fill(1); + + // Should not crash the compiler but should fail validation + assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(` +(module + (func $f (result ${xs.map(_ => 'i32 ').join(' ')}) + ${xs.map((_) => '(i32.const 1)').join(' ')}) + (func $g + (call $f)))`)), + WebAssembly.CompileError, + /(unused values not explicitly dropped)|(values remaining on stack)/); + +} diff --git a/js/src/jit-test/tests/wasm/regress/jit-updatepcquad.js b/js/src/jit-test/tests/wasm/regress/jit-updatepcquad.js new file mode 100644 index 0000000000..69f9371b84 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/jit-updatepcquad.js @@ -0,0 +1,31 @@ +var evalInFrame = (function (global) { + var dbgGlobal = newGlobal({newCompartment: true}); + var dbg = new dbgGlobal.Debugger(); + return function evalInFrame(code) { + dbg.addDebuggee(global); + var frame = dbg.getNewestFrame().older; + frame = frame.older || frame; + let completion = frame.eval(code); + return completion.return; + }; +})(this); + +const { exports } = wasmEvalText(` + (module + (import "global" "func" (func (param i32) (result i32))) + (func (export "func_0") (param i32)(result i32) + local.get 0 + call 0 + ) + ) +`, { + global: { + func: function jscode(i) { + return evalInFrame(`a = ${i}`); + } + } +}); + +for (i = 0; i < 20; ++i) { + assertEq(exports.func_0(i), i); +} diff --git a/js/src/jit-test/tests/wasm/regress/lazy-table-nan.js b/js/src/jit-test/tests/wasm/regress/lazy-table-nan.js new file mode 100644 index 0000000000..aa7bda7485 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/lazy-table-nan.js @@ -0,0 +1,10 @@ +let i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(` +(module + (func $f (result f32) + f32.const nan:0x42 + ) + (table (export "table") 10 funcref) + (elem (i32.const 0) $f) +) +`))).exports; +i.table.get(0)(); diff --git a/js/src/jit-test/tests/wasm/regress/load-lane-oob.js b/js/src/jit-test/tests/wasm/regress/load-lane-oob.js new file mode 100644 index 0000000000..02fea77daf --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/load-lane-oob.js @@ -0,0 +1,14 @@ +// |jit-test| skip-if: !wasmSimdEnabled() + +// Bug 1735128 - useless load should not be eliminated by Ion + +var ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary( +`(module + (memory 0) + (func (export "f") (param i32) + (v128.load64_lane 1 (local.get 0) (v128.const i32x4 0 0 0 0)) + drop))`))); +assertErrorMessage(() => ins.exports.f(100), + WebAssembly.RuntimeError, + /out of bounds/); + diff --git a/js/src/jit-test/tests/wasm/regress/long-select.js b/js/src/jit-test/tests/wasm/regress/long-select.js new file mode 100644 index 0000000000..dfda4e6799 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/long-select.js @@ -0,0 +1,38 @@ +// Bug 1337060 causes too much register pressure on x86 by requiring four int64 +// values in registers at the same time. + +wasmFullPassI64(` +(module + (func $run (result i64) + i64.const 0x2800000033 + i64.const 0x9900000044 + i64.const 0x1000000012 + i64.const 0x1000000013 + i64.lt_s + select))`, "0x2800000033"); + +wasmFullPassI64(` +(module + (func $run (result i64) + i64.const 0x2800000033 + i64.const 0x9900000044 + i64.const 0x1000000013 + i64.const 0x1000000012 + i64.lt_s + select))`, "0x9900000044"); + +wasmFullPassI64(` +(module + (func $run (param f32) (result i64) + i64.const 0x13100000001 + i64.const 0x23370000002 + i64.const 0x34480000003 + i32.const 1 + select + i32.const 1 + select + i64.const 0x45590000004 + i32.const 1 + select + ) +)`, "0x13100000001", {}, 'f32.const 0'); diff --git a/js/src/jit-test/tests/wasm/regress/misc-control-flow.js b/js/src/jit-test/tests/wasm/regress/misc-control-flow.js new file mode 100644 index 0000000000..6feafcee1b --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/misc-control-flow.js @@ -0,0 +1,227 @@ +wasmFailValidateText(`(module + (func (param i32) (result i32) + (loop (if (i32.const 0) (br 0)) (local.get 0))) + (export "" (func 0)) +)`, /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/); + +wasmFailValidateText(`(module + (func (param i32) + (loop (if (i32.const 0) (br 0)) (local.get 0))) + (export "" (func 0)) +)`, /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/); + +wasmFailValidateText(`(module + (func (param i32) (result i32) + (loop (if (i32.const 0) (br 0)) (drop (local.get 0)))) + (export "" (func 0)) +)`, emptyStackError); + +assertEq(wasmEvalText(`(module + (func (param i32) (result i32) + (loop (if (i32.const 0) (br 0))) (local.get 0)) + (export "" (func 0)) +)`).exports[""](42), 42); + +wasmEvalText(`(module (func $func$0 + (block (if (i32.const 1) (loop (br_table 0 (br 0))))) + ) +)`); + +wasmEvalText(`(module (func + (block $out (loop $in (br_table $out $out $in (i32.const 0)))) + ) +)`); + +wasmEvalText(`(module (func (result i32) + (select + (block (result i32) + (drop (block (result i32) + (br_table + 1 + 0 + (i32.const 1) + (i32.const 0) + ) + )) + (i32.const 2) + ) + (i32.const 3) + (i32.const 4) + ) +)) +`); + +wasmEvalText(`(module + (func (param i32) (param i32) (result i32) (i32.const 0)) + (func (result i32) + (call 0 (i32.const 1) (call 0 (i32.const 2) (i32.const 3))) + (call 0 (unreachable) (i32.const 4)) + ) +)`); + +wasmEvalText(` +(module + + (func + (param i32) (param i32) (param i32) (param i32) + (result i32) + (i32.const 0) + ) + + (func (result i32) + (call 0 + (i32.const 42) + (i32.const 53) + (call 0 (i32.const 100) (i32.const 13) (i32.const 37) (i32.const 128)) + (return (i32.const 42)) + ) + ) + + (export "" (func 1)) +) +`).exports[""](); + +wasmEvalText(` +(module + (import "check" "one" (func (param i32))) + (import "check" "two" (func (param i32) (param i32))) + (func (param i32) (call 0 (local.get 0))) + (func (param i32) (param i32) (call 1 (local.get 0) (local.get 1))) + (func + (call 1 + (i32.const 43) + (block $b (result i32) + (if (i32.const 1) + (call 0 + (block (result i32) + (call 0 (i32.const 42)) + (br $b (i32.const 10))))) + (i32.const 44)))) + (export "foo" (func 4))) +`, { + check: { + one(x) { + assertEq(x, 42); + }, + two(x, y) { + assertEq(x, 43); + assertEq(y, 10); + } + } +}).exports.foo(); + +assertEq(wasmEvalText(`(module (func + return + (select + (loop (result i32) (i32.const 1)) + (loop (result i32) (i32.const 2)) + (i32.const 3) + ) + drop +) (export "" (func 0)))`).exports[""](), undefined); + +wasmEvalText(`(module (func (result i32) + (return (i32.const 0)) + (select + (loop (result i32) (i32.const 1)) + (loop (result i32) (i32.const 2)) + (i32.const 3) + ) +))`); + +wasmEvalText(`(module (func + (block $return + (block $beforeReturn + (block $out + (loop $in + (block $otherTable + (br_table + $return + $return + $otherTable + $beforeReturn + (i32.const 0) + ) + ) + (block $backTop + (br_table + $backTop + $backTop + $beforeReturn + (i32.const 0) + ) + ) + (br $in) + ) + ) + ) + ) +))`); + +wasmFailValidateText( +`(module + (func $func$0 + (select + (if (result f32) + (i32.const 0) + (f32.const 0) + (i32.const 0) + ) + (if (result f32) + (i32.const 0) + (f32.const 0) + (i32.const 0) + ) + (i32.const 0) + ) + ) +)`, mismatchError("i32", "f32")); + +wasmEvalText(` +(module + (func (result i32) + (i32.add + (block $outer (result i32) + (drop (block $middle (result i32) + (block $inner (result i32) + (br_table $middle $outer $inner (i32.const 42) (i32.const 1)) + ) + (nop) + )) + (i32.const 0) + ) + (i32.const 13) + ) + ) +) +`); + +wasmFailValidateText(` +(module + (func (result i32) + (loop + (i32.const 0) + (br_table 1 0 (i32.const 15)) + ) + ) +)`, /(br_table targets must all have the same arity)|(br_table target labels have different types)/); + +wasmFailValidateText(` +(module + (func (result i32) + (loop (result i32) + (i32.const 0) + (br_table 1 0 (i32.const 15)) + ) + ) +)`, /(br_table targets must all have the same arity)|(br_table target labels have different types)/); + +wasmValidateText(` +(module + (func + (loop + (i32.const 0) + (br_table 1 0 (i32.const 15)) + ) + ) +)`); diff --git a/js/src/jit-test/tests/wasm/regress/movable-traps.js b/js/src/jit-test/tests/wasm/regress/movable-traps.js new file mode 100644 index 0000000000..ac5577032b --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/movable-traps.js @@ -0,0 +1,38 @@ +let bodies = [ + ` + i32.const 1 + i32.const 0 + i32.div_s + `, + ` + i32.const 1 + i32.const 0 + i32.rem_s + `, + ` + f64.const 1.7976931348623157e+308 + i64.trunc_s/f64 + `, + ` + f32.const 3.40282347e+38 + i32.trunc_s/f32 + ` +]; + +for (let body of bodies) { + wasmFullPass(` + (module + (func $f (param $x i32) (result i32) + loop $top (result i32) + local.get $x + if + local.get $x + br 2 + end + ${body} + br $top + end + ) + (export "run" (func $f)) + )`, 42, {}, 42); +} diff --git a/js/src/jit-test/tests/wasm/regress/no-directives/debugger-no-script.js b/js/src/jit-test/tests/wasm/regress/no-directives/debugger-no-script.js new file mode 100644 index 0000000000..1072e9268e --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/no-directives/debugger-no-script.js @@ -0,0 +1,19 @@ +// |jit-test| skip-if: !wasmDebuggingEnabled(); exitstatus:3 + +function userError() {}; + +let g = newGlobal({newCompartment: true}); +let dbg = new Debugger(g); + +g.eval(` + var wasm = wasmTextToBinary('(module (func (export "test") (nop)))'); + var m = new WebAssembly.Instance(new WebAssembly.Module(wasm)); +`); + +dbg.onEnterFrame = function(frame) { + if (frame.type == "wasmcall") { + throw new userError() + } +} + +result = g.eval("m.exports.test()"); diff --git a/js/src/jit-test/tests/wasm/regress/nop-fill-jit-exit.js b/js/src/jit-test/tests/wasm/regress/nop-fill-jit-exit.js new file mode 100644 index 0000000000..0aadbc22a5 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/nop-fill-jit-exit.js @@ -0,0 +1,28 @@ +// |jit-test| --arm-asm-nop-fill=1 +// +try { + enableSingleStepProfiling(); + disableSingleStepProfiling(); +} catch (e) { + // Early quit on platforms not supporting single step profiling. + quit(); +} + +load(libdir + "asm.js"); + +var ffi = function(enable) { + enableGeckoProfiling(); + enableSingleStepProfiling(); +} +var f = asmLink(asmCompile('global', 'ffis', + USE_ASM + ` + var ffi=ffis.ffi; + function f(i) { + i=i|0; + ffi(i|0); + } return f + `), null, { + ffi +}); +f(0); +f(+1); diff --git a/js/src/jit-test/tests/wasm/regress/null-call.js b/js/src/jit-test/tests/wasm/regress/null-call.js new file mode 100644 index 0000000000..b7ed4b46e3 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/null-call.js @@ -0,0 +1,14 @@ +// Bug 1747540 - two trap descriptors at the same address led to some confusion. + +var ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(` + (table 1 funcref) + (memory 1) + (func $test (export "test") (result i32) + (call_indirect (i32.const 0)) + (i32.load (i32.const 0)) +) +`))) +assertErrorMessage(() => ins.exports.test(), + WebAssembly.RuntimeError, + /indirect call to null/); + diff --git a/js/src/jit-test/tests/wasm/regress/null-metadata-filename.js b/js/src/jit-test/tests/wasm/regress/null-metadata-filename.js new file mode 100644 index 0000000000..638fef6c40 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/null-metadata-filename.js @@ -0,0 +1,20 @@ +// |jit-test| skip-if: !isAsmJSCompilationAvailable() + +enableGeckoProfiling(); +var code = evaluate("(function() { 'use asm'; function g() { return 43 } return g })", { + fileName: null +}); + +assertEq(code()(), 43); + +evaluate(` +let f = evalReturningScope.bind(null, ''); + +(function(glob, stdlib) { + "use asm"; + var f = stdlib.f; + function _() { f(); } + return _; +})(this, { f })(); +`, { fileName: null }); + diff --git a/js/src/jit-test/tests/wasm/regress/onlyjsiter-while-wasm.js b/js/src/jit-test/tests/wasm/regress/onlyjsiter-while-wasm.js new file mode 100644 index 0000000000..f67b6d27b8 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/onlyjsiter-while-wasm.js @@ -0,0 +1,13 @@ +// |jit-test| skip-if: typeof evalInCooperativeThread === 'undefined' + +try { + evalInCooperativeThread(` + var { f } = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(\` + (module + (func $f (export "f") call $f) + ) + \`))).exports; + gczeal(9); + f(); + `); +} catch(e) {} diff --git a/js/src/jit-test/tests/wasm/regress/oom-eval.js b/js/src/jit-test/tests/wasm/regress/oom-eval.js new file mode 100644 index 0000000000..1ce7c26df1 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/oom-eval.js @@ -0,0 +1,7 @@ +// |jit-test| slow; allow-oom; skip-if: !wasmIsSupported() || !('oomTest' in this) + +function foo() { + var g = newGlobal({sameZoneAs: this}); + g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module (func) (export "" (func 0)))')));`); +} +oomTest(foo); diff --git a/js/src/jit-test/tests/wasm/regress/oom-init.js b/js/src/jit-test/tests/wasm/regress/oom-init.js new file mode 100644 index 0000000000..f08b088107 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/oom-init.js @@ -0,0 +1,21 @@ +// |jit-test| slow; allow-oom; skip-if: !wasmIsSupported() || !('oomTest' in this) + +Object.getOwnPropertyNames(this); +s = newGlobal(); +evalcx("\ + /x/;\ + oomTest(function() {\ + this[\"\"];\ + void 0;\ + Object.freeze(this);\ + l(undefined)();\ + O;\ + t;\ + 0;\ + ({e});\ + i;\ + 0;\ + ({ z: p ? 0 : 0});\ + s;\ + });\ +", s); diff --git a/js/src/jit-test/tests/wasm/regress/oom-masm-baseline.js b/js/src/jit-test/tests/wasm/regress/oom-masm-baseline.js new file mode 100644 index 0000000000..cda1b54584 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/oom-masm-baseline.js @@ -0,0 +1,31 @@ +// |jit-test| slow; skip-if: !('oomTest' in this) + +// Test baseline compiler only. +if (typeof wasmCompileMode === 'undefined' || wasmCompileMode() != 'baseline') + quit(); + +try { + var bin = wasmTextToBinary( + `(module (func (result i32) (param f64) (param f32) + i64.const 0 + local.get 0 + drop + i32.wrap/i64 + f64.const 0 + f64.const 0 + i32.const 0 + select + f32.const 0 + f32.const 0 + f32.const 0 + i32.const 0 + select + i32.const 0 + i32.const 0 + i32.const 0 + select + select + drop + drop))`); + oomTest(() => new WebAssembly.Module(bin)); +} catch(e) { } diff --git a/js/src/jit-test/tests/wasm/regress/oom-wasm-streaming.js b/js/src/jit-test/tests/wasm/regress/oom-wasm-streaming.js new file mode 100644 index 0000000000..5d7e719912 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/oom-wasm-streaming.js @@ -0,0 +1,14 @@ +// |jit-test| skip-if: !('oomAfterAllocations' in this) + +ignoreUnhandledRejections(); + +try { + WebAssembly.compileStreaming(); +} catch (err) { + assertEq(String(err).indexOf("not supported with --no-threads") !== -1, true); + quit(); +} +oomAfterAllocations(1, 2); +var x = wasmTextToBinary('(module (func (export "run") (result i32) i32.const 42))'); +WebAssembly.compileStreaming(x); +drainJobQueue(); diff --git a/js/src/jit-test/tests/wasm/regress/oom-wasmtexttobinary-block.js b/js/src/jit-test/tests/wasm/regress/oom-wasmtexttobinary-block.js new file mode 100644 index 0000000000..6f3b666873 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/oom-wasmtexttobinary-block.js @@ -0,0 +1,7 @@ +// |jit-test| skip-if: !('oomTest' in this) + +try { + oomTest((function () { + wasmTextToBinary("(module(func(loop $label1 $label0)))"); + })); +} catch(e) { } diff --git a/js/src/jit-test/tests/wasm/regress/pass-stack-int64.js b/js/src/jit-test/tests/wasm/regress/pass-stack-int64.js new file mode 100644 index 0000000000..94497f35de --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/pass-stack-int64.js @@ -0,0 +1,15 @@ +var params = ''; +var locals = ''; +for (let i = 0; i < 20; i++) { + params += '(param i64) '; + locals += `(local.get ${i}) `; +} + +wasmEvalText(` +(module + (func + ${params} + (call 0 ${locals}) + ) +) +`); diff --git a/js/src/jit-test/tests/wasm/regress/proxy-get-trap-table.js b/js/src/jit-test/tests/wasm/regress/proxy-get-trap-table.js new file mode 100644 index 0000000000..56158e7b15 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/proxy-get-trap-table.js @@ -0,0 +1,14 @@ +// The 'get' handler should be invoked directly when reading fields of the +// descriptor. + +assertErrorMessage(() => { + var desc = { + element: "anyfunc", + initial: 1 + }; + var proxy = new Proxy({}, { + get: true + }); + Object.setPrototypeOf(desc, proxy); + let table = new WebAssembly.Table(desc); +}, TypeError, /proxy handler's get trap/); diff --git a/js/src/jit-test/tests/wasm/regress/regalloc-i64-load-store-global.js b/js/src/jit-test/tests/wasm/regress/regalloc-i64-load-store-global.js new file mode 100644 index 0000000000..da971d1aa2 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/regalloc-i64-load-store-global.js @@ -0,0 +1,20 @@ +wasmFullPassI64(` + (module + (global (mut i64) (i64.const 9970292656026947164)) + (func (export "global.get_0") (result i64) global.get 0) + + (func $run (param i32) (result i64) + i64.const 8692897571457488645 + i64.const 1028567229461950342 + i64.mul + global.get 0 + f32.const 3.141592653 + f32.floor + f32.const -13.37 + f32.floor + f32.copysign + drop + i64.div_u + ) + ) +`, 1, {}, 'i32.const 0'); diff --git a/js/src/jit-test/tests/wasm/regress/regalloc-muli64.js b/js/src/jit-test/tests/wasm/regress/regalloc-muli64.js new file mode 100644 index 0000000000..b9ad31dca9 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/regalloc-muli64.js @@ -0,0 +1,14 @@ +// Bug 1298808. +assertEq(wasmEvalText(`(module + (func + (result i32) + (i32.wrap/i64 + (i64.mul + ;; Conditions: rhs == lhs, rhs is not a constant. + (i64.add (i64.const 1) (i64.const 10)) + (i64.add (i64.const 1) (i64.const 10)) + ) + ) + ) + (export "" (func 0)) +)`).exports[""](), 121); diff --git a/js/src/jit-test/tests/wasm/regress/reserve-enough.js b/js/src/jit-test/tests/wasm/regress/reserve-enough.js new file mode 100644 index 0000000000..c591fa3153 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/reserve-enough.js @@ -0,0 +1,13 @@ +// Bug 1281131 - be sure to reserve enough stack space + +wasmEvalText( +`(module + (func $func0 + ${loopy(100)} + (nop)))`); + +function loopy(n) { + if (n == 0) + return "(nop)"; + return `(block $out${n} (loop $in${n} ${loopy(n-1)}))`; +} diff --git a/js/src/jit-test/tests/wasm/regress/reserve-joinreg.js b/js/src/jit-test/tests/wasm/regress/reserve-joinreg.js new file mode 100644 index 0000000000..7121914651 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/reserve-joinreg.js @@ -0,0 +1,22 @@ +// Bug 1280933, excerpted from binary test case provided there. + +wasmEvalText( +`(module + (func $func0 (param $arg0 i32) (result i32) (local $var0 i64) + (local.set $var0 (i64.extend_u/i32 (local.get $arg0))) + (i32.wrap/i64 + (i64.add + (block (result i64) + (block $label1 + (loop $label0 + (drop + (block $label2 (result i64) + (br_table $label2 (i64.const 0) (local.get $arg0)) + ) + ) + (local.set $var0 (i64.mul (i64.const 2) (local.get $var0))) + ) + ) + (tee_local $var0 (i64.add (i64.const 4) (local.get $var0)))) + (i64.const 1)))) + (export "" (func 0)))`); diff --git a/js/src/jit-test/tests/wasm/regress/savedframe-lookup-in-wasm.js b/js/src/jit-test/tests/wasm/regress/savedframe-lookup-in-wasm.js new file mode 100644 index 0000000000..6527c78efa --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/savedframe-lookup-in-wasm.js @@ -0,0 +1,17 @@ +g = newGlobal({newCompartment: true}); +g.parent = this; +g.eval(`(function() { + Debugger(parent).onExceptionUnwind = function(frame) { return frame.eval(""); } +})()`); + +var module = new WebAssembly.Module(wasmTextToBinary(` + (module (import $imp "" "inc") (func) (func $start (call $imp)) (start $start) (export "" (func $start))) +`)); + +var imports = { + "": { + inc: function() { undefined_function(); } + } +}; + +new WebAssembly.Instance(module, imports).exports[''](); diff --git a/js/src/jit-test/tests/wasm/regress/select-any.js b/js/src/jit-test/tests/wasm/regress/select-any.js new file mode 100644 index 0000000000..9e85d33897 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/select-any.js @@ -0,0 +1,41 @@ +// Bug 1280921 + +var m1 = wasmEvalText( +`(module + (type $type0 (func)) + (func $func0 + (select + (unreachable) + (return (nop)) + (loop (result i32) (i32.const 1)) + ) + drop + ) + (export "" (func 0)))`).exports[""]; + +try { + m1(); +} catch (e) { + if (!(e instanceof Error && e.message.match(/unreachable executed/))) + throw e; +} + +var m2 = wasmEvalText( +`(module + (type $type0 (func)) + (func $func0 + (select + (i32.const 26) + (unreachable) + (i32.const 3) + ) + drop + ) + (export "" (func 0)))`).exports[""]; + +try { + m2(); +} catch (e) { + if (!(e instanceof Error && e.message.match(/unreachable executed/))) + throw e; +} diff --git a/js/src/jit-test/tests/wasm/regress/shift-counts.js b/js/src/jit-test/tests/wasm/regress/shift-counts.js new file mode 100644 index 0000000000..aadc9e5d76 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/shift-counts.js @@ -0,0 +1,8 @@ +// Bug 1280926, extracted from binary + +wasmEvalText( +`(module + (type $type0 (func (result i32))) + (export "" (func $func0)) + (func $func0 (result i32) + (i32.shr_s (i32.const -40) (i32.const 34))))`); diff --git a/js/src/jit-test/tests/wasm/regress/signed-unsigned-div-mod.js b/js/src/jit-test/tests/wasm/regress/signed-unsigned-div-mod.js new file mode 100644 index 0000000000..370676d2c4 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/signed-unsigned-div-mod.js @@ -0,0 +1,75 @@ +// The result should be -1 because it is (i32.rem_s -1 10000) and the spec +// stipulates "result has the sign of the dividend". This test uncovers a bug +// in SpiderMonkey wherein the shape of the lhs (it looks like an unsigned +// value) causes an unsigned modulo to be emitted. + +assertEq(wasmEvalText( + `(module + (func (result i32) + (i32.const -1) + (i32.const 0) + i32.shr_u + (i32.const 10000) + i32.rem_s) + (export "f" (func 0)))`).exports.f(), -1); + +// Ditto for int64 + +wasmAssert( + `(module + (func $run (result i64) + (i64.const -1) + (i64.const 0) + i64.shr_u + (i64.const 10000) + i64.rem_s) + )`, [{type:'i64', expected:'0xffffffffffffffff', func:'$run'}]); + +// Despite the signed shift this is 0x80000000 % 10000 (rem_u) +// and the result is positive. + +assertEq(wasmEvalText( + `(module + (func (result i32) + (i32.const -1) + (i32.const 0) + i32.shl + (i32.const 10000) + i32.rem_u) + (export "f" (func 0)))`).exports.f(), 7295); + +// 0x80000000 is really -0x80000000 so the result of signed division shall be +// negative. + +assertEq(wasmEvalText( + `(module + (func (result i32) + (i32.const 0x80000000) + (i32.const 0) + i32.shr_u + (i32.const 10000) + i32.div_s) + (export "f" (func 0)))`).exports.f(), -214748); + +assertEq(wasmEvalText( + `(module + (func (result i32) + (i32.const 0x80000000) + (i32.const 0) + i32.shr_u + (i32.const -10000) + i32.div_s) + (export "f" (func 0)))`).exports.f(), 214748); + +// And the result of unsigned division shall be positive. + +assertEq(wasmEvalText( + `(module + (func (result i32) + (i32.const 0x80000000) + (i32.const 0) + i32.shr_u + (i32.const 10000) + i32.div_u) + (export "f" (func 0)))`).exports.f(), 214748); + diff --git a/js/src/jit-test/tests/wasm/regress/startfunc-in-table.js b/js/src/jit-test/tests/wasm/regress/startfunc-in-table.js new file mode 100644 index 0000000000..12ebfe64ab --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/startfunc-in-table.js @@ -0,0 +1,6 @@ +wasmEvalText(`(module + (func) + (start 0) + (table $0 1 anyfunc) + (elem 0 (i32.const 0) func 0) +)`); diff --git a/js/src/jit-test/tests/wasm/regress/table-of-anyref.js b/js/src/jit-test/tests/wasm/regress/table-of-anyref.js new file mode 100644 index 0000000000..a19ec95be5 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/table-of-anyref.js @@ -0,0 +1,9 @@ +// Faulty prebarrier for tables. +gczeal(4, 8); +let ins = wasmEvalText( + `(module + (table (export "t") 10 externref) + (func (export "set_externref") (param i32) (param externref) + (table.set (get_local 0) (get_local 1))))`); +ins.exports.set_externref(3, {}); +ins.exports.set_externref(3, null); diff --git a/js/src/jit-test/tests/wasm/regress/teavm-bugs.js b/js/src/jit-test/tests/wasm/regress/teavm-bugs.js new file mode 100644 index 0000000000..c526dbd7bb --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/teavm-bugs.js @@ -0,0 +1,53 @@ +// Register allocation issue with LCompareI64AndBranch. +let params = ''; +let locals = ''; +let tests = '(i64.const 0)'; + +for (let i = 15; i --> 0;) { + params += `\n(param i64)`; + locals += `\n(local i64)`; + tests = ` + (if (result i64) + (i64.eq + (local.get ${i + 8}) + (local.get ${i}) + ) + (local.get ${i + 8}) + ${tests} + )`; +} + +let code = `(module + (func $i64 + ${params} (result i64) ${locals} + ${tests} + ) +)` + +wasmEvalText(code); + +// Bounds check elimination. +assertEq(wasmEvalText(`(module + (memory 1) + (func (param $p i32) (result i32) (local $l i32) + (local.set $l (i32.const 0)) + (if + (local.get $p) + (local.set $l + (i32.add + (local.get $l) + (i32.load8_s (local.get $p)) + ) + ) + ) + (local.set $l + (i32.add + (local.get $l) + (i32.load8_s (local.get $p)) + ) + ) + (local.get $l) + ) + (data (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f") + (export "test" (func 0)) +)`).exports["test"](3), 6); diff --git a/js/src/jit-test/tests/wasm/regress/too-large-frame.js b/js/src/jit-test/tests/wasm/regress/too-large-frame.js new file mode 100644 index 0000000000..b91f8f6381 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/too-large-frame.js @@ -0,0 +1,27 @@ +// Bug 1280934, equivalent test case. + +try { + +wasmEvalText( +`(module + (func $func0 (result i32) ${locals()} + (i32.const 0)) + (export "" (func 0)))`); + +} catch (e) { + // The wasm baseline compiler throws OOM on too-large frames, so + // handle that. + if (!String(e).match(/out of memory/)) + throw e; +} + +// The wasm baseline compiler cuts off frames at 256KB at the moment; +// the test case for bug 1280934 constructed a frame around 512KB so +// duplicate that here. + +function locals() { + var s = ""; + for ( var i=0 ; i < 50000 ; i++ ) + s += "(local f64)\n"; + return s; +} diff --git a/js/src/jit-test/tests/wasm/regress/unaligned-store64.js b/js/src/jit-test/tests/wasm/regress/unaligned-store64.js new file mode 100644 index 0000000000..b878093451 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/unaligned-store64.js @@ -0,0 +1,35 @@ +var ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary( + `(module + (memory (export "mem") 1 1) + (func (export "store_32_1") (param $ptr i32) + (i64.store32 align=1 (local.get $ptr) (i64.const 0xabba1337))) + (func (export "store_32_2") (param $ptr i32) + (i64.store32 align=2 (local.get $ptr) (i64.const 0xabba1337))) + (func (export "store_16") (param $ptr i32) + (i64.store16 align=1 (local.get $ptr) (i64.const 0x1337))))`))).exports; + +var mem = new Uint8Array(ins.mem.buffer); + +ins.store_16(1); +assertEq(mem[1], 0x37); +assertEq(mem[2], 0x13); + +ins.store_32_1(11); +assertEq(mem[11], 0x37); +assertEq(mem[12], 0x13); +assertEq(mem[13], 0xba); +assertEq(mem[14], 0xab); + +ins.store_32_2(18); +assertEq(mem[18], 0x37); +assertEq(mem[19], 0x13); +assertEq(mem[20], 0xba); +assertEq(mem[21], 0xab); + +// This must also work on all platforms even though we're lying about the +// alignment. +ins.store_32_2(29); +assertEq(mem[29], 0x37); +assertEq(mem[30], 0x13); +assertEq(mem[31], 0xba); +assertEq(mem[32], 0xab); diff --git a/js/src/jit-test/tests/wasm/regress/upper-maximum-memory.js b/js/src/jit-test/tests/wasm/regress/upper-maximum-memory.js new file mode 100644 index 0000000000..d2d099f4fe --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/upper-maximum-memory.js @@ -0,0 +1,4 @@ +new WebAssembly.Memory({ + initial: 1, + maximum: 65536 +}); |