From 93aac073a583e41ab2a9ebb9a24872020cd52d37 Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Fri, 11 Oct 2019 06:09:26 +0000 Subject: [PATCH] Bug 1587050 - Adjust table.copy part 1. r=jseward Differential Revision: https://phabricator.services.mozilla.com/D48536 --- js/src/jit-test/tests/wasm/gc/tables-fill.js | 28 +++-- .../tests/wasm/gc/tables-generalized.js | 107 ++++++++++++++---- 2 files changed, 105 insertions(+), 30 deletions(-) diff --git a/js/src/jit-test/tests/wasm/gc/tables-fill.js b/js/src/jit-test/tests/wasm/gc/tables-fill.js index c95631f69d92..3728f49f147a 100644 --- a/js/src/jit-test/tests/wasm/gc/tables-fill.js +++ b/js/src/jit-test/tests/wasm/gc/tables-fill.js @@ -2,28 +2,28 @@ const N = 8; -function testTableFill(type, obj) { +function testTableFill(tbl_type, val_type, obj) { assertEq(obj.length, N); let ins = wasmEvalText( `(module - (table 8 ${type}) ;; table 0 - (table $t 10 ${type}) ;; table 1 + (table 8 ${tbl_type}) ;; table 0 + (table $t 10 ${tbl_type}) ;; table 1 ;; fill/get for table 0, referenced implicitly - (func (export "fill0") (param $i i32) (param $r ${type}) (param $n i32) + (func (export "fill0") (param $i i32) (param $r ${val_type}) (param $n i32) (table.fill (local.get $i) (local.get $r) (local.get $n)) ) - (func (export "get0") (param $i i32) (result ${type}) + (func (export "get0") (param $i i32) (result ${tbl_type}) (table.get (local.get $i)) ) ;; fill/get for table 1, referenced explicitly - (func (export "fill1") (param $i i32) (param $r ${type}) (param $n i32) + (func (export "fill1") (param $i i32) (param $r ${val_type}) (param $n i32) (table.fill $t (local.get $i) (local.get $r) (local.get $n)) ) - (func (export "get1") (param $i i32) (result ${type}) + (func (export "get1") (param $i i32) (result ${tbl_type}) (table.get $t (local.get $i)) ) )`); @@ -133,12 +133,13 @@ function testTableFill(type, obj) { var objs = []; for (var i = 0; i < N; i++) objs[i] = {n:i}; -testTableFill('anyref', objs); +testTableFill('anyref', 'anyref', objs); var funcs = []; for (var i = 0; i < N; i++) funcs[i] = wasmEvalText(`(module (func (export "x") (result i32) (i32.const ${i})))`).exports.x; -testTableFill('funcref', funcs); +testTableFill('funcref', 'funcref', funcs); +testTableFill('anyref', 'funcref', funcs); // funcref <: anyref so implicit upcast on fill // Type errors. Required sig is: (i32, anyref, i32) -> void @@ -202,3 +203,12 @@ assertErrorMessage(() => wasmEvalText( ))`), WebAssembly.CompileError, /popping value from empty stack/); + +assertErrorMessage(() => wasmEvalText( + `(module + (table 8 funcref) + (func (param $v anyref) + (table.fill (i32.const 0) (local.get $v) (i32.const 0))) + )`), + WebAssembly.CompileError, + /expression has type anyref but expected funcref/); diff --git a/js/src/jit-test/tests/wasm/gc/tables-generalized.js b/js/src/jit-test/tests/wasm/gc/tables-generalized.js index d17118922b20..f4932b3eb704 100644 --- a/js/src/jit-test/tests/wasm/gc/tables-generalized.js +++ b/js/src/jit-test/tests/wasm/gc/tables-generalized.js @@ -77,25 +77,52 @@ new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary( assertEq(t.get(9), objs[9]); } -// Wasm: element segments targeting table-of-anyref is forbidden +// Wasm: table.copy from table(funcref) to table(anyref) should work + +{ + let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary( + `(module + (table (export "t") 10 anyref) + (func $f1) + (func $f2) + (func $f3) + (func $f4) + (func $f5) + (table 5 funcref) + (elem (table 1) (i32.const 0) func $f1 $f2 $f3 $f4 $f5) + (func (export "f") + (table.copy 0 (i32.const 5) 1 (i32.const 0) (i32.const 5))))`))); + ins.exports.f(); + let t = ins.exports.t; + let xs = []; + for (let i=0; i < 5; i++) { + xs[i] = t.get(i+5); + assertEq(typeof xs[i], "function"); + } + for (let i=0; i < 5; i++) { + for (j=i+1; j < 5; j++) + assertEq(xs[i] != xs[j], true); + } +} + +// Wasm: table.copy from table(anyref) to table(funcref) should not work assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary( `(module - (func $f1 (result i32) (i32.const 0)) + (table 10 funcref) (table 10 anyref) - (elem 0 (i32.const 0) func $f1))`)), + (func (export "f") + (table.copy 0 (i32.const 0) 1 (i32.const 0) (i32.const 5))))`)), WebAssembly.CompileError, - /only tables of 'funcref' may have element segments/); + /expression has type anyref but expected funcref/); -// Wasm: table.init on table-of-anyref is forbidden +// Wasm: element segments targeting table-of-anyref is forbidden assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary( `(module (func $f1 (result i32) (i32.const 0)) (table 10 anyref) - (elem func $f1) - (func - (table.init 0 (i32.const 0) (i32.const 0) (i32.const 0))))`)), + (elem 0 (i32.const 0) func $f1))`)), WebAssembly.CompileError, /only tables of 'funcref' may have element segments/); @@ -197,24 +224,35 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary( // table.set with null - works // table.set out of bounds - fails -function testTableSet(type, x) { +function testTableSet(lhs_type, rhs_type, x) { let ins = wasmEvalText( `(module - (table (export "t") 10 ${type}) - (func (export "set_anyref") (param i32) (param ${type}) + (table (export "t") 10 ${lhs_type}) + (func (export "set_ref") (param i32) (param ${rhs_type}) (table.set (local.get 0) (local.get 1))) (func (export "set_null") (param i32) (table.set (local.get 0) (ref.null))))`); - ins.exports.set_anyref(3, x); + ins.exports.set_ref(3, x); assertEq(ins.exports.t.get(3), x); ins.exports.set_null(3); assertEq(ins.exports.t.get(3), null); - assertErrorMessage(() => ins.exports.set_anyref(10, x), RangeError, /index out of bounds/); - assertErrorMessage(() => ins.exports.set_anyref(-1, x), RangeError, /index out of bounds/); + assertErrorMessage(() => ins.exports.set_ref(10, x), RangeError, /index out of bounds/); + assertErrorMessage(() => ins.exports.set_ref(-1, x), RangeError, /index out of bounds/); } -testTableSet('anyref', {}); -testTableSet('funcref', wasmFun); +testTableSet('anyref', 'anyref', {}); +testTableSet('funcref', 'funcref', wasmFun); +testTableSet('anyref', 'funcref', wasmFun); + +// Wasm: table.set on table(funcref) with anyref value should fail + +assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary( + `(module + (table (export "t") 10 funcref) + (func (export "set_ref") (param i32) (param anyref) + (table.set (local.get 0) (local.get 1))))`)), + WebAssembly.CompileError, + /type mismatch: expression has type anyref but expected funcref/); // table.set with non-i32 index - fails validation @@ -252,13 +290,13 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary( WebAssembly.CompileError, /table index out of range for table.set/); -function testTableGrow(type, x) { +function testTableGrow(lhs_type, rhs_type, x) { let ins = wasmEvalText( `(module - (table (export "t") 10 20 ${type}) + (table (export "t") 10 20 ${lhs_type}) (func (export "grow") (param i32) (result i32) (table.grow (ref.null) (local.get 0))) - (func (export "grow2") (param i32) (param ${type}) (result i32) + (func (export "grow2") (param i32) (param ${rhs_type}) (result i32) (table.grow (local.get 1) (local.get 0))))`); // we can grow table of references @@ -287,8 +325,19 @@ function testTableGrow(type, x) { assertEq(ins.exports.grow(-1), -1); assertEq(ins.exports.t.length, 20) } -testTableGrow('anyref', 42); -testTableGrow('funcref', wasmFun); +testTableGrow('anyref', 'anyref', 42); +testTableGrow('funcref', 'funcref', wasmFun); +testTableGrow('anyref', 'funcref', wasmFun); + +// Wasm: table.grow on table(funcref) with anyref initializer should fail + +assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary( + `(module + (table (export "t") 10 20 funcref) + (func (export "grow2") (param i32) (param anyref) (result i32) + (table.grow (local.get 1) (local.get 0))))`)), + WebAssembly.CompileError, + /type mismatch: expression has type anyref but expected funcref/); // Special case for private tables without a maximum @@ -410,3 +459,19 @@ let VALUES = [null, t.grow(0, 1789); assertEq(t.get(0), 1337); } + +// Currently 'anyref' segments are not allowed whether passive or active, +// though that will change + +assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary( + `(module + (elem (i32.const 0) anyref (ref.null)))`)), + SyntaxError, + /parsing wasm text/); + + +assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary( + `(module + (elem anyref (ref.null)))`)), + SyntaxError, + /parsing wasm text/);