Bug 1587050 - Adjust table.copy part 1. r=jseward
authorLars T Hansen <lhansen@mozilla.com>
Fri, 11 Oct 2019 06:09:26 +0000
changeset 497263 83d82f306f89326f6a9c81702780cca0bde80f90
parent 497262 4b1c5a268d2e5bcc6bc981ce4c20c32fe8c5e17b
child 497264 f8479467f708eae59cd544baecf59705e8971077
push id97762
push userarchaeopteryx@coole-files.de
push dateFri, 11 Oct 2019 07:29:48 +0000
treeherderautoland@f8479467f708 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjseward
bugs1587050
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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
js/src/jit-test/tests/wasm/gc/tables-generalized.js
--- a/js/src/jit-test/tests/wasm/gc/tables-fill.js
+++ b/js/src/jit-test/tests/wasm/gc/tables-fill.js
@@ -1,34 +1,34 @@
 // |jit-test| skip-if: !wasmReftypesEnabled()
 
 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))
            )
          )`);
 
   // An initial test to ascertain that tables 0 and 1 are independent
 
   // Fill in table 0, then check it.
   assertEq(ins.exports.fill0(2, obj[6], 5), undefined)
@@ -128,22 +128,23 @@ function testTableFill(type, obj) {
 
   // Following all the above tests on table 1, check table 0 hasn't changed.
   check_table0();
 }
 
 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
 
 assertErrorMessage(() => wasmEvalText(
     `(module
       (table $t 10 anyref)
       (func $expected-3-args-got-0
@@ -197,8 +198,17 @@ assertErrorMessage(() => wasmEvalText(
 assertErrorMessage(() => wasmEvalText(
     `(module
       (table $t 10 anyref)
       (func $retty-wrong (result i32)
         (table.fill $t (i32.const 0) (ref.null) (i32.const 0))
      ))`),
      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/);
--- a/js/src/jit-test/tests/wasm/gc/tables-generalized.js
+++ b/js/src/jit-test/tests/wasm/gc/tables-generalized.js
@@ -72,38 +72,65 @@ new WebAssembly.Instance(new WebAssembly
     assertEq(t.get(4), objs[4]);
     assertEq(t.get(5), objs[0]);
     assertEq(t.get(6), objs[1]);
     assertEq(t.get(7), objs[2]);
     assertEq(t.get(8), objs[8]);
     assertEq(t.get(9), objs[9]);
 }
 
+// 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
+       (table 10 funcref)
+       (table 10 anyref)
+       (func (export "f")
+         (table.copy 0 (i32.const 0) 1 (i32.const 0) (i32.const 5))))`)),
+                   WebAssembly.CompileError,
+                   /expression has type anyref but expected funcref/);
+
 // 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 0 (i32.const 0) func $f1))`)),
                    WebAssembly.CompileError,
                    /only tables of 'funcref' may have element segments/);
 
-// Wasm: table.init on 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))))`)),
-                   WebAssembly.CompileError,
-                   /only tables of 'funcref' may have element segments/);
-
 // Wasm: table types must match at link time
 
 assertErrorMessage(
     () => new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
        (import "m" "t" (table 10 anyref)))`)),
                                    {m:{t: new WebAssembly.Table({element:"funcref", initial:10})}}),
     WebAssembly.LinkError,
@@ -192,34 +219,45 @@ assertErrorMessage(() => new WebAssembly
          (drop (table.get (local.get 0)))))`)),
                    WebAssembly.CompileError,
                    /table index out of range for table.get/);
 
 // table.set in bounds with i32 x anyref - works, no value generated
 // 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
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (table 10 anyref)
        (func (export "f") (param f64)
          (table.set (local.get 0) (ref.null))))`)),
@@ -247,23 +285,23 @@ assertErrorMessage(() => new WebAssembly
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (func (export "f") (param anyref)
        (table.set (i32.const 0) (local.get 0))))`)),
                    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
   // table.grow with zero delta - always works even at maximum
   // table.grow with delta - works and returns correct old value
   // table.grow with delta at upper limit - fails
   // table.grow with negative delta - fails
   assertEq(ins.exports.grow(0), 10);
@@ -282,18 +320,29 @@ function testTableGrow(type, x) {
   assertErrorMessage(() => ins.exports.t.grow(-1), TypeError, /bad [Tt]able grow delta/);
 
   // The wasm API does not throw if it can't grow, but returns -1
   assertEq(ins.exports.grow(1), -1);
   assertEq(ins.exports.t.length, 20);
   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
 
 {
     let ins = wasmEvalText(
         `(module
           (table 10 anyref)
           (func (export "grow") (param i32) (result i32)
@@ -405,8 +454,24 @@ let VALUES = [null,
 // If growing by zero elements there are no spurious writes
 
 {
     let t = new WebAssembly.Table({element:"anyref", initial:1});
     t.set(0, 1337);
     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/);