diff options
Diffstat (limited to 'js/src/jit-test/tests/wasm/resizing.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/resizing.js | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/resizing.js b/js/src/jit-test/tests/wasm/resizing.js new file mode 100644 index 0000000000..544efdc37e --- /dev/null +++ b/js/src/jit-test/tests/wasm/resizing.js @@ -0,0 +1,235 @@ +const Module = WebAssembly.Module; +const Instance = WebAssembly.Instance; +const Table = WebAssembly.Table; +const Memory = WebAssembly.Memory; +const RuntimeError = WebAssembly.RuntimeError; + +// ====== +// MEMORY +// ====== + +// Test for stale heap pointers after resize + +// Grow directly from builtin call: +wasmFullPass(`(module + (memory 1) + (func $test (result i32) + (i32.store (i32.const 0) (i32.const 1)) + (i32.store (i32.const 65532) (i32.const 10)) + (drop (memory.grow (i32.const 99))) + (i32.store (i32.const 6553596) (i32.const 100)) + (i32.add + (i32.load (i32.const 0)) + (i32.add + (i32.load (i32.const 65532)) + (i32.load (i32.const 6553596))))) + (export "run" (func $test)) +)`, 111); + +// Grow during import call: +var exports = wasmEvalText(`(module + (import "" "imp" (func $imp)) + (memory 1) + (func $grow (drop (memory.grow (i32.const 99)))) + (export "grow" (func $grow)) + (func $test (result i32) + (i32.store (i32.const 0) (i32.const 1)) + (i32.store (i32.const 65532) (i32.const 10)) + (call $imp) + (i32.store (i32.const 6553596) (i32.const 100)) + (i32.add + (i32.load (i32.const 0)) + (i32.add + (i32.load (i32.const 65532)) + (i32.load (i32.const 6553596))))) + (export "test" (func $test)) +)`, {"":{imp() { exports.grow() }}}).exports; + +setJitCompilerOption("baseline.warmup.trigger", 2); +setJitCompilerOption("ion.warmup.trigger", 4); +for (var i = 0; i < 10; i++) + assertEq(exports.test(), 111); + +// Grow during call_indirect: +var mem = new Memory({initial:1}); +var tbl = new Table({initial:1, element:"funcref"}); +var exports1 = wasmEvalText(`(module + (import "" "mem" (memory 1)) + (func $grow + (i32.store (i32.const 65532) (i32.const 10)) + (drop (memory.grow (i32.const 99))) + (i32.store (i32.const 6553596) (i32.const 100))) + (export "grow" (func $grow)) +)`, {"":{mem}}).exports; +var exports2 = wasmEvalText(`(module + (import "" "tbl" (table 1 funcref)) + (import "" "mem" (memory 1)) + (type $v2v (func)) + (func $test (result i32) + (i32.store (i32.const 0) (i32.const 1)) + (call_indirect (type $v2v) (i32.const 0)) + (i32.add + (i32.load (i32.const 0)) + (i32.add + (i32.load (i32.const 65532)) + (i32.load (i32.const 6553596))))) + (export "test" (func $test)) +)`, {"":{tbl, mem}}).exports; +tbl.set(0, exports1.grow); +assertEq(exports2.test(), 111); + +// Test for coherent length/contents + +var mem = new Memory({initial:1}); +new Int32Array(mem.buffer)[0] = 42; +var mod = new Module(wasmTextToBinary(`(module + (import "" "mem" (memory 1)) + (func $gm (param i32) (result i32) (memory.grow (local.get 0))) + (export "grow_memory" (func $gm)) + (func $cm (result i32) (memory.size)) + (export "current_memory" (func $cm)) + (func $ld (param i32) (result i32) (i32.load (local.get 0))) + (export "load" (func $ld)) + (func $st (param i32) (param i32) (i32.store (local.get 0) (local.get 1))) + (export "store" (func $st)) +)`)); +var exp1 = new Instance(mod, {"":{mem}}).exports; +var exp2 = new Instance(mod, {"":{mem}}).exports; +assertEq(exp1.current_memory(), 1); +assertEq(exp1.load(0), 42); +assertEq(exp2.current_memory(), 1); +assertEq(exp2.load(0), 42); +mem.grow(1); +assertEq(mem.buffer.byteLength, 2*64*1024); +new Int32Array(mem.buffer)[64*1024/4] = 13; +assertEq(exp1.current_memory(), 2); +assertEq(exp1.load(0), 42); +assertEq(exp1.load(64*1024), 13); +assertEq(exp2.current_memory(), 2); +assertEq(exp2.load(0), 42); +assertEq(exp2.load(64*1024), 13); +exp1.grow_memory(2); +assertEq(exp1.current_memory(), 4); +exp1.store(3*64*1024, 99); +assertEq(exp2.current_memory(), 4); +assertEq(exp2.load(3*64*1024), 99); +assertEq(mem.buffer.byteLength, 4*64*1024); +assertEq(new Int32Array(mem.buffer)[3*64*1024/4], 99); + +// Fail at maximum + +var mem = new Memory({initial:1, maximum:2}); +assertEq(mem.buffer.byteLength, 1 * 64*1024); +assertEq(mem.grow(1), 1); +assertEq(mem.buffer.byteLength, 2 * 64*1024); +assertErrorMessage(() => mem.grow(1), RangeError, /failed to grow memory/); +assertEq(mem.buffer.byteLength, 2 * 64*1024); + +// Do not misinterpret the maximum @ max for the current size. + +(new WebAssembly.Memory({initial: 1, maximum: 65536})).grow(1) + +// ====== +// TABLE +// ====== + +// Test for stale table base pointers after resize + +// Grow during import call: +var exports = wasmEvalText(`(module + (type $v2i (func (result i32))) + (import "" "grow" (func $grow)) + (table (export "tbl") 1 funcref) + (func $test (result i32) + (i32.add + (call_indirect (type $v2i) (i32.const 0)) + (block (result i32) + (call $grow) + (call_indirect (type $v2i) (i32.const 1))))) + (func $one (result i32) (i32.const 1)) + (elem (i32.const 0) $one) + (func $two (result i32) (i32.const 2)) + (export "test" (func $test)) + (export "two" (func $two)) +)`, {"":{grow() { exports.tbl.grow(1); exports.tbl.set(1, exports.two) }}}).exports; + +setJitCompilerOption("baseline.warmup.trigger", 2); +setJitCompilerOption("ion.warmup.trigger", 4); +for (var i = 0; i < 10; i++) + assertEq(exports.test(), 3); +assertEq(exports.tbl.length, 11); + +// Grow during call_indirect: +var exports1 = wasmEvalText(`(module + (import "" "grow" (func $grow)) + (func $exp (call $grow)) + (export "exp" (func $exp)) +)`, {"":{grow() { exports2.tbl.grow(1); exports2.tbl.set(2, exports2.eleven) }}}).exports; +var exports2 = wasmEvalText(`(module + (type $v2v (func)) + (type $v2i (func (result i32))) + (import "" "imp" (func $imp)) + (elem (i32.const 0) $imp) + (table 2 funcref) + (func $test (result i32) + (i32.add + (call_indirect (type $v2i) (i32.const 1)) + (block (result i32) + (call_indirect (type $v2v) (i32.const 0)) + (call_indirect (type $v2i) (i32.const 2))))) + (func $ten (result i32) (i32.const 10)) + (elem (i32.const 1) $ten) + (func $eleven (result i32) (i32.const 11)) + (export "tbl" (table 0)) + (export "test" (func $test)) + (export "eleven" (func $eleven)) +)`, {"":{imp:exports1.exp}}).exports; +assertEq(exports2.test(), 21); + +// Test for coherent length/contents + +var src = wasmEvalText(`(module + (func $one (result i32) (i32.const 1)) + (export "one" (func $one)) + (func $two (result i32) (i32.const 2)) + (export "two" (func $two)) + (func $three (result i32) (i32.const 3)) + (export "three" (func $three)) +)`).exports; +var tbl = new Table({element:"funcref", initial:1}); +tbl.set(0, src.one); + +var mod = new Module(wasmTextToBinary(`(module + (type $v2i (func (result i32))) + (table (import "" "tbl") 1 funcref) + (func $ci (param i32) (result i32) (call_indirect (type $v2i) (local.get 0))) + (export "call_indirect" (func $ci)) +)`)); +var exp1 = new Instance(mod, {"":{tbl}}).exports; +var exp2 = new Instance(mod, {"":{tbl}}).exports; +assertEq(exp1.call_indirect(0), 1); +assertErrorMessage(() => exp1.call_indirect(1), RuntimeError, /index out of bounds/); +assertEq(exp2.call_indirect(0), 1); +assertErrorMessage(() => exp2.call_indirect(1), RuntimeError, /index out of bounds/); +assertEq(tbl.grow(1), 1); +assertEq(tbl.length, 2); +assertEq(exp1.call_indirect(0), 1); +assertErrorMessage(() => exp1.call_indirect(1), Error, /indirect call to null/); +tbl.set(1, src.two); +assertEq(exp1.call_indirect(1), 2); +assertErrorMessage(() => exp1.call_indirect(2), RuntimeError, /index out of bounds/); +assertEq(tbl.grow(2), 2); +assertEq(tbl.length, 4); +assertEq(exp2.call_indirect(0), 1); +assertEq(exp2.call_indirect(1), 2); +assertErrorMessage(() => exp2.call_indirect(2), Error, /indirect call to null/); +assertErrorMessage(() => exp2.call_indirect(3), Error, /indirect call to null/); + +// Fail at maximum + +var tbl = new Table({initial:1, maximum:2, element:"funcref"}); +assertEq(tbl.length, 1); +assertEq(tbl.grow(1), 1); +assertEq(tbl.length, 2); +assertErrorMessage(() => tbl.grow(1), RangeError, /failed to grow table/); +assertEq(tbl.length, 2); |