diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /js/src/jit-test/tests/wasm/table-gc.js | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/jit-test/tests/wasm/table-gc.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/table-gc.js | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/table-gc.js b/js/src/jit-test/tests/wasm/table-gc.js new file mode 100644 index 000000000..0cce3edf8 --- /dev/null +++ b/js/src/jit-test/tests/wasm/table-gc.js @@ -0,0 +1,221 @@ +// |jit-test| --no-baseline +// Turn off baseline and since it messes up the GC finalization assertions by +// adding spurious edges to the GC graph. + +load(libdir + 'wasm.js'); + +const Module = WebAssembly.Module; +const Instance = WebAssembly.Instance; +const Table = WebAssembly.Table; +const RuntimeError = WebAssembly.RuntimeError; + +var caller = `(type $v2i (func (result i32))) (func $call (param $i i32) (result i32) (call_indirect $v2i (get_local $i))) (export "call" $call)` +var callee = i => `(func $f${i} (type $v2i) (i32.const ${i}))`; + +// A table should not hold exported functions alive and exported functions +// should not hold their originating table alive. Live exported functions should +// hold instances alive and instances hold imported tables alive. Nothing +// should hold the export object alive. +resetFinalizeCount(); +var i = wasmEvalText(`(module (table 2 anyfunc) (export "tbl" table) (elem (i32.const 0) $f0) ${callee(0)} ${caller})`); +var e = i.exports; +var t = e.tbl; +var f = t.get(0); +assertEq(f(), e.call(0)); +assertErrorMessage(() => e.call(1), RuntimeError, /indirect call to null/); +assertErrorMessage(() => e.call(2), RuntimeError, /index out of bounds/); +assertEq(finalizeCount(), 0); +i.edge = makeFinalizeObserver(); +t.edge = makeFinalizeObserver(); +f.edge = makeFinalizeObserver(); +gc(); +assertEq(finalizeCount(), 0); +f = null; +gc(); +assertEq(finalizeCount(), 1); +f = t.get(0); +f.edge = makeFinalizeObserver(); +gc(); +assertEq(finalizeCount(), 1); +i.exports = null; +e = null; +gc(); +assertEq(finalizeCount(), 1); +t = null; +gc(); +assertEq(finalizeCount(), 1); +i = null; +gc(); +assertEq(finalizeCount(), 1); +assertEq(f(), 0); +f = null; +gc(); +assertEq(finalizeCount(), 4); + +// A table should hold the instance of any of its elements alive. +resetFinalizeCount(); +var i = wasmEvalText(`(module (table 1 anyfunc) (export "tbl" table) (elem (i32.const 0) $f0) ${callee(0)} ${caller})`); +var e = i.exports; +var t = e.tbl; +var f = t.get(0); +i.edge = makeFinalizeObserver(); +t.edge = makeFinalizeObserver(); +f.edge = makeFinalizeObserver(); +gc(); +assertEq(finalizeCount(), 0); +i.exports = null; +e = null; +gc(); +assertEq(finalizeCount(), 0); +f = null; +gc(); +assertEq(finalizeCount(), 1); +i = null; +gc(); +assertEq(finalizeCount(), 1); +t = null; +gc(); +assertEq(finalizeCount(), 3); + +// Null elements shouldn't keep anything alive. +resetFinalizeCount(); +var i = wasmEvalText(`(module (table 2 anyfunc) (export "tbl" table) ${caller})`); +var e = i.exports; +var t = e.tbl; +i.edge = makeFinalizeObserver(); +t.edge = makeFinalizeObserver(); +gc(); +assertEq(finalizeCount(), 0); +i.exports = null; +e = null; +gc(); +assertEq(finalizeCount(), 0); +i = null; +gc(); +assertEq(finalizeCount(), 1); +t = null; +gc(); +assertEq(finalizeCount(), 2); + +// Before initialization, a table is not bound to any instance. +resetFinalizeCount(); +var i = wasmEvalText(`(module (func $f0 (result i32) (i32.const 0)) (export "f0" $f0))`); +var t = new Table({initial:4, element:"anyfunc"}); +i.edge = makeFinalizeObserver(); +t.edge = makeFinalizeObserver(); +gc(); +assertEq(finalizeCount(), 0); +i = null; +gc(); +assertEq(finalizeCount(), 1); +t = null; +gc(); +assertEq(finalizeCount(), 2); + +// When a Table is created (uninitialized) and then first assigned, it keeps the +// first element's Instance alive (as above). +resetFinalizeCount(); +var i = wasmEvalText(`(module (func $f (result i32) (i32.const 42)) (export "f" $f))`); +var f = i.exports.f; +var t = new Table({initial:1, element:"anyfunc"}); +i.edge = makeFinalizeObserver(); +f.edge = makeFinalizeObserver(); +t.edge = makeFinalizeObserver(); +t.set(0, f); +assertEq(t.get(0), f); +assertEq(t.get(0)(), 42); +gc(); +assertEq(finalizeCount(), 0); +f = null; +i.exports = null; +gc(); +assertEq(finalizeCount(), 1); +assertEq(t.get(0)(), 42); +t.get(0).edge = makeFinalizeObserver(); +gc(); +assertEq(finalizeCount(), 2); +i = null; +gc(); +assertEq(finalizeCount(), 2); +t.set(0, null); +assertEq(t.get(0), null); +gc(); +assertEq(finalizeCount(), 3); +t = null; +gc(); +assertEq(finalizeCount(), 4); + +// Once all of an instance's elements in a Table have been clobbered, the +// Instance should not be reachable. +resetFinalizeCount(); +var i1 = wasmEvalText(`(module (func $f1 (result i32) (i32.const 13)) (export "f1" $f1))`); +var i2 = wasmEvalText(`(module (func $f2 (result i32) (i32.const 42)) (export "f2" $f2))`); +var f1 = i1.exports.f1; +var f2 = i2.exports.f2; +var t = new Table({initial:2, element:"anyfunc"}); +i1.edge = makeFinalizeObserver(); +i2.edge = makeFinalizeObserver(); +f1.edge = makeFinalizeObserver(); +f2.edge = makeFinalizeObserver(); +t.edge = makeFinalizeObserver(); +t.set(0, f1); +t.set(1, f2); +gc(); +assertEq(finalizeCount(), 0); +f1 = f2 = null; +i1.exports = null; +i2.exports = null; +gc(); +assertEq(finalizeCount(), 2); +i1 = null; +i2 = null; +gc(); +assertEq(finalizeCount(), 2); +t.set(0, t.get(1)); +gc(); +assertEq(finalizeCount(), 3); +t = null; +gc(); +assertEq(finalizeCount(), 5); + +// Ensure that an instance that is only live on the stack cannot be GC even if +// there are no outstanding references. +resetFinalizeCount(); +const N = 10; +var tbl = new Table({initial:N, element:"anyfunc"}); +tbl.edge = makeFinalizeObserver(); +function runTest() { + tbl = null; + gc(); + assertEq(finalizeCount(), 0); + return 100; +} +var i = wasmEvalText( + `(module + (import $imp "a" "b" (result i32)) + (func $f (param i32) (result i32) (call $imp)) + (export "f" $f) + )`, + {a:{b:runTest}} +); +i.edge = makeFinalizeObserver(); +tbl.set(0, i.exports.f); +var m = new Module(wasmTextToBinary(`(module + (import "a" "b" (table ${N} anyfunc)) + (type $i2i (func (param i32) (result i32))) + (func $f (param $i i32) (result i32) + (set_local $i (i32.sub (get_local $i) (i32.const 1))) + (i32.add + (i32.const 1) + (call_indirect $i2i (get_local $i) (get_local $i)))) + (export "f" $f) +)`)); +for (var i = 1; i < N; i++) { + var inst = new Instance(m, {a:{b:tbl}}); + inst.edge = makeFinalizeObserver(); + tbl.set(i, inst.exports.f); +} +inst = null; +assertEq(tbl.get(N - 1)(N - 1), 109); +gc(); +assertEq(finalizeCount(), N + 1); |