Merge mozilla-central to mozilla-inbound. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Mon, 26 Nov 2018 11:49:38 +0200
changeset 504410 89e474b0a492ba2748e3bd6d7eb851a33c786a72
parent 504409 5219f57277c4b6b76b61d435227bd666afee59ea (diff)
parent 504383 14ae1910a4f5dd1cdea7fcb4855a3aa86ed3731b (current diff)
child 504411 76207eef2ca82b95660a0c60adb2823da634f0a6
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone65.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
Merge mozilla-central to mozilla-inbound. CLOSED TREE
media/libyuv/README_MOZILLA
--- a/js/src/jit-test/tests/wasm/gc/TypedObject.js
+++ b/js/src/jit-test/tests/wasm/gc/TypedObject.js
@@ -1,15 +1,15 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 // We can read the object fields from JS, and write them if they are mutable.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
 
                              (type $p (struct (field f64) (field (mut i32))))
 
                              (func (export "mkp") (result anyref)
                               (struct.new $p (f64.const 1.5) (i32.const 33))))`).exports;
 
     let p = ins.mkp();
     assertEq(p._0, 1.5);
@@ -19,17 +19,17 @@
     p._1 = 44;
     assertEq(p._1, 44);
 }
 
 // Writing an immutable field from JS throws.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
 
                              (type $p (struct (field f64)))
 
                              (func (export "mkp") (result anyref)
                               (struct.new $p (f64.const 1.5))))`).exports;
 
     let p = ins.mkp();
     assertErrorMessage(() => p._0 = 5.7,
@@ -39,28 +39,28 @@
 
 // MVA v1 restriction: structs that expose ref-typed fields should not be
 // constructible from JS.
 //
 // However, if the fields are anyref the structs can be constructed from JS.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
 
                              (type $q (struct (field (mut f64))))
                              (type $p (struct (field (mut (ref $q)))))
 
                              (type $r (struct (field (mut anyref))))
 
                              (func (export "mkp") (result anyref)
-                              (struct.new $p (ref.null (ref $q))))
+                              (struct.new $p (ref.null)))
 
                              (func (export "mkr") (result anyref)
-                              (struct.new $r (ref.null anyref))))`).exports;
+                              (struct.new $r (ref.null))))`).exports;
 
     assertEq(typeof ins.mkp().constructor, "function");
     assertErrorMessage(() => new (ins.mkp().constructor)({_0:null}),
                        TypeError,
                        /not constructible/);
 
     assertEq(typeof ins.mkr().constructor, "function");
     let r = new (ins.mkr().constructor)({_0:null});
@@ -69,26 +69,26 @@
 
 // MVA v1 restriction: structs that expose ref-typed fields make those fields
 // immutable from JS even if we're trying to store the correct type.
 //
 // However, anyref fields are mutable from JS.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
 
                              (type $q (struct (field (mut f64))))
                              (type $p (struct (field (mut (ref $q))) (field (mut anyref))))
 
                              (func (export "mkq") (result anyref)
                               (struct.new $q (f64.const 1.5)))
 
                              (func (export "mkp") (result anyref)
-                              (struct.new $p (ref.null (ref $q)) (ref.null anyref))))`).exports;
+                              (struct.new $p (ref.null) (ref.null))))`).exports;
     let q = ins.mkq();
     assertEq(typeof q, "object");
     assertEq(q._0, 1.5);
     let p = ins.mkp();
     assertEq(typeof p, "object");
     assertEq(p._0, null);
 
     assertErrorMessage(() => { p._0 = q },
@@ -99,17 +99,17 @@
     assertEq(p._1, q);
 }
 
 // MVA v1 restriction: structs that expose i64 fields make those fields
 // immutable from JS, and the structs are not constructible from JS.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
                              (type $p (struct (field (mut i64))))
                              (func (export "mkp") (result anyref)
                               (struct.new $p (i64.const 0x1234567887654321))))`).exports;
 
     let p = ins.mkp();
     assertEq(typeof p, "object");
     assertEq(p._0_high, 0x12345678)
     assertEq(p._0_low, 0x87654321|0);
@@ -128,17 +128,17 @@
 }
 
 // A consequence of the current mapping of i64 as two i32 fields is that we run
 // a risk of struct.narrow not recognizing the difference.  So check this.
 
 {
     let ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $p (struct (field i64)))
           (type $q (struct (field i32) (field i32)))
           (func $f (param anyref) (result i32)
            (ref.is_null (struct.narrow anyref (ref $q) (get_local 0))))
           (func $g (param anyref) (result i32)
            (ref.is_null (struct.narrow anyref (ref $p) (get_local 0))))
           (func (export "t1") (result i32)
            (call $f (struct.new $p (i64.const 0))))
--- a/js/src/jit-test/tests/wasm/gc/anyref-global-postbarrier.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref-global-postbarrier.js
@@ -5,38 +5,38 @@ const { startProfiling, endProfiling, as
 // Dummy constructor.
 function Baguette(calories) {
     this.calories = calories;
 }
 
 // Ensure the baseline compiler sync's before the postbarrier.
 (function() {
     wasmEvalText(`(module
-        (gc_feature_opt_in 1)
-        (global (mut anyref) (ref.null anyref))
+        (gc_feature_opt_in 2)
+        (global (mut anyref) (ref.null))
         (func (export "f")
             get_global 0
-            ref.null anyref
+            ref.null
             set_global 0
             set_global 0
         )
     )`).exports.f();
 })();
 
 let exportsPlain = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (global i32 (i32.const 42))
-    (global $g (mut anyref) (ref.null anyref))
+    (global $g (mut anyref) (ref.null))
     (func (export "set") (param anyref) get_local 0 set_global $g)
     (func (export "get") (result anyref) get_global $g)
 )`).exports;
 
 let exportsObj = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
-    (global $g (export "g") (mut anyref) (ref.null anyref))
+    (gc_feature_opt_in 2)
+    (global $g (export "g") (mut anyref) (ref.null))
     (func (export "set") (param anyref) get_local 0 set_global $g)
     (func (export "get") (result anyref) get_global $g)
 )`).exports;
 
 // 7 => Generational GC zeal.
 gczeal(7, 1);
 
 for (var i = 0; i < 100; i++) {
--- a/js/src/jit-test/tests/wasm/gc/anyref-global-prebarrier.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref-global-prebarrier.js
@@ -1,15 +1,15 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 const { startProfiling, endProfiling, assertEqPreciseStacks, isSingleStepProfilingEnabled } = WasmHelpers;
 
 let e = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
-    (global $g (mut anyref) (ref.null anyref))
+    (gc_feature_opt_in 2)
+    (global $g (mut anyref) (ref.null))
     (func (export "set") (param anyref) get_local 0 set_global $g)
 )`).exports;
 
 let obj = { field: null };
 
 // GCZeal mode 4 implies that prebarriers are being verified at many
 // locations in the interpreter, during interrupt checks, etc. It can be ultra
 // slow, so disable it with gczeal(0) when it's not strictly needed.
--- a/js/src/jit-test/tests/wasm/gc/anyref-val-tracing.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref-val-tracing.js
@@ -1,13 +1,13 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 gczeal(14, 1);
 let { exports } = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (global $anyref (import "glob" "anyref") anyref)
     (func (export "get") (result anyref) get_global $anyref)
 )`, {
     glob: {
         anyref: { sentinel: "lol" },
     }
 });
 assertEq(exports.get().sentinel, "lol");
--- a/js/src/jit-test/tests/wasm/gc/anyref.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref.js
@@ -6,88 +6,88 @@ function Baguette(calories) {
     this.calories = calories;
 }
 
 // Type checking.
 
 const { validate, CompileError } = WebAssembly;
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (result anyref)
         i32.const 42
     )
 )`), CompileError, mismatchError('i32', 'anyref'));
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (result anyref)
         i32.const 0
-        ref.null anyref
+        ref.null
         i32.const 42
         select
     )
 )`), CompileError, /select operand types/);
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (result i32)
-        ref.null anyref
+        ref.null
         if
             i32.const 42
         end
     )
-)`), CompileError, mismatchError('anyref', 'i32'));
+)`), CompileError, mismatchError('nullref', 'i32'));
 
 
 // Basic compilation tests.
 
 let simpleTests = [
-    "(module (gc_feature_opt_in 1) (func (drop (ref.null anyref))))",
-    "(module (gc_feature_opt_in 1) (func $test (local anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (param anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (result anyref) (ref.null anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (block anyref (unreachable)) unreachable))",
-    "(module (gc_feature_opt_in 1) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
-    `(module (gc_feature_opt_in 1) (import "a" "b" (param anyref)))`,
-    `(module (gc_feature_opt_in 1) (import "a" "b" (result anyref)))`,
-    `(module (gc_feature_opt_in 1) (global anyref (ref.null anyref)))`,
-    `(module (gc_feature_opt_in 1) (global (mut anyref) (ref.null anyref)))`,
+    "(module (gc_feature_opt_in 2) (func (drop (ref.null))))",
+    "(module (gc_feature_opt_in 2) (func $test (local anyref)))",
+    "(module (gc_feature_opt_in 2) (func $test (param anyref)))",
+    "(module (gc_feature_opt_in 2) (func $test (result anyref) (ref.null)))",
+    "(module (gc_feature_opt_in 2) (func $test (block anyref (unreachable)) unreachable))",
+    "(module (gc_feature_opt_in 2) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
+    `(module (gc_feature_opt_in 2) (import "a" "b" (param anyref)))`,
+    `(module (gc_feature_opt_in 2) (import "a" "b" (result anyref)))`,
+    `(module (gc_feature_opt_in 2) (global anyref (ref.null)))`,
+    `(module (gc_feature_opt_in 2) (global (mut anyref) (ref.null)))`,
 ];
 
 for (let src of simpleTests) {
     wasmEvalText(src, {a:{b(){}}});
     assertEq(validate(wasmTextToBinary(src)), true);
 }
 
 // Basic behavioral tests.
 
 let { exports } = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (export "is_null") (result i32)
-        ref.null anyref
+        ref.null
         ref.is_null
     )
 
     (func $sum (result i32) (param i32)
         get_local 0
         i32.const 42
         i32.add
     )
 
     (func (export "is_null_spill") (result i32)
-        ref.null anyref
+        ref.null
         i32.const 58
         call $sum
         drop
         ref.is_null
     )
 
     (func (export "is_null_local") (result i32) (local anyref)
-        ref.null anyref
+        ref.null
         set_local 0
         i32.const 58
         call $sum
         drop
         get_local 0
         ref.is_null
     )
 
@@ -108,25 +108,25 @@ assertEq(exports.ref_eq(null, {}), 0);
 assertEq(exports.ref_eq(this, this), 1);
 assertEq(exports.ref_eq_for_control(null, null), 5);
 assertEq(exports.ref_eq_for_control(null, {}), 3);
 assertEq(exports.ref_eq_for_control(this, this), 5);
 
 // Anyref param and result in wasm functions.
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (export "is_null") (result i32) (param $ref anyref)
         get_local $ref
         ref.is_null
     )
 
     (func (export "ref_or_null") (result anyref) (param $ref anyref) (param $selector i32)
         get_local $ref
-        ref.null anyref
+        ref.null
         get_local $selector
         select
     )
 
     (func $recursive (export "nested") (result anyref) (param $ref anyref) (param $i i32)
         ;; i == 10 => ret $ref
         get_local $i
         i32.const 10
@@ -166,33 +166,33 @@ assertEq(ref.calories, baguette.calories
 
 ref = exports.nested(baguette, 0);
 assertEq(ref, baguette);
 assertEq(ref.calories, baguette.calories);
 
 // Make sure grow-memory isn't blocked by the lack of gc.
 (function() {
     assertEq(wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (memory 0 64)
     (func (export "f") (param anyref) (result i32)
         i32.const 10
         grow_memory
         drop
         current_memory
     )
 )`).exports.f({}), 10);
 })();
 
 // More interesting use cases about control flow joins.
 
 function assertJoin(body) {
     let val = { i: -1 };
     assertEq(wasmEvalText(`(module
-        (gc_feature_opt_in 1)
+        (gc_feature_opt_in 2)
         (func (export "test") (param $ref anyref) (param $i i32) (result anyref)
             ${body}
         )
     )`).exports.test(val), val);
     assertEq(val.i, -1);
 }
 
 assertJoin("(block anyref get_local $ref)");
@@ -249,17 +249,17 @@ assertJoin(`(block $out anyref (block $u
     i32.add
     tee_local $i
     br_table $unreachable $out
     ) unreachable))
 `);
 
 let x = { i: 42 }, y = { f: 53 };
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (export "test") (param $lhs anyref) (param $rhs anyref) (param $i i32) (result anyref)
         get_local $lhs
         get_local $rhs
         get_local $i
         select
     )
 )`).exports;
 
@@ -304,17 +304,17 @@ let imports = {
         },
         ret() {
             return imports.myBaguette;
         }
     }
 };
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (import $ret "funcs" "ret" (result anyref))
     (import $param "funcs" "param" (param anyref))
 
     (func (export "param") (param $x anyref) (param $y anyref)
         get_local $y
         get_local $x
         call $param
         call $param
@@ -333,17 +333,17 @@ imports.myBaguette = null;
 assertEq(exports.ret(), null);
 
 imports.myBaguette = new Baguette(1337);
 assertEq(exports.ret(), imports.myBaguette);
 
 // Check lazy stubs generation.
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (import $mirror "funcs" "mirror" (param anyref) (result anyref))
     (import $augment "funcs" "augment" (param anyref) (result anyref))
 
     (global $count_f (mut i32) (i32.const 0))
     (global $count_g (mut i32) (i32.const 0))
 
     (func $f (param $param anyref) (result anyref)
         i32.const 1
@@ -417,48 +417,48 @@ assertEq(x.i, 24);
 assertEq(x.newProp, "hello");
 assertEq(exports.count_f(), 1);
 assertEq(exports.count_g(), 1);
 
 // Globals.
 
 // Anyref globals in wasm modules.
 
-assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 1) (global (import "glob" "anyref") anyref))`, { glob: { anyref: 42 } }),
+assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 2) (global (import "glob" "anyref") anyref))`, { glob: { anyref: 42 } }),
     WebAssembly.LinkError,
     /import object field 'anyref' is not a Object-or-null/);
 
-assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 1) (global (import "glob" "anyref") anyref))`, { glob: { anyref: new WebAssembly.Global({ value: 'i32' }, 42) } }),
+assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 2) (global (import "glob" "anyref") anyref))`, { glob: { anyref: new WebAssembly.Global({ value: 'i32' }, 42) } }),
     WebAssembly.LinkError,
     /imported global type mismatch/);
 
-assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 1) (global (import "glob" "i32") i32))`, { glob: { i32: {} } }),
+assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 2) (global (import "glob" "i32") i32))`, { glob: { i32: {} } }),
     WebAssembly.LinkError,
     /import object field 'i32' is not a Number/);
 
 imports = {
     constants: {
         imm_null: null,
         imm_bread: new Baguette(321),
         mut_null: new WebAssembly.Global({ value: "anyref", mutable: true }, null),
         mut_bread: new WebAssembly.Global({ value: "anyref", mutable: true }, new Baguette(123))
     }
 };
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (global $g_imp_imm_null  (import "constants" "imm_null") anyref)
     (global $g_imp_imm_bread (import "constants" "imm_bread") anyref)
 
     (global $g_imp_mut_null   (import "constants" "mut_null") (mut anyref))
     (global $g_imp_mut_bread  (import "constants" "mut_bread") (mut anyref))
 
-    (global $g_imm_null     anyref (ref.null anyref))
+    (global $g_imm_null     anyref (ref.null))
     (global $g_imm_getglob  anyref (get_global $g_imp_imm_bread))
-    (global $g_mut         (mut anyref) (ref.null anyref))
+    (global $g_mut         (mut anyref) (ref.null))
 
     (func (export "imm_null")      (result anyref) get_global $g_imm_null)
     (func (export "imm_getglob")   (result anyref) get_global $g_imm_getglob)
 
     (func (export "imp_imm_null")  (result anyref) get_global $g_imp_imm_null)
     (func (export "imp_imm_bread") (result anyref) get_global $g_imp_imm_bread)
     (func (export "imp_mut_null")  (result anyref) get_global $g_imp_mut_null)
     (func (export "imp_mut_bread") (result anyref) get_global $g_imp_mut_bread)
--- a/js/src/jit-test/tests/wasm/gc/binary.js
+++ b/js/src/jit-test/tests/wasm/gc/binary.js
@@ -2,39 +2,21 @@
 
 load(libdir + "wasm-binary.js");
 
 const v2vSig = {args:[], ret:VoidCode};
 const v2vSigSection = sigSection([v2vSig]);
 
 function checkInvalid(body, errorMessage) {
     assertErrorMessage(() => new WebAssembly.Module(
-        moduleWithSections([gcFeatureOptInSection(1), v2vSigSection, declSection([0]), bodySection([body])])),
+        moduleWithSections([gcFeatureOptInSection(2), v2vSigSection, declSection([0]), bodySection([body])])),
                        WebAssembly.CompileError,
                        errorMessage);
 }
 
-const invalidRefNullBody = funcBody({locals:[], body:[
-    RefNull,
-    RefCode,
-    0x42,
-
-    RefNull,
-    RefCode,
-    0x10,
-
-    // Condition code;
-    I32ConstCode,
-    0x10,
-
-    SelectCode,
-    DropCode
-]});
-checkInvalid(invalidRefNullBody, /invalid reference type for ref.null/);
-
 const invalidRefBlockType = funcBody({locals:[], body:[
     BlockCode,
     RefCode,
     0x42,
     EndCode,
 ]});
 checkInvalid(invalidRefBlockType, /invalid inline block type/);
 
--- a/js/src/jit-test/tests/wasm/gc/debugger.js
+++ b/js/src/jit-test/tests/wasm/gc/debugger.js
@@ -1,23 +1,23 @@
 // |jit-test| skip-if: !wasmGcEnabled() || !wasmDebuggingIsSupported()
 
 (function() {
     let g = newGlobal();
     let dbg = new Debugger(g);
-    g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module (gc_feature_opt_in 1) (func (result anyref) (param anyref) get_local 0) (export "" 0))')));`);
+    g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module (gc_feature_opt_in 2) (func (result anyref) (param anyref) get_local 0) (export "" 0))')));`);
 })();
 
 (function() {
     var g = newGlobal();
     g.parent = this;
 
     let src = `
       (module
-        (gc_feature_opt_in 1)
+        (gc_feature_opt_in 2)
         (func (export "func") (result anyref) (param $ref anyref)
             get_local $ref
         )
       )
     `;
 
     g.eval(`
         var obj = { somekey: 'somevalue' };
--- a/js/src/jit-test/tests/wasm/gc/disabled.js
+++ b/js/src/jit-test/tests/wasm/gc/disabled.js
@@ -4,25 +4,25 @@ const { CompileError, validate } = WebAs
 
 const UNRECOGNIZED_OPCODE_OR_BAD_TYPE = /unrecognized opcode|(Structure|reference) types not enabled|invalid inline block type/;
 
 function assertValidateError(text) {
     assertEq(validate(wasmTextToBinary(text)), false);
 }
 
 let simpleTests = [
-    "(module (gc_feature_opt_in 1) (func (drop (ref.null anyref))))",
-    "(module (gc_feature_opt_in 1) (func $test (local anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (param anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (result anyref) (ref.null anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (block anyref (unreachable)) unreachable))",
-    "(module (gc_feature_opt_in 1) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
-    `(module (gc_feature_opt_in 1) (import "a" "b" (param anyref)))`,
-    `(module (gc_feature_opt_in 1) (import "a" "b" (result anyref)))`,
-    `(module (gc_feature_opt_in 1) (type $s (struct)))`,
+    "(module (gc_feature_opt_in 2) (func (drop (ref.null))))",
+    "(module (gc_feature_opt_in 2) (func $test (local anyref)))",
+    "(module (gc_feature_opt_in 2) (func $test (param anyref)))",
+    "(module (gc_feature_opt_in 2) (func $test (result anyref) (ref.null)))",
+    "(module (gc_feature_opt_in 2) (func $test (block anyref (unreachable)) unreachable))",
+    "(module (gc_feature_opt_in 2) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
+    `(module (gc_feature_opt_in 2) (import "a" "b" (param anyref)))`,
+    `(module (gc_feature_opt_in 2) (import "a" "b" (result anyref)))`,
+    `(module (gc_feature_opt_in 2) (type $s (struct)))`,
 ];
 
 // Two distinct failure modes:
 //
 // - if we have no compiled-in support for wasm-gc we'll get a syntax error when
 //   parsing the test programs that use ref types and structures.
 //
 // - if we have compiled-in support for wasm-gc, but wasm-gc is not currently
--- a/js/src/jit-test/tests/wasm/gc/gc-feature-opt-in.js
+++ b/js/src/jit-test/tests/wasm/gc/gc-feature-opt-in.js
@@ -1,122 +1,132 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
+// Version numbers
+
+let CURRENT_VERSION = 2;
+let OLDER_INCOMPATIBLE_VERSION = 1; // v1 incompatible with v2
+let FUTURE_VERSION = 3;
+
 // Encoding.  If the section is present it must be first.
 
 var bad_order =
     new Uint8Array([0x00, 0x61, 0x73, 0x6d,
                     0x01, 0x00, 0x00, 0x00,
 
                     0x01,                   // Type section
                     0x01,                   // Section size
                     0x00,                   // Zero types
 
                     0x2a,                   // GcFeatureOptIn section
                     0x01,                   // Section size
-                    0x01]);                 // Version
+                    CURRENT_VERSION]);      // Version
 
 assertErrorMessage(() => new WebAssembly.Module(bad_order),
                    WebAssembly.CompileError,
                    /expected custom section/);
 
-// Version numbers.  Version 1 and 2 are good, version 3 is bad.
-
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1))`));
+      (gc_feature_opt_in ${CURRENT_VERSION}))`));
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1))`));
+      (gc_feature_opt_in ${CURRENT_VERSION}))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 3))`)),
+      (gc_feature_opt_in ${OLDER_INCOMPATIBLE_VERSION}))`)),
                    WebAssembly.CompileError,
-                   /unsupported version of the gc feature/);
+                   /GC feature version \d+ is no longer supported by this engine/);
+
+assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
+    `(module
+      (gc_feature_opt_in ${FUTURE_VERSION}))`)),
+                   WebAssembly.CompileError,
+                   /GC feature version is unknown/);
 
 // Struct types are only available if we opt in.
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in ${CURRENT_VERSION})
       (type (struct (field i32))))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (type (struct (field i32))))`)),
                    WebAssembly.CompileError,
                    /Structure types not enabled/);
 
 // Parameters of ref type are only available if we opt in.
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in ${CURRENT_VERSION})
       (type (func (param anyref))))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (type (func (param anyref))))`)),
                    WebAssembly.CompileError,
                    /reference types not enabled/);
 
 // Ditto returns
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in ${CURRENT_VERSION})
       (type (func (result anyref))))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (type (func (result anyref))))`)),
                    WebAssembly.CompileError,
                    /reference types not enabled/);
 
 // Ditto locals
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in ${CURRENT_VERSION})
       (func (result i32)
        (local anyref)
        (i32.const 0)))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (func (result i32)
        (local anyref)
        (i32.const 0)))`)),
                    WebAssembly.CompileError,
                    /reference types not enabled/);
 
 // Ditto globals
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
-      (global (mut anyref) (ref.null anyref)))`));
+      (gc_feature_opt_in ${CURRENT_VERSION})
+      (global (mut anyref) (ref.null)))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (global (mut anyref) (ref.null anyref)))`)),
+      (global (mut anyref) (ref.null)))`)),
                    WebAssembly.CompileError,
                    /reference types not enabled/);
 
 // Ref instructions are only available if we opt in.
 //
 // When testing these we need to avoid struct types or parameters, locals,
 // returns, or globals of ref type, or guards on those will preempt the guards
 // on the instructions.
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (func (ref.null anyref)))`)),
+      (func ref.null))`)),
                    WebAssembly.CompileError,
                    /unrecognized opcode/);
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (func ref.is_null))`)),
                    WebAssembly.CompileError,
                    /unrecognized opcode/);
--- a/js/src/jit-test/tests/wasm/gc/ion-and-baseline.js
+++ b/js/src/jit-test/tests/wasm/gc/ion-and-baseline.js
@@ -15,35 +15,35 @@
 // Ion can't talk about references yet *but* we can call indirect from Ion to a
 // baseline module that has exported a function that accepts or returns anyref,
 // without the caller knowing this or having to declare it.  All such calls
 // should fail in an orderly manner with a type mismatch, at the point of the
 // call.
 
 var refmod = new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (import $tbl "" "tbl" (table 4 anyfunc))
       (import $print "" "print" (func (param i32)))
 
       (type $htype (func (param anyref)))
       (type $itype (func (result anyref)))
 
       (elem (i32.const 0) $f $g)
 
       (func $f (param anyref)
        (call $print (i32.const 1)))
 
       (func $g (result anyref)
        (call $print (i32.const 2))
-       (ref.null anyref))
+       (ref.null))
 
       (func (export "test_h")
-       (call_indirect $htype (ref.null anyref) (i32.const 2)))
+       (call_indirect $htype (ref.null) (i32.const 2)))
 
       (func (export "test_i")
        (drop (call_indirect $itype (i32.const 3))))
 
      )`));
 
 var nonrefmod = new WebAssembly.Module(wasmTextToBinary(
     `(module
--- a/js/src/jit-test/tests/wasm/gc/ref-global.js
+++ b/js/src/jit-test/tests/wasm/gc/ref-global.js
@@ -1,68 +1,68 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 // Basic private-to-module functionality.  At the moment all we have is null
 // pointers, not very exciting.
 
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $point (struct
                         (field $x f64)
                         (field $y f64)))
 
-          (global $g1 (mut (ref $point)) (ref.null (ref $point)))
-          (global $g2 (mut (ref $point)) (ref.null (ref $point)))
-          (global $g3 (ref $point) (ref.null (ref $point)))
+          (global $g1 (mut (ref $point)) (ref.null))
+          (global $g2 (mut (ref $point)) (ref.null))
+          (global $g3 (ref $point) (ref.null))
 
           ;; Restriction: cannot expose Refs outside the module, not even
           ;; as a return value.  See ref-restrict.js.
 
           (func (export "get") (result anyref)
            (get_global $g1))
 
           (func (export "copy")
            (set_global $g2 (get_global $g1)))
 
           (func (export "clear")
            (set_global $g1 (get_global $g3))
-           (set_global $g2 (ref.null (ref $point)))))`);
+           (set_global $g2 (ref.null))))`);
 
     let mod = new WebAssembly.Module(bin);
     let ins = new WebAssembly.Instance(mod).exports;
 
     assertEq(ins.get(), null);
     ins.copy();                 // Should not crash
     ins.clear();                // Should not crash
 }
 
 // Global with struct type
 
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $point (struct
                         (field $x f64)
                         (field $y f64)))
 
-          (global $glob (mut (ref $point)) (ref.null (ref $point)))
+          (global $glob (mut (ref $point)) (ref.null))
 
           (func (export "init")
            (set_global $glob (struct.new $point (f64.const 0.5) (f64.const 2.75))))
 
           (func (export "change")
            (set_global $glob (struct.new $point (f64.const 3.5) (f64.const 37.25))))
 
           (func (export "clear")
-           (set_global $glob (ref.null (ref $point))))
+           (set_global $glob (ref.null)))
 
           (func (export "x") (result f64)
            (struct.get $point 0 (get_global $glob)))
 
           (func (export "y") (result f64)
            (struct.get $point 1 (get_global $glob))))`);
 
     let mod = new WebAssembly.Module(bin);
@@ -82,17 +82,17 @@
     assertErrorMessage(() => ins.x(), WebAssembly.RuntimeError, /dereferencing null pointer/);
 }
 
 // Global value of type anyref for initializer from a WebAssembly.Global,
 // just check that it works.
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (import $g "" "g" (global anyref))
           (global $glob anyref (get_global $g))
           (func (export "get") (result anyref)
            (get_global $glob)))`);
 
     let mod = new WebAssembly.Module(bin);
     let obj = {zappa:37};
     let g = new WebAssembly.Global({value: "anyref"}, obj);
@@ -100,30 +100,30 @@
     assertEq(ins.get(), obj);
 }
 
 // We can't import a global of a reference type because we don't have a good
 // notion of structural type compatibility yet.
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $box (struct (field $val i32)))
           (import "m" "g" (global (mut (ref $box)))))`);
 
     assertErrorMessage(() => new WebAssembly.Module(bin), WebAssembly.CompileError,
                        /cannot expose reference type/);
 }
 
 // We can't export a global of a reference type because we can't later import
 // it.  (Once we can export it, the value setter must also perform the necessary
 // subtype check, which implies we have some notion of exporting types, and we
 // don't have that yet.)
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $box (struct (field $val i32)))
-          (global $boxg (export "box") (mut (ref $box)) (ref.null (ref $box))))`);
+          (global $boxg (export "box") (mut (ref $box)) (ref.null)))`);
 
     assertErrorMessage(() => new WebAssembly.Module(bin), WebAssembly.CompileError,
                        /cannot expose reference type/);
 }
--- a/js/src/jit-test/tests/wasm/gc/ref-restrict.js
+++ b/js/src/jit-test/tests/wasm/gc/ref-restrict.js
@@ -46,304 +46,304 @@
 function wasmCompile(text) {
     return new WebAssembly.Module(wasmTextToBinary(text));
 }
 
 // Exported function can't take ref type parameter, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $x i32)))
       (func (export "f") (param (ref $box)) (unreachable)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (func (export "f") (param anyref) (unreachable)))`),
          "object");
 
 // Exported function can't return ref result, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $x i32)))
-      (func (export "f") (result (ref $box)) (ref.null (ref $box))))`),
+      (func (export "f") (result (ref $box)) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
-      (func (export "f") (result anyref) (ref.null anyref)))`),
+      (gc_feature_opt_in 2)
+      (func (export "f") (result anyref) (ref.null)))`),
          "object");
 
 // Imported function can't take ref parameter, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $x i32)))
       (import "m" "f" (param (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "f" (param anyref)))`),
          "object");
 
 // Imported function can't return ref type, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $x i32)))
       (import "m" "f" (param i32) (result (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "f" (param i32) (result anyref)))`),
          "object");
 
 // Imported global can't be of Ref type (irrespective of mutability), though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (import "m" "g" (global (mut (ref $box)))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (import "m" "g" (global (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "g" (global (mut anyref))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "g" (global anyref)))`),
          "object");
 
 // Exported global can't be of Ref type (irrespective of mutability), though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
-      (global $boxg (export "box") (mut (ref $box)) (ref.null (ref $box))))`),
+      (global $boxg (export "box") (mut (ref $box)) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
-      (global $boxg (export "box") (ref $box) (ref.null (ref $box))))`),
+      (global $boxg (export "box") (ref $box) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
-      (global $boxg (export "box") (mut anyref) (ref.null anyref)))`),
+      (gc_feature_opt_in 2)
+      (global $boxg (export "box") (mut anyref) (ref.null)))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
-      (global $boxg (export "box") anyref (ref.null anyref)))`),
+      (gc_feature_opt_in 2)
+      (global $boxg (export "box") anyref (ref.null)))`),
          "object");
 
 // Exported table cannot reference functions that are exposed for Ref, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
       (func $f1 (param (ref $box)) (unreachable)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
-      (func $f1 (result (ref $box)) (ref.null (ref $box))))`),
+      (func $f1 (result (ref $box)) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
       (func $f1 (param anyref) (unreachable)))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
-      (func $f1 (result anyref) (ref.null anyref)))`),
+      (func $f1 (result anyref) (ref.null)))`),
          "object");
 
 // Imported table cannot reference functions that are exposed for Ref, though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
       (func $f1 (param (ref $box)) (unreachable)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
-      (func $f1 (result (ref $box)) (ref.null (ref $box))))`),
+      (func $f1 (result (ref $box)) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
       (func $f1 (param anyref) (unreachable)))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
-      (func $f1 (result anyref) (ref.null anyref)))`),
+      (func $f1 (result anyref) (ref.null)))`),
          "object");
 
 // Can't call via exported table with type that is exposed for Ref, though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (type $fn (func (param (ref $box))))
       (table (export "tbl") 1 anyfunc)
       (func (param i32)
-       (call_indirect $fn (ref.null (ref $box)) (get_local 0))))`),
+       (call_indirect $fn (ref.null) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (type $fn (func (result (ref $box))))
       (table (export "tbl") 1 anyfunc)
       (func (param i32) (result (ref $box))
        (call_indirect $fn (get_local 0))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $fn (func (param anyref)))
       (table (export "tbl") 1 anyfunc)
       (func (param i32)
-       (call_indirect $fn (ref.null anyref) (get_local 0))))`),
+       (call_indirect $fn (ref.null) (get_local 0))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $fn (func (result anyref)))
       (table (export "tbl") 1 anyfunc)
       (func (param i32) (result anyref)
        (call_indirect $fn (get_local 0))))`),
          "object");
 
 // Can't call via imported table with type that is exposed for Ref, though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (type $fn (func (param (ref $box))))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32)
-       (call_indirect $fn (ref.null (ref $box)) (get_local 0))))`),
+       (call_indirect $fn (ref.null) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (type $fn (func (result (ref $box))))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32) (result (ref $box))
        (call_indirect $fn (get_local 0))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $fn (func (param anyref)))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32)
-       (call_indirect $fn (ref.null anyref) (get_local 0))))`),
+       (call_indirect $fn (ref.null) (get_local 0))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $fn (func (result anyref)))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32) (result anyref)
        (call_indirect $fn (get_local 0))))`),
          "object");
 
 // We can call via a private table with a type that is exposed for Ref.
 
 {
     let m = wasmCompile(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $box (struct (field $val i32)))
           (type $fn (func (param (ref $box)) (result i32)))
           (table 1 anyfunc)
           (elem (i32.const 0) $f1)
           (func $f1 (param (ref $box)) (result i32) (i32.const 37))
           (func (export "f") (param i32) (result i32)
-           (call_indirect $fn (ref.null (ref $box)) (get_local 0))))`);
+           (call_indirect $fn (ref.null) (get_local 0))))`);
     let i = new WebAssembly.Instance(m).exports;
     assertEq(i.f(0), 37);
 }
--- a/js/src/jit-test/tests/wasm/gc/ref-struct.js
+++ b/js/src/jit-test/tests/wasm/gc/ref-struct.js
@@ -3,54 +3,54 @@
 // We'll be running some binary-format tests shortly.
 
 load(libdir + "wasm-binary.js");
 
 const v2vSigSection = sigSection([{args:[], ret:VoidCode}]);
 
 function checkInvalid(body, errorMessage) {
     assertErrorMessage(() => new WebAssembly.Module(
-        moduleWithSections([gcFeatureOptInSection(1),
+        moduleWithSections([gcFeatureOptInSection(2),
                             v2vSigSection,
                             declSection([0]),
                             bodySection([body])])),
                        WebAssembly.CompileError,
                        errorMessage);
 }
 
 // General test case for struct.new, struct.get, and struct.set: binary tree
 // manipulation.
 
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (import $print_lp "" "print_lp" (func))
           (import $print_rp "" "print_rp" (func))
           (import $print_int "" "print_int" (func (param i32)))
 
           (type $wabbit (struct
                          (field $x (mut i32))
                          (field $left (mut (ref $wabbit)))
                          (field $right (mut (ref $wabbit)))))
 
-          (global $g (mut (ref $wabbit)) (ref.null (ref $wabbit)))
+          (global $g (mut (ref $wabbit)) (ref.null))
 
           (global $k (mut i32) (i32.const 0))
 
           (func (export "init") (param $n i32)
                 (set_global $g (call $make (get_local $n))))
 
           (func $make (param $n i32) (result (ref $wabbit))
                 (local $tmp i32)
                 (set_local $tmp (get_global $k))
                 (set_global $k (i32.add (get_local $tmp) (i32.const 1)))
                 (if (ref $wabbit) (i32.le_s (get_local $n) (i32.const 2))
-                    (struct.new $wabbit (get_local $tmp) (ref.null (ref $wabbit)) (ref.null (ref $wabbit)))
+                    (struct.new $wabbit (get_local $tmp) (ref.null) (ref.null))
                     (block (ref $wabbit)
                       (struct.new $wabbit
                                   (get_local $tmp)
                                   (call $make (i32.sub (get_local $n) (i32.const 1)))
                                   (call $make (i32.sub (get_local $n) (i32.const 2)))))))
 
           (func (export "accumulate") (result i32)
                 (call $accum (get_global $g)))
@@ -114,55 +114,55 @@ function checkInvalid(body, errorMessage
 }
 
 // Sanity check for struct.set: we /can/ store a (ref T) into a (ref U) field
 // with struct.set if T <: U; this should fall out of normal coercion but good
 // to test.
 
 wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut (ref $node)))))
       (type $nix (struct (field (mut (ref $node))) (field i32)))
       (func $f (param $p (ref $node)) (param $q (ref $nix))
        (struct.set $node 0 (get_local $p) (get_local $q))))`);
 
 // struct.narrow: if the pointer's null we get null
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result anyref)
-       (call $f (ref.null (ref $node)))))`).exports.test(),
+       (call $f (ref.null))))`).exports.test(),
          null);
 
 // struct.narrow: if the downcast succeeds we get the original pointer
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result i32)
        (local $n (ref $node))
        (set_local $n (struct.new $node2 (i32.const 0) (f32.const 12)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          1);
 
 // And once more with mutable fields
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (type $node2 (struct (field (mut i32)) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result i32)
        (local $n (ref $node))
        (set_local $n (struct.new $node2 (i32.const 0) (f32.const 12)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
@@ -174,111 +174,111 @@ assertEq(wasmEvalText(
 //
 // We use ref-typed fields here because they have the trickiest equality rules,
 // and we have two cases: one where the ref types are the same, and one where
 // they reference different structures that look the same; this latter case
 // should fail because our structural compatibility is shallow.
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (type $node (struct (field i32)))
       (type $node2a (struct (field i32) (field (ref $node))))
       (type $node2b (struct (field i32) (field (ref $node))))
 
       (func $f (param $p (ref $node)) (result (ref $node2b))
        (struct.narrow (ref $node) (ref $node2b) (get_local $p)))
 
       (func (export "test") (result i32)
        (local $n (ref $node))
-       (set_local $n (struct.new $node2a (i32.const 0) (ref.null (ref $node))))
+       (set_local $n (struct.new $node2a (i32.const 0) (ref.null)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          1);
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (type $node (struct (field i32)))
       (type $nodeCopy (struct (field i32)))
       (type $node2a (struct (field i32) (field (ref $node))))
       (type $node2b (struct (field i32) (field (ref $nodeCopy))))
 
       (func $f (param $p (ref $node)) (result (ref $node2b))
        (struct.narrow (ref $node) (ref $node2b) (get_local $p)))
 
       (func (export "test") (result i32)
        (local $n (ref $node))
-       (set_local $n (struct.new $node2a (i32.const 0) (ref.null (ref $node))))
+       (set_local $n (struct.new $node2a (i32.const 0) (ref.null)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          0);
 
 // Another subtle case: struct.narrow can target a type that is not the concrete
 // type of the object, but a prefix of that concrete type.
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (type $node3 (struct (field i32) (field f32) (field f64)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result i32)
        (local $n (ref $node))
        (set_local $n (struct.new $node3 (i32.const 0) (f32.const 12) (f64.const 17)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          1);
 
 // struct.narrow: if the downcast fails we get null
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (type $snort (struct (field i32) (field f64)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result anyref)
        (call $f (struct.new $snort (i32.const 0) (f64.const 12)))))`).exports.test(),
          null);
 
 // struct.narrow: anyref -> struct when the anyref is the right struct;
 // special case since anyref requires unboxing
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p anyref) (result (ref $node))
        (struct.narrow anyref (ref $node) (get_local $p)))
       (func (export "test") (result i32)
        (local $n (ref $node))
        (set_local $n (struct.new $node (i32.const 0)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          1);
 
 // struct.narrow: anyref -> struct when the anyref is some random gunk.
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func (export "test") (param $p anyref) (result anyref)
        (struct.narrow anyref (ref $node) (get_local $p))))`).exports.test({hi:37}),
          null);
 
 // Types are private to an instance and struct.narrow can't break this
 
 {
     let txt =
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $node (struct (field i32)))
           (func (export "make") (param $n i32) (result anyref)
            (struct.new $node (get_local $n)))
           (func (export "coerce") (param $p anyref) (result i32)
            (ref.is_null (struct.narrow anyref (ref $node) (get_local $p)))))`;
     let mod = new WebAssembly.Module(wasmTextToBinary(txt));
     let ins1 = new WebAssembly.Instance(mod).exports;
     let ins2 = new WebAssembly.Instance(mod).exports;
@@ -288,201 +288,199 @@ assertEq(wasmEvalText(
 }
 
 // Negative tests
 
 // Attempting to mutate immutable field with struct.set
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node))
        (struct.set $node 0 (get_local $p) (i32.const 37))))`),
                    WebAssembly.CompileError,
                    /field is not mutable/);
 
 // Attempting to store incompatible value in mutable field with struct.set
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (func $f (param $p (ref $node))
        (struct.set $node 0 (get_local $p) (f32.const 37))))`),
                    WebAssembly.CompileError,
                    /expression has type f32 but expected i32/);
 
 // Out-of-bounds reference for struct.get
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node)) (result i32)
        (struct.get $node 1 (get_local $p))))`),
                    WebAssembly.CompileError,
                    /field index out of range/);
 
 // Out-of-bounds reference for struct.set
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (func $f (param $p (ref $node))
        (struct.set $node 1 (get_local $p) (i32.const 37))))`),
                    WebAssembly.CompileError,
                    /field index out of range/);
 
 // Base pointer is of unrelated type to stated type in struct.get
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $snort (struct (field f64)))
       (func $f (param $p (ref $snort)) (result i32)
        (struct.get $node 0 (get_local $p))))`),
                    WebAssembly.CompileError,
                    /expression has type.*but expected.*/);
 
 // Base pointer is of unrelated type to stated type in struct.set
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (type $snort (struct (field f64)))
       (func $f (param $p (ref $snort)) (result i32)
        (struct.set $node 0 (get_local $p) (i32.const 0))))`),
                    WebAssembly.CompileError,
                    /expression has type.*but expected.*/);
 
 // Base pointer is of unrelated type to stated type in struct.narrow
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (type $snort (struct (field f64)))
       (func $f (param $p (ref $snort)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /expression has type.*but expected.*/);
 
 // source and target types are compatible except for mutability
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field (mut i32)) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /invalid narrowing operation/);
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (type $node2 (struct (field i32) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /invalid narrowing operation/);
 
 // source and target types must be ref types: source syntax
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node)) (result anyref)
        (struct.narrow i32 anyref (get_local 0))))`),
                    SyntaxError,
                    /struct.narrow requires ref type/);
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node)) (result anyref)
        (struct.narrow anyref i32 (get_local 0))))`),
                    SyntaxError,
                    /struct.narrow requires ref type/);
 
 // source and target types must be ref types: binary format
 
 checkInvalid(funcBody({locals:[],
                        body:[
                            RefNull,
-                           AnyrefCode,
                            MiscPrefix, StructNarrow, I32Code, AnyrefCode,
                            DropCode
                        ]}),
              /invalid reference type for struct.narrow/);
 
 checkInvalid(funcBody({locals:[],
                        body:[
                            RefNull,
-                           AnyrefCode,
                            MiscPrefix, StructNarrow, AnyrefCode, I32Code,
                            DropCode
                        ]}),
              /invalid reference type for struct.narrow/);
 
 // target type is anyref so source type must be anyref as well (no upcasts)
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node)) (result anyref)
        (struct.narrow (ref $node) anyref (get_local 0))))`),
                    WebAssembly.CompileError,
                    /invalid type combination in struct.narrow/);
 
 // target type must be subtype of source type (no upcasts)
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (func $f (param $p (ref $node2)) (result anyref)
        (struct.narrow (ref $node2) (ref $node) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /invalid narrowing operation/);
 
 // Null pointer dereference in struct.get
 
 assertErrorMessage(function() {
     let ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $node (struct (field i32)))
           (func (export "test")
-           (drop (call $f (ref.null (ref $node)))))
+           (drop (call $f (ref.null))))
           (func $f (param $p (ref $node)) (result i32)
            (struct.get $node 0 (get_local $p))))`);
     ins.exports.test();
 },
                    WebAssembly.RuntimeError,
                    /dereferencing null pointer/);
 
 // Null pointer dereference in struct.set
 
 assertErrorMessage(function() {
     let ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $node (struct (field (mut i32))))
           (func (export "test")
-           (call $f (ref.null (ref $node))))
+           (call $f (ref.null)))
           (func $f (param $p (ref $node))
            (struct.set $node 0 (get_local $p) (i32.const 0))))`);
     ins.exports.test();
 },
                    WebAssembly.RuntimeError,
                    /dereferencing null pointer/);
--- a/js/src/jit-test/tests/wasm/gc/ref.js
+++ b/js/src/jit-test/tests/wasm/gc/ref.js
@@ -3,17 +3,17 @@ if (!wasmGcEnabled()) {
                        WebAssembly.CompileError, /reference types not enabled/);
     quit(0);
 }
 
 // Parsing and resolving.
 
 var bin = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $cons (struct
                    (field $car i32)
                    (field $cdr (ref $cons))))
 
       (type $odd (struct
                   (field $odd.x i32)
                   (field $to_even (ref $even))))
 
@@ -29,191 +29,191 @@ var bin = wasmTextToBinary(
       ;; Note none of these functions are exported, as they use Ref types in their signatures.
 
       (func (param (ref $cons)) (result i32)
        (i32.const 0))
 
       (func $cdr (param $p (ref $cons)) (result (ref $cons))
        (local $l (ref $cons))
        ;; store null value of correct type
-       (set_local $l (ref.null (ref $cons)))
+       (set_local $l (ref.null))
        ;; store local of correct type
        (set_local $l (get_local $p))
        ;; store call result of correct type
        (set_local $l (call $cdr (get_local $p)))
        ;; TODO: eventually also a test with get_global
        ;; blocks and if with result type
        (block (ref $cons)
         (if (ref $cons) (i32.eqz (i32.const 0))
             (unreachable)
-            (ref.null (ref $cons)))))
+            (ref.null))))
 
       (func (param (ref $even)) (result (ref $odd))
-       (ref.null (ref $odd)))
+       (ref.null))
 
       (func (param (ref $odd)) (result (ref $even))
-       (ref.null (ref $even)))
+       (ref.null))
 
       (func (param (ref $cons))
        (call $cdr (get_local 0))
        drop
        (call $imp (get_local 0))
        drop)
 
       (func (param (ref $cons))
-       (drop (ref.eq (get_local 0) (ref.null (ref $cons))))
-       (drop (ref.eq (ref.null (ref $cons)) (get_local 0)))
-       (drop (ref.eq (get_local 0) (ref.null anyref)))
-       (drop (ref.eq (ref.null anyref) (get_local 0))))
+       (drop (ref.eq (get_local 0) (ref.null)))
+       (drop (ref.eq (ref.null) (get_local 0)))
+       (drop (ref.eq (get_local 0) (ref.null)))
+       (drop (ref.eq (ref.null) (get_local 0))))
      )`);
 
 // Validation
 
 assertEq(WebAssembly.validate(bin), true);
 
 // ref.is_null should work on any reference type
 
 new WebAssembly.Module(wasmTextToBinary(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct))
  (func $null (param (ref $s)) (result i32)
    (ref.is_null (get_local 0))))
 `))
 
 // Automatic upcast to anyref
 
 new WebAssembly.Module(wasmTextToBinary(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (func $f (param (ref $s)) (call $g (get_local 0)))
  (func $g (param anyref) (unreachable)))
 `));
 
 // Misc failure modes
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (func (param (ref $odd)) (unreachable)))
 `),
 SyntaxError, /Type label.*not found/);
 
 // Ref type mismatch in parameter is allowed through the prefix rule
 // but not if the structs are incompatible.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field i32)))
  (func $f (param (ref $s)) (unreachable))
  (func $g (param (ref $t)) (call $f (get_local 0)))
 )`);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field f32))) ;; Incompatible type
  (func $f (param (ref $s)) (unreachable))
  (func $g (param (ref $t)) (call $f (get_local 0)))
 )`),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field (mut i32)))) ;; Incompatible mutability
  (func $f (param (ref $s)) (unreachable))
  (func $g (param (ref $t)) (call $f (get_local 0)))
 )`),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 // Ref type mismatch in assignment to local but the prefix rule allows
 // the assignment to succeed if the structs are the same.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field i32)))
  (func $f (param (ref $s)) (local (ref $t)) (set_local 1 (get_local 0))))
 `)
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field f32)))
  (func $f (param (ref $s)) (local (ref $t)) (set_local 1 (get_local 0))))
 `),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field (mut i32))))
  (func $f (param (ref $s)) (unreachable))
  (func $g (param (ref $t)) (call $f (get_local 0)))
 )`),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 // Ref type mismatch in return but the prefix rule allows the return
 // to succeed if the structs are the same.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field i32)))
  (func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
 `);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field f32)))
  (func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
 `),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field (mut i32))))
  (func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
 `),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 // Ref type can't reference a function type
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $x (func (param i32)))
  (func $f (param (ref $x)) (unreachable)))
 `),
 SyntaxError, /Type label.*not found/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type (func (param i32)))
  (func $f (param (ref 0)) (unreachable)))
 `),
 WebAssembly.CompileError, /does not reference a struct type/);
 
 // No automatic downcast from anyref
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (func $f (param anyref) (call $g (get_local 0)))
  (func $g (param (ref $s)) (unreachable)))
 `),
 WebAssembly.CompileError, /expression has type anyref but expected ref/);
--- a/js/src/jit-test/tests/wasm/gc/structs.js
+++ b/js/src/jit-test/tests/wasm/gc/structs.js
@@ -1,15 +1,15 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 var conf = getBuildConfiguration();
 
 var bin = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (table 2 anyfunc)
       (elem (i32.const 0) $doit $doitagain)
 
       ;; Type array has a mix of types
 
       (type $f1 (func (param i32) (result i32)))
 
@@ -221,17 +221,17 @@ assertEq(withfloats._1, Math.PI);
 assertEq(withfloats._2, bigger);
 assertEq(withfloats._3, Math.fround(5/6));
 assertEq(withfloats._4, 0x1337);
 
 // A simple stress test
 
 var stress = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32) (field (ref $node))))
       (func (export "iota1") (param $n i32) (result anyref)
        (local $list (ref $node))
        (block $exit
         (loop $loop
          (br_if $exit (i32.eqz (get_local $n)))
          (set_local $list (struct.new $node (get_local $n) (get_local $list)))
          (set_local $n (i32.sub (get_local $n) (i32.const 1)))
@@ -249,17 +249,17 @@ assertEq(the_list, null);
 // Fields and their exposure in JS.  We can't export types yet so hide them
 // inside the module with globals.
 
 // i64 fields.
 
 {
     let txt =
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $big (struct
                       (field (mut i32))
                       (field (mut i64))
                       (field (mut i32))))
 
           (func (export "set") (param anyref)
            (local (ref $big))
@@ -309,24 +309,24 @@ assertEq(the_list, null);
     assertEq(v._1_high, 0x31415926)
     assertEq(ins.low(v), 0x53589793);
     assertEq(ins.high(v), 0x31415926)
 }
 
 {
     let txt =
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $big (struct
                       (field (mut i32))
                       (field (mut i64))
                       (field (mut i32))))
 
-          (global $g (mut (ref $big)) (ref.null (ref $big)))
+          (global $g (mut (ref $big)) (ref.null))
 
           (func (export "make") (result anyref)
            (set_global $g
             (struct.new $big (i32.const 0x7aaaaaaa) (i64.const 0x4201020337) (i32.const 0x6bbbbbbb)))
            (get_global $g))
 
           (func (export "update0") (param $x i32)
            (struct.set $big 0 (get_global $g) (get_local $x)))
@@ -384,21 +384,21 @@ assertEq(the_list, null);
     assertEq(ins.get1_high(), 0x77777777);
     assertEq(v._1_high, 0x77777777);
     assertEq(v._2, 0x62345123);
 }
 
 
 var bin = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (type $cons (struct (field i32) (field (ref $cons))))
 
-      (global $g (mut (ref $cons)) (ref.null (ref $cons)))
+      (global $g (mut (ref $cons)) (ref.null))
 
       (func (export "push") (param i32)
        (set_global $g (struct.new $cons (get_local 0) (get_global $g))))
 
       (func (export "top") (result i32)
        (struct.get $cons 0 (get_global $g)))
 
       (func (export "pop")
@@ -427,17 +427,17 @@ assertErrorMessage(() => ins.pop(),
 
 // Check that a wrapped object cannot be unboxed from anyref even if the wrapper
 // points to the right type.  This is a temporary restriction, until we're able
 // to avoid dealing with wrappers inside the engine.
 
 {
     var ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $Node (struct (field i32)))
           (func (export "mk") (result anyref)
            (struct.new $Node (i32.const 37)))
           (func (export "f") (param $n anyref) (result anyref)
            (struct.narrow anyref (ref $Node) (get_local $n))))`).exports;
     var n = ins.mk();
     assertEq(ins.f(n), n);
     assertEq(ins.f(wrapWithProto(n, {})), null);
@@ -445,17 +445,17 @@ assertErrorMessage(() => ins.pop(),
 
 // Field names.
 
 // Test that names map to the right fields.
 
 {
     let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $s (struct
                     (field $x i32)
                     (field $y i32)))
 
           (func $f (param $p (ref $s)) (result i32)
            (struct.get $s $x (get_local $p)))
 
@@ -473,165 +473,165 @@ assertErrorMessage(() => ins.pop(),
     assertEq(ins.testf(10), 10);
     assertEq(ins.testg(10), 20);
 }
 
 // Test that field names must be unique in the module.
 
 assertErrorMessage(() => wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (type $s (struct (field $x i32)))
       (type $t (struct (field $x i32)))
      )`),
                   SyntaxError,
                   /duplicate field name/);
 
 // negative tests
 
 // Wrong type passed as initializer
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
 (module
-  (gc_feature_opt_in 1)
+  (gc_feature_opt_in 2)
   (type $r (struct (field i32)))
   (func $f (param f64) (result anyref)
     (struct.new $r (get_local 0)))
 )`)),
 WebAssembly.CompileError, /type mismatch/);
 
 // Too few values passed for initializer
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
 (module
-  (gc_feature_opt_in 1)
+  (gc_feature_opt_in 2)
   (type $r (struct (field i32) (field i32)))
   (func $f (result anyref)
     (struct.new $r (i32.const 0)))
 )`)),
 WebAssembly.CompileError, /popping value from empty stack/);
 
 // Too many values passed for initializer, sort of
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
 (module
-  (gc_feature_opt_in 1)
+  (gc_feature_opt_in 2)
   (type $r (struct (field i32) (field i32)))
   (func $f (result anyref)
     (i32.const 0)
     (i32.const 1)
     (i32.const 2)
     struct.new $r)
 )`)),
 WebAssembly.CompileError, /unused values/);
 
 // Not referencing a structure type
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
 (module
-  (gc_feature_opt_in 1)
+  (gc_feature_opt_in 2)
   (type (func (param i32) (result i32)))
   (func $f (result anyref)
     (struct.new 0))
 )`)),
 WebAssembly.CompileError, /not a struct type/);
 
 // Nominal type equivalence for structs, but the prefix rule allows this
 // conversion to succeed.
 
 wasmEvalText(`
  (module
-   (gc_feature_opt_in 1)
+   (gc_feature_opt_in 2)
    (type $p (struct (field i32)))
    (type $q (struct (field i32)))
    (func $f (result (ref $p))
     (struct.new $q (i32.const 0))))
 `);
 
 // The field name is optional, so this should work.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32))))
 `)
 
 // Empty structs are OK.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct)))
 `)
 
 // Multiply defined structures.
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field $x i32)))
  (type $s (struct (field $y i32))))
 `),
 SyntaxError, /duplicate type name/);
 
 // Bogus type definition syntax.
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (field $x i32)))
 `),
 SyntaxError, /bad type definition/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field $x i31))))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (fjeld $x i32))))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct abracadabra)))
 `),
 SyntaxError, /parsing wasm text/);
 
 // Function should not reference struct type: syntactic test
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct))
  (type $f (func (param i32) (result i32)))
  (func (type 0) (param i32) (result i32) (unreachable)))
 `),
 WebAssembly.CompileError, /signature index references non-signature/);
 
 // Can't set immutable fields from JS
 
 {
     let ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $s (struct
                     (field i32)
                     (field (mut i64))))
           (func (export "make") (result anyref)
            (struct.new $s (i32.const 37) (i64.const 42))))`).exports;
     let v = ins.make();
     assertErrorMessage(() => v._0 = 12,
                        Error,
@@ -646,17 +646,17 @@ WebAssembly.CompileError, /signature ind
 
 // Function should not reference struct type: binary test
 
 var bad = new Uint8Array([0x00, 0x61, 0x73, 0x6d,
                           0x01, 0x00, 0x00, 0x00,
 
                           0x2a,                   // GcFeatureOptIn section
                           0x01,                   // Section size
-                          0x01,                   // Version
+                          0x02,                   // Version
 
                           0x01,                   // Type section
                           0x03,                   // Section size
                           0x01,                   // One type
                           0x50,                   // Struct
                           0x00,                   // Zero fields
 
                           0x03,                   // Function section
--- a/js/src/jit-test/tests/wasm/gc/tables-generalized.js
+++ b/js/src/jit-test/tests/wasm/gc/tables-generalized.js
@@ -3,53 +3,53 @@
 ///////////////////////////////////////////////////////////////////////////
 //
 // General table management in wasm
 
 // Wasm: Create table-of-anyref
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table 10 anyref))`));
 
 // Wasm: Import table-of-anyref
 // JS: create table-of-anyref
 
 new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table (import "m" "t") 10 anyref))`)),
                          {m:{t: new WebAssembly.Table({element:"anyref", initial:10})}});
 
 new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (import "m" "t" (table 10 anyref)))`)),
                          {m:{t: new WebAssembly.Table({element:"anyref", initial:10})}});
 
 // Wasm: Export table-of-anyref, initial values shall be null
 
 {
     let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table (export "t") 10 anyref))`)));
     let t = ins.exports.t;
     assertEq(t.length, 10);
     for (let i=0; i < t.length; i++)
         assertEq(t.get(0), null);
 }
 
 // JS: Exported table can be grown, and values are preserved
 
 {
     let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table (export "t") 10 anyref))`)));
     let t = ins.exports.t;
     let objs = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}];
     for (let i in objs)
         t.set(i, objs[i]);
     ins.exports.t.grow(10);
     assertEq(ins.exports.t.length, 20);
     for (let i in objs)
@@ -57,17 +57,17 @@ new WebAssembly.Instance(new WebAssembly
 }
 
 // Wasm: table.copy between tables of anyref (currently source and destination
 // are both table zero)
 
 {
     let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table (export "t") 10 anyref)
        (func (export "f")
          (table.copy (i32.const 5) (i32.const 0) (i32.const 3))))`)));
     let t = ins.exports.t;
     let objs = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}];
     for (let i in objs)
         t.set(i, objs[i]);
     ins.exports.f();
@@ -82,52 +82,52 @@ new WebAssembly.Instance(new WebAssembly
     assertEq(t.get(8), objs[8]);
     assertEq(t.get(9), objs[9]);
 }
 
 // Wasm: element segments targeting table-of-anyref is forbidden
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (func $f1 (result i32) (i32.const 0))
        (table 10 anyref)
        (elem (i32.const 0) $f1))`)),
                    WebAssembly.CompileError,
                    /only tables of 'anyfunc' may have element segments/);
 
 // Wasm: table.init on table-of-anyref is forbidden
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (func $f1 (result i32) (i32.const 0))
        (table 10 anyref)
        (elem passive $f1)
        (func
          (table.init 0 (i32.const 0) (i32.const 0) (i32.const 0))))`)),
                    WebAssembly.CompileError,
                    /only tables of 'anyfunc' may have element segments/);
 
 // Wasm: table types must match at link time
 
 assertErrorMessage(
     () => new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (import "m" "t" (table 10 anyref)))`)),
                                    {m:{t: new WebAssembly.Table({element:"anyfunc", initial:10})}}),
     WebAssembly.LinkError,
     /imported table type mismatch/);
 
 // call_indirect cannot reference table-of-anyref
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table 10 anyref)
        (type $t (func (param i32) (result i32)))
        (func (result i32)
          (call_indirect $t (i32.const 37))))`)),
                    WebAssembly.CompileError,
                    /indirect calls must go through a table of 'anyfunc'/);
 
 ///////////////////////////////////////////////////////////////////////////
@@ -237,17 +237,17 @@ assertErrorMessage(() => new WebAssembly
     let ins = wasmEvalText(
         `(module
            (gc_feature_opt_in 2)
            (table (export "t") 10 anyref)
            (type $dummy (struct (field i32)))
            (func (export "set_anyref") (param i32) (param anyref)
              (table.set (get_local 0) (get_local 1)))
            (func (export "set_null") (param i32)
-             (table.set (get_local 0) (ref.null anyref)))
+             (table.set (get_local 0) (ref.null)))
            (func (export "set_ref") (param i32) (param anyref)
              (table.set (get_local 0) (struct.narrow anyref (ref $dummy) (get_local 1))))
            (func (export "make_struct") (result anyref)
              (struct.new $dummy (i32.const 37))))`);
     let x = {};
     ins.exports.set_anyref(3, x);
     assertEq(ins.exports.t.get(3), x);
     ins.exports.set_null(3);
@@ -262,17 +262,17 @@ assertErrorMessage(() => new WebAssembly
 
 // table.set with non-i32 index - fails validation
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (gc_feature_opt_in 2)
        (table 10 anyref)
        (func (export "f") (param f64)
-         (table.set (get_local 0) (ref.null anyref))))`)),
+         (table.set (get_local 0) (ref.null))))`)),
                    WebAssembly.CompileError,
                    /type mismatch/);
 
 // table.set with non-anyref value - fails validation
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (gc_feature_opt_in 2)
@@ -311,17 +311,17 @@ assertErrorMessage(() => new WebAssembly
 // table.grow with delta at upper limit - fails
 // table.grow with negative delta - fails
 
 let ins = wasmEvalText(
     `(module
       (gc_feature_opt_in 2)
       (table (export "t") 10 20 anyref)
       (func (export "grow") (param i32) (result i32)
-       (table.grow (get_local 0) (ref.null anyref))))`);
+       (table.grow (get_local 0) (ref.null))))`);
 assertEq(ins.exports.grow(0), 10);
 assertEq(ins.exports.t.length, 10);
 assertEq(ins.exports.grow(1), 10);
 assertEq(ins.exports.t.length, 11);
 assertEq(ins.exports.t.get(10), null);
 assertEq(ins.exports.grow(9), 11);
 assertEq(ins.exports.t.length, 20);
 assertEq(ins.exports.t.get(19), null);
@@ -340,52 +340,52 @@ assertEq(ins.exports.t.length, 20)
 // Special case for private tables without a maximum
 
 {
     let ins = wasmEvalText(
         `(module
           (gc_feature_opt_in 2)
           (table 10 anyref)
           (func (export "grow") (param i32) (result i32)
-           (table.grow (get_local 0) (ref.null anyref))))`);
+           (table.grow (get_local 0) (ref.null))))`);
     assertEq(ins.exports.grow(0), 10);
     assertEq(ins.exports.grow(1), 10);
     assertEq(ins.exports.grow(9), 11);
     assertEq(ins.exports.grow(0), 20);
 }
 
 // Can't grow table of anyfunc yet
 
 assertErrorMessage(() => wasmEvalText(
     `(module
       (gc_feature_opt_in 2)     ;; Required because of the 'anyref' null value below
       (table $t 2 anyfunc)
       (func $f
-       (drop (table.grow (i32.const 1) (ref.null anyref)))))`),
+       (drop (table.grow (i32.const 1) (ref.null)))))`),
                    WebAssembly.CompileError,
                    /table.grow only on tables of anyref/);
 
 // table.grow with non-i32 argument - fails validation
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (gc_feature_opt_in 2)
        (table 10 anyref)
        (func (export "f") (param f64)
-        (table.grow (get_local 0) (ref.null anyref))))`)),
+        (table.grow (get_local 0) (ref.null))))`)),
                    WebAssembly.CompileError,
                    /type mismatch/);
 
 // table.grow when there are no tables - fails validation
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (gc_feature_opt_in 2)
        (func (export "f") (param i32)
-        (table.grow (get_local 0) (ref.null anyref))))`)),
+        (table.grow (get_local 0) (ref.null))))`)),
                    WebAssembly.CompileError,
                    /table index out of range for table.grow/);
 
 // table.grow on table of anyref with non-null ref value
 
 {
     let ins = wasmEvalText(
         `(module
@@ -406,17 +406,17 @@ for (let visibility of ['', '(export "t"
     let exp = {m:{t: new WebAssembly.Table({element:"anyref",
                                             initial: 10,
                                             maximum: 20})}};
     let ins = wasmEvalText(
         `(module
           (gc_feature_opt_in 2)
           (table ${visibility} 10 20 anyref)
           (func (export "grow") (param i32) (result i32)
-           (table.grow (get_local 0) (ref.null anyref)))
+           (table.grow (get_local 0) (ref.null)))
           (func (export "size") (result i32)
            (table.size)))`,
         exp);
     assertEq(ins.exports.grow(0), 10);
     assertEq(ins.exports.size(), 10);
     assertEq(ins.exports.grow(1), 10);
     assertEq(ins.exports.size(), 11);
     assertEq(ins.exports.grow(9), 11);
--- a/js/src/jit-test/tests/wasm/gc/tables-multiple.js
+++ b/js/src/jit-test/tests/wasm/gc/tables-multiple.js
@@ -113,17 +113,17 @@ var exp = {m:{t0: new WebAssembly.Table(
               t1: new WebAssembly.Table({element:"anyref", initial:3})}};
 var ins = wasmEvalText(
     `(module
       (gc_feature_opt_in 2)
 
       (table $t0 (import "m" "t0") 2 anyref)
       (table $t1 (import "m" "t1") 3 anyref)
       (func (export "f") (result i32)
-       (table.grow $t1 (i32.const 5) (ref.null anyref)))
+       (table.grow $t1 (i32.const 5) (ref.null)))
       (func (export "size0") (result i32)
        (table.size $t0))
       (func (export "size1") (result i32)
        (table.size $t1)))`,
     exp);
 
 assertEq(ins.exports.f(), 3);
 assertEq(exp.m.t1.length, 8);
@@ -229,19 +229,19 @@ var exp = {m: {t0: tbl, t1:tbl}};
 
 var ins = wasmEvalText(
     `(module
       (gc_feature_opt_in 2)
       (import $t0 "m" "t0" (table 1 anyref))
       (import $t1 "m" "t1" (table 1 anyref))
       (table $t2 (export "t2") 1 anyfunc)
       (func (export "f") (result i32)
-       (table.grow $t0 (i32.const 1) (ref.null anyref)))
+       (table.grow $t0 (i32.const 1) (ref.null)))
       (func (export "g") (result i32)
-       (table.grow $t1 (i32.const 1) (ref.null anyref)))
+       (table.grow $t1 (i32.const 1) (ref.null)))
       (func (export "size") (result i32)
        (table.size $t2)))`,
     exp);
 
 assertEq(ins.exports.f(), 1);
 assertEq(ins.exports.g(), 2);
 assertEq(ins.exports.f(), 3);
 assertEq(ins.exports.g(), 4);
@@ -382,17 +382,17 @@ assertErrorMessage(() => wasmEvalText(
                    /table index out of range for table.size/);
 
 assertErrorMessage(() => wasmEvalText(
     `(module
       (gc_feature_opt_in 2)
       (table $t0 2 anyref)
       (table $t1 2 anyref)
       (func $f (result i32)
-       (table.grow 2 (i32.const 1) (ref.null anyref))))`),
+       (table.grow 2 (i32.const 1) (ref.null))))`),
                    WebAssembly.CompileError,
                    /table index out of range for table.grow/);
 
 assertErrorMessage(() => wasmEvalText(
     `(module
       (table $t0 2 anyfunc)
       (elem passive) ;; 0
       (func $f (result i32)
--- a/js/src/jit-test/tests/wasm/gc/tables-stress.js
+++ b/js/src/jit-test/tests/wasm/gc/tables-stress.js
@@ -8,17 +8,17 @@ for ( let prefix of ['', '(table $prefix
        (table $tbl 0 anyref)
        (import $item "m" "item" (func (result anyref)))
        (func (export "run") (param $numiters i32)
          (local $i i32)
          (local $j i32)
          (local $last i32)
          (local $iters i32)
          (local $tmp anyref)
-         (set_local $last (table.grow $tbl (i32.const 1) (ref.null anyref)))
+         (set_local $last (table.grow $tbl (i32.const 1) (ref.null)))
          (table.set $tbl (get_local $last) (call $item))
          (loop $iter_continue
            (set_local $i (i32.const 0))
            (set_local $j (get_local $last))
            (block $l_break
              (loop $l_continue
                (br_if $l_break (i32.ge_s (get_local $j) (get_local $i)))
                (set_local $tmp (table.get $tbl (get_local $i)))
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/regress/baseline-stack-height.js
@@ -0,0 +1,1 @@
+new WebAssembly.Module(os.file.readFile(scriptdir + "/baseline-stack-height.wasm", 'binary'));
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cc25a1dac8033e72ef5ea8f7a207f6f1636beaed
GIT binary patch
literal 67032
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
EA1oYNI{*Lx
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -13932,16 +13932,18 @@ CodeGenerator::emitIonToWasmCallBase(LIo
             argMir = ToMIRType(sig.args()[i]);
             break;
           case wasm::ValType::I64:
           case wasm::ValType::Ref:
           case wasm::ValType::AnyRef:
             // Don't forget to trace GC type arguments in TraceJitExitFrames
             // when they're enabled.
             MOZ_CRASH("unexpected argument type when calling from ion to wasm");
+          case wasm::ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
         }
 
         ABIArg arg = abi.next(argMir);
         switch (arg.kind()) {
           case ABIArg::GPR:
           case ABIArg::FPU: {
             MOZ_ASSERT(ToAnyRegister(lir->getOperand(i)) == arg.reg());
             stackArgs.infallibleEmplaceBack(wasm::JitCallStackArg());
@@ -13988,16 +13990,18 @@ CodeGenerator::emitIonToWasmCallBase(LIo
         MOZ_ASSERT(ToFloatRegister(lir->output()) == ReturnDoubleReg);
         break;
       case wasm::ExprType::Ref:
       case wasm::ExprType::AnyRef:
       case wasm::ExprType::I64:
         // Don't forget to trace GC type return value in TraceJitExitFrames
         // when they're enabled.
         MOZ_CRASH("unexpected return type when calling from ion to wasm");
+      case wasm::ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case wasm::ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     bool profilingEnabled = isProfilerInstrumentationEnabled();
     WasmInstanceObject* instObj = lir->mir()->instanceObject();
 
     bool wasmGcEnabled = false;
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -4108,16 +4108,18 @@ IonBuilder::inlineWasmCall(CallInfo& cal
             break;
           case wasm::ValType::F64:
             conversion = MToDouble::New(alloc(), arg);
             break;
           case wasm::ValType::I64:
           case wasm::ValType::AnyRef:
           case wasm::ValType::Ref:
             MOZ_CRASH("impossible per above check");
+          case wasm::ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
         }
 
         current->add(conversion);
         call->initArg(i, conversion);
     }
 
     current->push(call);
     current->add(call);
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -6388,16 +6388,17 @@ ValidateGlobalVariable(JSContext* cx, co
             double d;
             if (!ToNumber(cx, v, &d)) {
                 return false;
             }
             val->emplace(d);
             return true;
           }
           case ValType::Ref:
+          case ValType::NullRef:
           case ValType::AnyRef: {
             MOZ_CRASH("not available in asm.js");
           }
         }
       }
     }
 
     MOZ_CRASH("unreachable");
--- a/js/src/wasm/WasmAST.h
+++ b/js/src/wasm/WasmAST.h
@@ -1782,25 +1782,21 @@ class AstExtraConversionOperator final :
     {}
 
     MiscOp op() const { return op_; }
     AstExpr* operand() const { return operand_; }
 };
 
 class AstRefNull final : public AstExpr
 {
-    AstValType refType_;
   public:
     static const AstExprKind Kind = AstExprKind::RefNull;
-    explicit AstRefNull(AstValType refType)
-      : AstExpr(Kind, ExprType::Limit), refType_(refType)
+    AstRefNull()
+      : AstExpr(Kind, ExprType::Limit)
     {}
-    AstValType& baseType() {
-        return refType_;
-    }
 };
 
 // This is an artificial AST node which can fill operand slots in an AST
 // constructed from parsing or decoding stack-machine code that doesn't have
 // an inherent AST structure.
 class AstPop final : public AstExpr
 {
   public:
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1082,16 +1082,17 @@ BaseLocalIter::settle()
           case ValType::I64:
           case ValType::F32:
           case ValType::F64:
           case ValType::Ref:
           case ValType::AnyRef:
             mirType_ = ToMIRType(locals_[index_]);
             frameOffset_ = pushLocal(MIRTypeToSize(mirType_));
             break;
+          case ValType::NullRef:
           default:
             MOZ_CRASH("Compiler bug: Unexpected local type");
         }
         return;
     }
 
     done_ = true;
 }
@@ -1159,17 +1160,16 @@ class BaseStackFrame
     // risk; if it is too small we spend too much time adjusting the stack
     // pointer.
     //
     // Good values for ChunkSize are the subject of future empirical analysis;
     // eight words is just an educated guess.
 
     static constexpr uint32_t ChunkSize = 8 * sizeof(void*);
     static constexpr uint32_t InitialChunk = ChunkSize;
-    static constexpr uint32_t ChunkCutoff = ChunkSize + InitialChunk;
 #endif
 
     MacroAssembler& masm;
 
     // Size of local area in bytes (stable after beginFunction).
     uint32_t localSize_;
 
     // Low byte offset of local area for true locals (not parameters).
@@ -1478,16 +1478,22 @@ class BaseStackFrame
         return maxFramePushed_ <= 512 * 1024;
     }
 
     // The current height of the stack area, not necessarily zero-based.
     StackHeight stackHeight() const {
         return StackHeight(currentFramePushed());
     }
 
+    // The current height of the dynamic part of the stack area (ie, the backing
+    // store for the evaluation stack), zero-based.
+    uint32_t dynamicHeight() const {
+        return currentFramePushed() - localSize_;
+    }
+
     // Set the frame height.
     void setStackHeight(StackHeight amount) {
 #ifdef RABALDR_CHUNKY_STACK
         currentFramePushed_ = amount.height;
         masm.setFramePushed(framePushedForHeight(amount));
         CHUNKY_INVARIANT();
 #else
         masm.setFramePushed(amount.height);
@@ -1574,16 +1580,18 @@ class BaseStackFrame
             masm.freeStack(bytes);
 #endif
         }
     }
 
     // Before branching to an outer control label, pop the execution stack to
     // the level expected by that region, but do not update masm.framePushed()
     // as that will happen as compilation leaves the block.
+    //
+    // Note these operate directly on the stack pointer register.
 
     void popStackBeforeBranch(StackHeight destStackHeight) {
         uint32_t framePushedHere = masm.framePushed();
         uint32_t framePushedThere = framePushedForHeight(destStackHeight);
         if (framePushedHere > framePushedThere) {
             masm.addToStackPtr(Imm32(framePushedHere - framePushedThere));
         }
     }
@@ -1592,32 +1600,36 @@ class BaseStackFrame
         uint32_t framePushedHere = masm.framePushed();
         uint32_t framePushedThere = framePushedForHeight(destStackHeight);
         return framePushedHere > framePushedThere;
     }
 
     // Before exiting a nested control region, pop the execution stack
     // to the level expected by the nesting region, and free the
     // stack.
+    //
+    // Note this operates on the stack height, which is not the same as the
+    // stack pointer on chunky-stack systems; the stack pointer may or may not
+    // change on such systems.
 
     void popStackOnBlockExit(StackHeight destStackHeight, bool deadCode) {
-        uint32_t framePushedHere = masm.framePushed();
-        uint32_t framePushedThere = framePushedForHeight(destStackHeight);
-        if (framePushedHere > framePushedThere) {
+        uint32_t stackHeightHere = currentFramePushed();
+        uint32_t stackHeightThere = destStackHeight.height;
+        if (stackHeightHere > stackHeightThere) {
 #ifdef RABALDR_CHUNKY_STACK
             if (deadCode) {
                 setStackHeight(destStackHeight);
             } else {
-                popChunkyBytes(framePushedHere - framePushedThere);
+                popChunkyBytes(stackHeightHere - stackHeightThere);
             }
 #else
             if (deadCode) {
-                masm.setFramePushed(framePushedThere);
+                masm.setFramePushed(stackHeightThere);
             } else {
-                masm.freeStack(framePushedHere - framePushedThere);
+                masm.freeStack(stackHeightHere - stackHeightThere);
             }
 #endif
         }
     }
 
     void loadStackI32(int32_t offset, RegI32 dest) {
         masm.load32(Address(sp_, stackOffset(offset)), dest);
     }
@@ -2189,32 +2201,34 @@ class BaseCompiler final : public BaseCo
         switch (type.code()) {
           case ExprType::I32:
             needI32(joinRegI32_);
             break;
           case ExprType::I64:
             needI64(joinRegI64_);
             break;
           case ExprType::AnyRef:
+          case ExprType::NullRef:
           case ExprType::Ref:
             needRef(joinRegPtr_);
             break;
           default:;
         }
     }
 
     void maybeUnreserveJoinRegI(ExprType type) {
         switch (type.code()) {
           case ExprType::I32:
             freeI32(joinRegI32_);
             break;
           case ExprType::I64:
             freeI64(joinRegI64_);
             break;
           case ExprType::AnyRef:
+          case ExprType::NullRef:
           case ExprType::Ref:
             freeRef(joinRegPtr_);
             break;
           default:;
         }
     }
 
     void maybeReserveJoinReg(ExprType type) {
@@ -2227,16 +2241,17 @@ class BaseCompiler final : public BaseCo
             break;
           case ExprType::F32:
             needF32(joinRegF32_);
             break;
           case ExprType::F64:
             needF64(joinRegF64_);
             break;
           case ExprType::Ref:
+          case ExprType::NullRef:
           case ExprType::AnyRef:
             needRef(joinRegPtr_);
             break;
           default:
             break;
         }
     }
 
@@ -2250,16 +2265,17 @@ class BaseCompiler final : public BaseCo
             break;
           case ExprType::F32:
             freeF32(joinRegF32_);
             break;
           case ExprType::F64:
             freeF64(joinRegF64_);
             break;
           case ExprType::Ref:
+          case ExprType::NullRef:
           case ExprType::AnyRef:
             freeRef(joinRegPtr_);
             break;
           default:
             break;
         }
     }
 
@@ -3217,16 +3233,17 @@ class BaseCompiler final : public BaseCo
           }
           case ExprType::F32: {
             DebugOnly<Stk::Kind> k(stk_.back().kind());
             MOZ_ASSERT(k == Stk::RegisterF32 || k == Stk::ConstF32 || k == Stk::MemF32 ||
                        k == Stk::LocalF32);
             return Some(AnyReg(popF32(joinRegF32_)));
           }
           case ExprType::Ref:
+          case ExprType::NullRef:
           case ExprType::AnyRef: {
             DebugOnly<Stk::Kind> k(stk_.back().kind());
             MOZ_ASSERT(k == Stk::RegisterRef || k == Stk::ConstRef || k == Stk::MemRef ||
                        k == Stk::LocalRef);
             return Some(AnyReg(popRef(joinRegPtr_)));
           }
           default: {
             MOZ_CRASH("Compiler bug: unexpected expression type");
@@ -3254,16 +3271,17 @@ class BaseCompiler final : public BaseCo
             MOZ_ASSERT(isAvailableF32(joinRegF32_));
             needF32(joinRegF32_);
             return Some(AnyReg(joinRegF32_));
           case ExprType::F64:
             MOZ_ASSERT(isAvailableF64(joinRegF64_));
             needF64(joinRegF64_);
             return Some(AnyReg(joinRegF64_));
           case ExprType::Ref:
+          case ExprType::NullRef:
           case ExprType::AnyRef:
             MOZ_ASSERT(isAvailableRef(joinRegPtr_));
             needRef(joinRegPtr_);
             return Some(AnyReg(joinRegPtr_));
           case ExprType::Void:
             return Nothing();
           default:
             MOZ_CRASH("Compiler bug: unexpected type");
@@ -3405,16 +3423,32 @@ class BaseCompiler final : public BaseCo
               case Stk::RegisterRef:
                 check.addKnownRef(item.refReg());
                 break;
               default:
                 break;
             }
         }
     }
+
+    void assertStackInvariants() const {
+        size_t size = 0;
+        for (const Stk& v : stk_) {
+            switch (v.kind()) {
+              case Stk::MemRef: size += BaseStackFrame::StackSizeOfPtr;    break;
+              case Stk::MemI32: size += BaseStackFrame::StackSizeOfPtr;    break;
+              case Stk::MemI64: size += BaseStackFrame::StackSizeOfInt64;  break;
+              case Stk::MemF64: size += BaseStackFrame::StackSizeOfDouble; break;
+              case Stk::MemF32: size += BaseStackFrame::StackSizeOfFloat;  break;
+              default:          MOZ_ASSERT(!v.isMem());                    break;
+            }
+        }
+        MOZ_ASSERT(size == fr.dynamicHeight());
+    }
+
 #endif
 
     ////////////////////////////////////////////////////////////
     //
     // Control stack
 
     void initControl(Control& item)
     {
@@ -3534,16 +3568,17 @@ class BaseCompiler final : public BaseCo
             break;
           case ExprType::F32:
             masm.storeFloat32(RegF32(ReturnFloat32Reg), resultsAddress);
             break;
           case ExprType::Ref:
           case ExprType::AnyRef:
             masm.storePtr(RegPtr(ReturnReg), resultsAddress);
             break;
+          case ExprType::NullRef:
           default:
             MOZ_CRASH("Function return type");
         }
     }
 
     void restoreResult() {
         MOZ_ASSERT(env_.debugEnabled());
         size_t debugFrameOffset = masm.framePushed() - DebugFrame::offsetOfFrame();
@@ -3562,16 +3597,17 @@ class BaseCompiler final : public BaseCo
             break;
           case ExprType::F32:
             masm.loadFloat32(resultsAddress, RegF32(ReturnFloat32Reg));
             break;
           case ExprType::Ref:
           case ExprType::AnyRef:
             masm.loadPtr(resultsAddress, RegPtr(ReturnReg));
             break;
+          case ExprType::NullRef:
           default:
             MOZ_CRASH("Function return type");
         }
     }
 
     bool endFunction() {
         // Always branch to returnLabel_.
         masm.breakpoint();
@@ -3852,16 +3888,18 @@ class BaseCompiler final : public BaseCo
                 ScratchPtr scratch(*this);
                 loadRef(arg, scratch);
                 masm.storePtr(scratch, Address(masm.getStackPointer(), argLoc.offsetFromArgBase()));
             } else {
                 loadRef(arg, RegPtr(argLoc.gpr()));
             }
             break;
           }
+          case ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
           default:
             MOZ_CRASH("Function argument type");
         }
     }
 
     void callDefinition(uint32_t funcIndex, const FunctionCall& call)
     {
         CallSiteDesc desc(call.lineOrBytecode, CallSiteDesc::Func);
@@ -7414,17 +7452,17 @@ BaseCompiler::sniffConditionalControlCmp
     // reserved join register and the lhs and rhs operands require six, but we
     // only have five.
     if (operandType == ValType::I64) {
         return false;
     }
 #endif
 
     // No optimization for pointer compares yet.
-    if (operandType.isRefOrAnyRef()) {
+    if (operandType.isReference()) {
         return false;
     }
 
     OpBytes op;
     iter_.peekOp(&op);
     switch (op.b0) {
       case uint16_t(Op::BrIf):
       case uint16_t(Op::If):
@@ -8034,16 +8072,17 @@ BaseCompiler::doReturn(ExprType type, bo
       }
       case ExprType::F32: {
         RegF32 rv = popF32(RegF32(ReturnFloat32Reg));
         returnCleanup(popStack);
         freeF32(rv);
         break;
       }
       case ExprType::Ref:
+      case ExprType::NullRef:
       case ExprType::AnyRef: {
         RegPtr rv = popRef(RegPtr(ReturnReg));
         returnCleanup(popStack);
         freeRef(rv);
         break;
       }
       default: {
         MOZ_CRASH("Function return type");
@@ -8113,16 +8152,18 @@ BaseCompiler::pushReturnedIfNonVoid(cons
         break;
       }
       case ExprType::Ref:
       case ExprType::AnyRef: {
         RegPtr rv = captureReturnedRef();
         pushRef(rv);
         break;
       }
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       default:
         MOZ_CRASH("Function return type");
     }
 }
 
 // For now, always sync() at the beginning of the call to easily save live
 // values.
 //
@@ -8459,16 +8500,17 @@ BaseCompiler::emitGetLocal()
         break;
       case ValType::F32:
         pushLocalF32(slot);
         break;
       case ValType::Ref:
       case ValType::AnyRef:
         pushLocalRef(slot);
         break;
+      case ValType::NullRef:
       default:
         MOZ_CRASH("Local variable type");
     }
 
     return true;
 }
 
 template<bool isSetLocal>
@@ -8532,16 +8574,17 @@ BaseCompiler::emitSetOrTeeLocal(uint32_t
         fr.storeLocalPtr(rv, localFromSlot(slot, MIRType::Pointer));
         if (isSetLocal) {
             freeRef(rv);
         } else {
             pushRef(rv);
         }
         break;
       }
+      case ValType::NullRef:
       default:
         MOZ_CRASH("Local variable type");
     }
 
     return true;
 }
 
 bool
@@ -8591,16 +8634,17 @@ BaseCompiler::emitGetGlobal()
             break;
           case ValType::F32:
             pushF32(value.f32());
             break;
           case ValType::F64:
             pushF64(value.f64());
             break;
           case ValType::Ref:
+          case ValType::NullRef:
           case ValType::AnyRef:
             pushRef(intptr_t(value.ptr()));
             break;
           default:
             MOZ_CRASH("Global constant type");
         }
         return true;
     }
@@ -8637,16 +8681,18 @@ BaseCompiler::emitGetGlobal()
       case ValType::Ref:
       case ValType::AnyRef: {
         RegPtr rv = needRef();
         ScratchI32 tmp(*this);
         masm.loadPtr(addressOfGlobalVar(global, tmp), rv);
         pushRef(rv);
         break;
       }
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       default:
         MOZ_CRASH("Global variable type");
         break;
     }
     return true;
 }
 
 bool
@@ -8701,16 +8747,18 @@ BaseCompiler::emitSetGlobal()
             ScratchI32 tmp(*this);
             masm.computeEffectiveAddress(addressOfGlobalVar(global, tmp), valueAddr);
         }
         RegPtr rv = popRef();
         emitBarrieredStore(Nothing(), valueAddr, rv); // Consumes valueAddr
         freeRef(rv);
         break;
       }
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       default:
         MOZ_CRASH("Global variable type");
         break;
     }
     return true;
 }
 
 // Bounds check elimination.
@@ -9099,16 +9147,17 @@ BaseCompiler::emitSelect()
         emitBranchPerform(&b);
         moveF64(rs, r);
         masm.bind(&done);
         freeF64(rs);
         pushF64(r);
         break;
       }
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::AnyRef: {
         RegPtr r, rs;
         pop2xRef(&r, &rs);
         emitBranchPerform(&b);
         moveRef(rs, r);
         masm.bind(&done);
         freeRef(rs);
         pushRef(r);
@@ -9301,18 +9350,17 @@ BaseCompiler::emitCurrentMemory()
     // infallible
     emitInstanceCall(lineOrBytecode, SigP_, ExprType::I32, SymbolicAddress::CurrentMemory);
     return true;
 }
 
 bool
 BaseCompiler::emitRefNull()
 {
-    ValType type;
-    if (!iter_.readRefNull(&type)) {
+    if (!iter_.readRefNull()) {
         return false;
     }
 
     if (deadCode_) {
         return true;
     }
 
     pushRef(NULLREF_VALUE);
@@ -10010,16 +10058,18 @@ BaseCompiler::emitStructNew()
             popRef(rp);                 // Restore rp
             if (!structType.isInline_) {
                 masm.loadPtr(Address(rp, OutlineTypedObject::offsetOfData()), rdata);
             }
 
             masm.bind(&skipBarrier);
             break;
           }
+          case ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
           default: {
             MOZ_CRASH("Unexpected field type");
           }
         }
     }
 
     if (!structType.isInline_) {
         freeRef(rdata);
@@ -10085,18 +10135,21 @@ BaseCompiler::emitStructGet()
       }
       case ValType::Ref:
       case ValType::AnyRef: {
           RegPtr r = needRef();
           masm.loadPtr(Address(rp, offs), r);
           pushRef(r);
           break;
       }
+      case ValType::NullRef: {
+        MOZ_CRASH("NullRef not expressible");
+      }
       default: {
-          MOZ_CRASH("Unexpected field type");
+        MOZ_CRASH("Unexpected field type");
       }
     }
 
     freeRef(rp);
 
     return true;
 }
 
@@ -10120,17 +10173,17 @@ BaseCompiler::emitStructSet()
     RegI64 rl;
     RegF32 rf;
     RegF64 rd;
     RegPtr rr;
 
     // Reserve this register early if we will need it so that it is not taken by
     // rr or rp.
     RegPtr valueAddr;
-    if (structType.fields_[fieldIndex].type.isRefOrAnyRef()) {
+    if (structType.fields_[fieldIndex].type.isReference()) {
         valueAddr = RegPtr(PreBarrierReg);
         needRef(valueAddr);
     }
 
     switch (structType.fields_[fieldIndex].type.code()) {
       case ValType::I32:
         ri = popI32();
         break;
@@ -10142,16 +10195,18 @@ BaseCompiler::emitStructSet()
         break;
       case ValType::F64:
         rd = popF64();
         break;
       case ValType::Ref:
       case ValType::AnyRef:
         rr = popRef();
         break;
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       default:
         MOZ_CRASH("Unexpected field type");
     }
 
     RegPtr rp = popRef();
 
     Label ok;
     masm.branchTestPtr(Assembler::NonZero, rp, rp, &ok);
@@ -10180,21 +10235,25 @@ BaseCompiler::emitStructSet()
         break;
       }
       case ValType::F64: {
         masm.storeDouble(rd, Address(rp, offs));
         freeF64(rd);
         break;
       }
       case ValType::Ref:
-      case ValType::AnyRef:
+      case ValType::AnyRef: {
         masm.computeEffectiveAddress(Address(rp, offs), valueAddr);
         emitBarrieredStore(Some(rp), valueAddr, rr);// Consumes valueAddr
         freeRef(rr);
         break;
+      }
+      case ValType::NullRef: {
+        MOZ_CRASH("NullRef not expressible");
+      }
       default: {
         MOZ_CRASH("Unexpected field type");
       }
     }
 
     freeRef(rp);
 
     return true;
@@ -10252,16 +10311,17 @@ BaseCompiler::emitBody()
     uint32_t overhead = 0;
 
     for (;;) {
 
         Nothing unused_a, unused_b;
 
 #ifdef DEBUG
         performRegisterLeakCheck();
+        assertStackInvariants();
 #endif
 
 #define emitBinary(doEmit, type) \
         iter_.readBinary(type, &unused_a, &unused_b) && (deadCode_ || (doEmit(), true))
 
 #define emitUnary(doEmit, type) \
         iter_.readUnary(type, &unused_a) && (deadCode_ || (doEmit(), true))
 
--- a/js/src/wasm/WasmConstants.h
+++ b/js/src/wasm/WasmConstants.h
@@ -62,16 +62,19 @@ enum class TypeCode
     Func                                 = 0x60,  // SLEB128(-0x20)
 
     // Type constructor for structure types - unofficial
     Struct                               = 0x50,  // SLEB128(-0x30)
 
     // Special code representing the block signature ()->()
     BlockVoid                            = 0x40,  // SLEB128(-0x40)
 
+    // Type designator for null - unofficial, will not appear in the binary format
+    NullRef                              = 0x39,
+
     Limit                                = 0x80
 };
 
 enum class FuncTypeIdDescKind
 {
     None,
     Immediate,
     Global
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -135,16 +135,18 @@ Instance::callImport(JSContext* cx, uint
             break;
           case ValType::Ref:
           case ValType::AnyRef: {
             args[i].set(ObjectOrNullValue(*(JSObject**)&argv[i]));
             break;
           }
           case ValType::I64:
             MOZ_CRASH("unhandled type in callImport");
+          case ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
         }
     }
 
     FuncImportTls& import = funcImportTls(fi);
     RootedFunction importFun(cx, import.fun);
     MOZ_ASSERT(cx->realm() == importFun->realm());
 
     RootedValue fval(cx, ObjectValue(*importFun));
@@ -199,22 +201,23 @@ Instance::callImport(JSContext* cx, uint
     }
 
     const ValTypeVector& importArgs = fi.funcType().args();
 
     size_t numKnownArgs = Min(importArgs.length(), importFun->nargs());
     for (uint32_t i = 0; i < numKnownArgs; i++) {
         TypeSet::Type type = TypeSet::UnknownType();
         switch (importArgs[i].code()) {
-          case ValType::I32:    type = TypeSet::Int32Type(); break;
-          case ValType::F32:    type = TypeSet::DoubleType(); break;
-          case ValType::F64:    type = TypeSet::DoubleType(); break;
-          case ValType::Ref:    MOZ_CRASH("case guarded above");
-          case ValType::AnyRef: MOZ_CRASH("case guarded above");
-          case ValType::I64:    MOZ_CRASH("NYI");
+          case ValType::I32:     type = TypeSet::Int32Type(); break;
+          case ValType::F32:     type = TypeSet::DoubleType(); break;
+          case ValType::F64:     type = TypeSet::DoubleType(); break;
+          case ValType::Ref:     MOZ_CRASH("case guarded above");
+          case ValType::AnyRef:  MOZ_CRASH("case guarded above");
+          case ValType::I64:     MOZ_CRASH("NYI");
+          case ValType::NullRef: MOZ_CRASH("NullRef not expressible");
         }
         if (!TypeScript::ArgTypes(script, i)->hasType(type)) {
             return true;
         }
     }
 
     // These arguments will be filled with undefined at runtime by the
     // arguments rectifier: check that the imported function can handle
@@ -1088,17 +1091,17 @@ Instance::tracePrivate(JSTracer* trc)
     }
 
     for (const SharedTable& table : tables_) {
         table->trace(trc);
     }
 
     for (const GlobalDesc& global : code().metadata().globals) {
         // Indirect anyref global get traced by the owning WebAssembly.Global.
-        if (!global.type().isRefOrAnyRef() || global.isConstant() || global.isIndirect()) {
+        if (!global.type().isReference() || global.isConstant() || global.isIndirect()) {
             continue;
         }
         GCPtrObject* obj = (GCPtrObject*)(globalData() + global.offset());
         TraceNullableEdge(trc, obj, "wasm ref/anyref global");
     }
 
     TraceNullableEdge(trc, &memory_, "wasm buffer");
     structTypeDescrs_.trace(trc);
@@ -1199,16 +1202,19 @@ Instance::callExport(JSContext* cx, uint
             break;
           case ValType::Ref:
           case ValType::AnyRef: {
             if (!ToRef(cx, v, &exportArgs[i])) {
                 return false;
             }
             break;
           }
+          case ValType::NullRef: {
+            MOZ_CRASH("NullRef not expressible");
+          }
         }
     }
 
     {
         JitActivation activation(cx);
 
         void* callee;
         if (func.hasEagerStubs()) {
@@ -1256,16 +1262,18 @@ Instance::callExport(JSContext* cx, uint
       case ExprType::F64:
         args.rval().set(NumberValue(*(double*)retAddr));
         break;
       case ExprType::Ref:
       case ExprType::AnyRef:
         retObj = *(JSObject**)retAddr;
         expectsObject = true;
         break;
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     if (expectsObject) {
         args.rval().set(ObjectOrNullValue(retObj));
     } else if (retObj) {
         args.rval().set(ObjectValue(*retObj));
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -223,16 +223,18 @@ class FunctionCompiler
                 break;
               case ValType::F64:
                 ins = MConstant::New(alloc(), DoubleValue(0.0), MIRType::Double);
                 break;
               case ValType::Ref:
               case ValType::AnyRef:
                 MOZ_CRASH("ion support for ref/anyref value NYI");
                 break;
+              case ValType::NullRef:
+                MOZ_CRASH("NullRef not expressible");
             }
 
             curBlock_->add(ins);
             curBlock_->initSlot(info().localSlot(i), ins);
             if (!mirGen_.ensureBallast()) {
                 return false;
             }
         }
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -155,28 +155,29 @@ ToWebAssemblyValue(JSContext* cx, ValTyp
         if (!ToNumber(cx, v, &d)) {
             return false;
         }
         val.set(Val(d));
         return true;
       }
       case ValType::AnyRef: {
         if (v.isNull()) {
-            val.set(Val(nullptr));
+            val.set(Val(targetType, nullptr));
         } else {
             JSObject* obj = ToObject(cx, v);
             if (!obj) {
                 return false;
             }
             MOZ_ASSERT(obj->compartment() == cx->compartment());
-            val.set(Val(obj));
+            val.set(Val(targetType, obj));
         }
         return true;
       }
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::I64: {
         break;
       }
     }
     MOZ_CRASH("unexpected import value type, caller must guard");
 }
 
 static Value
@@ -190,16 +191,17 @@ ToJSValue(const Val& val)
       case ValType::F64:
         return DoubleValue(JS::CanonicalizeNaN(val.f64()));
       case ValType::AnyRef:
         if (!val.ptr()) {
             return NullValue();
         }
         return ObjectValue(*(JSObject*)val.ptr());
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::I64:
         break;
     }
     MOZ_CRASH("unexpected type when translating to a JS value");
 }
 
 // ============================================================================
 // Imports
@@ -331,17 +333,17 @@ GetImports(JSContext* cx,
                 globalObjs[index] = obj;
                 obj->val(&val);
             } else {
                 if (IsNumberType(global.type())) {
                     if (!v.isNumber()) {
                         return ThrowBadImportType(cx, import.field.get(), "Number");
                     }
                 } else {
-                    MOZ_ASSERT(global.type().isRefOrAnyRef());
+                    MOZ_ASSERT(global.type().isReference());
                     if (!v.isNull() && !v.isObject()) {
                         return ThrowBadImportType(cx, import.field.get(), "Object-or-null");
                     }
                 }
 
                 if (global.type() == ValType::I64) {
                     JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_LINK);
                     return false;
@@ -2429,16 +2431,18 @@ WasmGlobalObject::trace(JSTracer* trc, J
         break;
       case ValType::I32:
       case ValType::F32:
       case ValType::I64:
       case ValType::F64:
         break;
       case ValType::Ref:
         MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
     }
 }
 
 /* static */ void
 WasmGlobalObject::finalize(FreeOp*, JSObject* obj)
 {
     WasmGlobalObject* global = reinterpret_cast<WasmGlobalObject*>(obj);
     if (!global->isNewborn()) {
@@ -2478,16 +2482,19 @@ WasmGlobalObject::create(JSContext* cx, 
         cell->i64 = val.i64();
         break;
       case ValType::F32:
         cell->f32 = val.f32();
         break;
       case ValType::F64:
         cell->f64 = val.f64();
         break;
+      case ValType::NullRef:
+        MOZ_ASSERT(!cell->ptr, "value should be null already");
+        break;
       case ValType::AnyRef:
         MOZ_ASSERT(!cell->ptr, "no prebarriers needed");
         cell->ptr = val.ptr();
         if (cell->ptr) {
             JSObject::writeBarrierPost(&cell->ptr, nullptr, cell->ptr);
         }
         break;
       case ValType::Ref:
@@ -2571,18 +2578,19 @@ WasmGlobalObject::construct(JSContext* c
     RootedVal globalVal(cx);
 
     // Initialize with default value.
     switch (globalType.code()) {
       case ValType::I32:    globalVal = Val(uint32_t(0)); break;
       case ValType::I64:    globalVal = Val(uint64_t(0)); break;
       case ValType::F32:    globalVal = Val(float(0.0));  break;
       case ValType::F64:    globalVal = Val(double(0.0)); break;
-      case ValType::AnyRef: globalVal = Val(nullptr);     break;
+      case ValType::AnyRef: globalVal = Val(ValType::AnyRef, nullptr); break;
       case ValType::Ref:    MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:MOZ_CRASH("NullRef not expressible");
     }
 
     // Override with non-undefined value, if provided.
     RootedValue valueVal(cx, args.get(1));
     if (!valueVal.isUndefined()) {
         if (!ToWebAssemblyValue(cx, globalType, valueVal, &globalVal)) {
             return false;
         }
@@ -2613,16 +2621,18 @@ WasmGlobalObject::valueGetterImpl(JSCont
       case ValType::AnyRef:
         args.rval().set(args.thisv().toObject().as<WasmGlobalObject>().value(cx));
         return true;
       case ValType::I64:
         JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_TYPE);
         return false;
       case ValType::Ref:
         MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
     }
     MOZ_CRASH();
 }
 
 /* static */ bool
 WasmGlobalObject::valueGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -2671,16 +2681,18 @@ WasmGlobalObject::valueSetterImpl(JSCont
             JSObject::writeBarrierPost(&cell->ptr, prevPtr, cell->ptr);
         }
         break;
       }
       case ValType::I64:
         MOZ_CRASH("unexpected i64 when setting global's value");
       case ValType::Ref:
         MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
     }
 
     args.rval().setUndefined();
     return true;
 }
 
 /* static */ bool
 WasmGlobalObject::valueSetter(JSContext* cx, unsigned argc, Value* vp)
@@ -2721,18 +2733,19 @@ void
 WasmGlobalObject::val(MutableHandleVal outval) const
 {
     Cell* cell = this->cell();
     switch (type().code()) {
       case ValType::I32:    outval.set(Val(uint32_t(cell->i32))); return;
       case ValType::I64:    outval.set(Val(uint64_t(cell->i64))); return;
       case ValType::F32:    outval.set(Val(cell->f32));           return;
       case ValType::F64:    outval.set(Val(cell->f64));           return;
-      case ValType::AnyRef: outval.set(Val(cell->ptr));           return;
+      case ValType::AnyRef: outval.set(Val(ValType::AnyRef, cell->ptr)); return;
       case ValType::Ref:    MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:MOZ_CRASH("NullRef not expressible");
     }
     MOZ_CRASH("unexpected Global type");
 }
 
 Value
 WasmGlobalObject::value(JSContext* cx) const
 {
     // ToJSValue crashes on I64; this is desirable.
--- a/js/src/wasm/WasmOpIter.h
+++ b/js/src/wasm/WasmOpIter.h
@@ -48,35 +48,37 @@ class StackType
     bool isValidCode() {
         switch (UnpackTypeCodeType(tc_)) {
           case TypeCode::I32:
           case TypeCode::I64:
           case TypeCode::F32:
           case TypeCode::F64:
           case TypeCode::AnyRef:
           case TypeCode::Ref:
+          case TypeCode::NullRef:
           case TypeCode::Limit:
             return true;
           default:
             return false;
         }
     }
 #endif
 
   public:
     enum Code {
-        I32    = uint8_t(ValType::I32),
-        I64    = uint8_t(ValType::I64),
-        F32    = uint8_t(ValType::F32),
-        F64    = uint8_t(ValType::F64),
-
-        AnyRef = uint8_t(ValType::AnyRef),
-        Ref    = uint8_t(ValType::Ref),
-
-        Any    = uint8_t(TypeCode::Limit),
+        I32     = uint8_t(ValType::I32),
+        I64     = uint8_t(ValType::I64),
+        F32     = uint8_t(ValType::F32),
+        F64     = uint8_t(ValType::F64),
+
+        AnyRef  = uint8_t(ValType::AnyRef),
+        Ref     = uint8_t(ValType::Ref),
+        NullRef = uint8_t(ValType::NullRef),
+
+        TVar    = uint8_t(TypeCode::Limit),
     };
 
     StackType() : tc_(InvalidPackedTypeCode()) {}
 
     MOZ_IMPLICIT StackType(Code c)
       : tc_(PackTypeCode(TypeCode(c)))
     {
         MOZ_ASSERT(isValidCode());
@@ -97,19 +99,19 @@ class StackType
     uint32_t refTypeIndex() const {
         return UnpackTypeCodeIndex(tc_);
     }
 
     bool isRef() const {
         return UnpackTypeCodeType(tc_) == TypeCode::Ref;
     }
 
-    bool isRefOrAnyRef() const {
+    bool isReference() const {
         TypeCode tc = UnpackTypeCodeType(tc_);
-        return tc == TypeCode::Ref || tc == TypeCode::AnyRef;
+        return tc == TypeCode::Ref || tc == TypeCode::AnyRef || tc == TypeCode::NullRef;
     }
 
     bool operator ==(const StackType& that) const {
         return tc_ == that.tc_;
     }
 
     bool operator !=(const StackType& that) const {
         return tc_ != that.tc_;
@@ -123,17 +125,17 @@ class StackType
     bool operator !=(Code that) const {
         return !(*this == that);
     }
 };
 
 static inline ValType
 NonAnyToValType(StackType type)
 {
-    MOZ_ASSERT(type != StackType::Any);
+    MOZ_ASSERT(type != StackType::TVar);
     return ValType(type.packed());
 }
 
 #ifdef DEBUG
 // Families of opcodes that share a signature and validation logic.
 enum class OpKind {
     Block,
     Loop,
@@ -290,17 +292,17 @@ class ControlStackEntry<Nothing>
 
 template <typename Value>
 class TypeAndValue
 {
     StackType type_;
     Value value_;
 
   public:
-    TypeAndValue() : type_(StackType::Any), value_() {}
+    TypeAndValue() : type_(StackType::TVar), value_() {}
     explicit TypeAndValue(StackType type)
       : type_(type), value_()
     {}
     explicit TypeAndValue(ValType type)
       : type_(StackType(type)), value_()
     {}
     TypeAndValue(StackType type, Value value)
       : type_(type), value_(value)
@@ -324,17 +326,17 @@ class TypeAndValue
 
 // Specialization for when there is no additional data needed.
 template <>
 class TypeAndValue<Nothing>
 {
     StackType type_;
 
   public:
-    TypeAndValue() : type_(StackType::Any) {}
+    TypeAndValue() : type_(StackType::TVar) {}
     explicit TypeAndValue(StackType type) : type_(type) {}
     explicit TypeAndValue(ValType type) : type_(StackType(type)) {}
     TypeAndValue(StackType type, Nothing value) : type_(type) {}
     TypeAndValue(ValType type, Nothing value) : type_(StackType(type)) {}
 
     StackType type() const { return type_; }
     StackType& typeRef() { return type_; }
     Nothing value() const { return Nothing(); }
@@ -434,19 +436,16 @@ class MOZ_STACK_CLASS OpIter : private P
         valueStack_.infallibleAppend(tv);
     }
 
     void afterUnconditionalBranch() {
         valueStack_.shrinkTo(controlStack_.back().valueStackStart());
         controlStack_.back().setPolymorphicBase();
     }
 
-    inline bool IsPrefixOf(StackType a, StackType b);
-    inline bool IsSubtypeOf(StackType one, StackType two);
-    inline bool Unify(StackType observed, StackType expected, StackType* result);
     inline bool Join(StackType one, StackType two, StackType* result);
 
   public:
     typedef Vector<Value, 8, SystemAllocPolicy> ValueVector;
 
 #ifdef DEBUG
     explicit OpIter(const ModuleEnvironment& env, Decoder& decoder,
                     ExclusiveDeferredValidationState& dvs)
@@ -539,17 +538,17 @@ class MOZ_STACK_CLASS OpIter : private P
     MOZ_MUST_USE bool readTeeLocal(const ValTypeVector& locals, uint32_t* id, Value* value);
     MOZ_MUST_USE bool readGetGlobal(uint32_t* id);
     MOZ_MUST_USE bool readSetGlobal(uint32_t* id, Value* value);
     MOZ_MUST_USE bool readTeeGlobal(uint32_t* id, Value* value);
     MOZ_MUST_USE bool readI32Const(int32_t* i32);
     MOZ_MUST_USE bool readI64Const(int64_t* i64);
     MOZ_MUST_USE bool readF32Const(float* f32);
     MOZ_MUST_USE bool readF64Const(double* f64);
-    MOZ_MUST_USE bool readRefNull(ValType* type);
+    MOZ_MUST_USE bool readRefNull();
     MOZ_MUST_USE bool readCall(uint32_t* calleeIndex, ValueVector* argValues);
     MOZ_MUST_USE bool readCallIndirect(uint32_t* funcTypeIndex, uint32_t* tableIndex, Value* callee,
                                        ValueVector* argValues);
     MOZ_MUST_USE bool readOldCallDirect(uint32_t numFuncImports, uint32_t* funcIndex,
                                         ValueVector* argValues);
     MOZ_MUST_USE bool readOldCallIndirect(uint32_t* funcTypeIndex, Value* callee, ValueVector* argValues);
     MOZ_MUST_USE bool readWake(LinearMemoryAddress<Value>* addr, Value* count);
     MOZ_MUST_USE bool readWait(LinearMemoryAddress<Value>* addr,
@@ -626,86 +625,40 @@ class MOZ_STACK_CLASS OpIter : private P
     // end of the function body.
     bool controlStackEmpty() const {
         return controlStack_.empty();
     }
 };
 
 template <typename Policy>
 inline bool
-OpIter<Policy>::IsPrefixOf(StackType a, StackType b)
-{
-    const StructType& other = env_.types[a.refTypeIndex()].structType();
-    return env_.types[b.refTypeIndex()].structType().hasPrefix(other);
-}
-
-template <typename Policy>
-inline bool
-OpIter<Policy>::IsSubtypeOf(StackType one, StackType two)
-{
-    MOZ_ASSERT(one.isRefOrAnyRef());
-    MOZ_ASSERT(two.isRefOrAnyRef());
-    return one == two || two == StackType::AnyRef || (one.isRef() && IsPrefixOf(two, one));
-}
-
-template <typename Policy>
-inline bool
-OpIter<Policy>::Unify(StackType observed, StackType expected, StackType* result)
-{
-    if (MOZ_LIKELY(observed == expected)) {
-        *result = observed;
-        return true;
-    }
-
-    if (observed == StackType::Any) {
-        *result = expected;
-        return true;
-    }
-
-    if (expected == StackType::Any) {
-        *result = observed;
-        return true;
-    }
-
-    if (env_.gcTypesEnabled() == HasGcTypes::True && observed.isRefOrAnyRef() &&
-        expected.isRefOrAnyRef() && IsSubtypeOf(observed, expected))
-    {
-        *result = expected;
-        return true;
-    }
-
-    return false;
-}
-
-template <typename Policy>
-inline bool
 OpIter<Policy>::Join(StackType one, StackType two, StackType* result)
 {
     if (MOZ_LIKELY(one == two)) {
         *result = one;
         return true;
     }
 
-    if (one == StackType::Any) {
+    if (one == StackType::TVar) {
         *result = two;
         return true;
     }
 
-    if (two == StackType::Any) {
+    if (two == StackType::TVar) {
         *result = one;
         return true;
     }
 
-    if (env_.gcTypesEnabled() == HasGcTypes::True && one.isRefOrAnyRef() && two.isRefOrAnyRef()) {
-        if (IsSubtypeOf(two, one)) {
+    if (env_.gcTypesEnabled() == HasGcTypes::True && one.isReference() && two.isReference()) {
+        if (env_.isRefSubtypeOf(NonAnyToValType(two), NonAnyToValType(one))) {
             *result = one;
             return true;
         }
 
-        if (IsSubtypeOf(one, two)) {
+        if (env_.isRefSubtypeOf(NonAnyToValType(one), NonAnyToValType(two))) {
             *result = two;
             return true;
         }
 
         // No subtyping relations between the two types.
         *result = StackType::AnyRef;
         return true;
     }
@@ -741,29 +694,29 @@ OpIter<Policy>::fail_ctx(const char* fmt
     if (!error) {
         return false;
     }
     return fail(error.get());
 }
 
 // This function pops exactly one value from the stack, yielding Any types in
 // various cases and therefore making it the caller's responsibility to do the
-// right thing for StackType::Any. Prefer (pop|top)WithType.
+// right thing for StackType::TVar. Prefer (pop|top)WithType.
 template <typename Policy>
 inline bool
 OpIter<Policy>::popAnyType(StackType* type, Value* value)
 {
     ControlStackEntry<ControlItem>& block = controlStack_.back();
 
     MOZ_ASSERT(valueStack_.length() >= block.valueStackStart());
     if (MOZ_UNLIKELY(valueStack_.length() == block.valueStackStart())) {
         // If the base of this block's stack is polymorphic, then we can pop a
         // dummy value of any type; it won't be used since we're in unreachable code.
         if (block.polymorphicBase()) {
-            *type = StackType::Any;
+            *type = StackType::TVar;
             *value = Value();
 
             // Maintain the invariant that, after a pop, there is always memory
             // reserved to push a value infallibly.
             return valueStack_.reserve(valueStack_.length() + 1);
         }
 
         if (valueStack_.empty()) {
@@ -817,19 +770,26 @@ OpIter<Policy>::popWithType(StackType ex
         if (valueStack_.empty()) {
             return fail("popping value from empty stack");
         }
         return fail("popping value from outside block");
     }
 
     TypeAndValue<Value> tv = valueStack_.popCopy();
 
-    StackType _;
-    if (MOZ_UNLIKELY(!Unify(tv.type(), expectedType, &_))) {
-        return typeMismatch(tv.type(), expectedType);
+    StackType observedType = tv.type();
+    if (!(MOZ_LIKELY(observedType == expectedType) ||
+          observedType == StackType::TVar ||
+          expectedType == StackType::TVar ||
+          (env_.gcTypesEnabled() == HasGcTypes::True &&
+           observedType.isReference() && expectedType.isReference() &&
+           env_.isRefSubtypeOf(NonAnyToValType(observedType),
+                               NonAnyToValType(expectedType)))))
+    {
+        return typeMismatch(observedType, expectedType);
     }
 
     *value = tv.value();
     return true;
 }
 
 // This function pops as many types from the stack as determined by the given
 // signature. Currently, all signatures are limited to 0 or 1 types, with
@@ -873,18 +833,29 @@ OpIter<Policy>::topWithType(ValType expe
         if (valueStack_.empty()) {
             return fail("reading value from empty stack");
         }
         return fail("reading value from outside block");
     }
 
     TypeAndValue<Value>& tv = valueStack_.back();
 
-    if (MOZ_UNLIKELY(!Unify(tv.type(), StackType(expectedType), &tv.typeRef()))) {
-        return typeMismatch(tv.type(), StackType(expectedType));
+    StackType observed = tv.type();
+    StackType expected = StackType(expectedType);
+
+    if (!MOZ_UNLIKELY(observed == expected)) {
+        if (observed == StackType::TVar ||
+            (env_.gcTypesEnabled() == HasGcTypes::True &&
+             observed.isReference() && expected.isReference() &&
+             env_.isRefSubtypeOf(NonAnyToValType(observed), expectedType)))
+        {
+            tv.typeRef() = expected;
+        } else {
+            return typeMismatch(observed, expected);
+        }
     }
 
     *value = tv.value();
     return true;
 }
 
 template <typename Policy>
 inline bool
@@ -1702,24 +1673,21 @@ OpIter<Policy>::readF64Const(double* f64
     MOZ_ASSERT(Classify(op_) == OpKind::F64);
 
     return readFixedF64(f64) &&
            push(ValType::F64);
 }
 
 template <typename Policy>
 inline bool
-OpIter<Policy>::readRefNull(ValType* type)
+OpIter<Policy>::readRefNull()
 {
     MOZ_ASSERT(Classify(op_) == OpKind::RefNull);
-    if (!readReferenceType(type, "ref.null")) {
-        return false;
-    }
-
-    return push(StackType(*type));
+
+    return push(StackType(ValType::NullRef));
 }
 
 template <typename Policy>
 inline bool
 OpIter<Policy>::readReferenceType(ValType* type, const char* context)
 {
     uint8_t code;
     uint32_t refTypeIndex;
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -175,16 +175,18 @@ StoreABIReturn(MacroAssembler& masm, con
       case ExprType::F64:
         masm.canonicalizeDouble(ReturnDoubleReg);
         masm.storeDouble(ReturnDoubleReg, Address(argv, 0));
         break;
       case ExprType::Ref:
       case ExprType::AnyRef:
         masm.storePtr(ReturnReg, Address(argv, 0));
         break;
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 }
 
 #if defined(JS_CODEGEN_ARM)
 // The ARM system ABI also includes d15 & s31 in the non volatile float registers.
 // Also exclude lr (a.k.a. r14) as we preserve it manually.
@@ -792,16 +794,18 @@ GenerateJitEntry(MacroAssembler& masm, s
       case ExprType::Ref:
         MOZ_CRASH("return ref in jitentry NYI");
         break;
       case ExprType::AnyRef:
         MOZ_CRASH("return anyref in jitentry NYI");
         break;
       case ExprType::I64:
         MOZ_CRASH("unexpected return type when calling from ion to wasm");
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     MOZ_ASSERT(masm.framePushed() == 0);
 #ifdef JS_CODEGEN_ARM64
     masm.loadPtr(Address(sp, 0), lr);
     masm.addToStackPtr(Imm32(8));
@@ -1004,16 +1008,18 @@ wasm::GenerateDirectCallFromJit(MacroAss
         break;
       case wasm::ExprType::F64:
         masm.canonicalizeDouble(ReturnDoubleReg);
         break;
       case wasm::ExprType::Ref:
       case wasm::ExprType::AnyRef:
       case wasm::ExprType::I64:
         MOZ_CRASH("unexpected return type when calling from ion to wasm");
+      case wasm::ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case wasm::ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     // Free args + frame descriptor.
     masm.leaveExitFrame(bytesNeeded + ExitFrameLayout::Size());
 
     // If we pushed it, free FramePointer.
@@ -1344,16 +1350,18 @@ GenerateImportInterpExit(MacroAssembler&
         masm.loadDouble(argv, ReturnDoubleReg);
         break;
       case ExprType::Ref:
       case ExprType::AnyRef:
         masm.call(SymbolicAddress::CallImport_Ref);
         masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
         masm.loadPtr(argv, ReturnReg);
         break;
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     // The native ABI preserves the TLS, heap and global registers since they
     // are non-volatile.
     MOZ_ASSERT(NonVolatileRegs.has(WasmTlsReg));
 #if defined(JS_CODEGEN_X64) || \
@@ -1517,16 +1525,18 @@ GenerateImportJitExit(MacroAssembler& ma
         masm.convertValueToDouble(JSReturnOperand, ReturnDoubleReg, &oolConvert);
         break;
       case ExprType::Ref:
         MOZ_CRASH("ref returned by import (jit exit) NYI");
         break;
       case ExprType::AnyRef:
         MOZ_CRASH("anyref returned by import (jit exit) NYI");
         break;
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     Label done;
     masm.bind(&done);
 
     GenerateJitExitEpilogue(masm, masm.framePushed(), offsets);
--- a/js/src/wasm/WasmTextToBinary.cpp
+++ b/js/src/wasm/WasmTextToBinary.cpp
@@ -3875,29 +3875,17 @@ ParseStructNarrow(WasmParseContext& c, b
 
     return new(c.lifo) AstStructNarrow(inputType, outputType, ptr);
 }
 #endif
 
 static AstExpr*
 ParseRefNull(WasmParseContext& c)
 {
-    WasmToken token;
-    AstValType vt;
-
-    if (!ParseValType(c, &vt)) {
-        return nullptr;
-    }
-
-    if (!vt.isRefType()) {
-        c.ts.generateError(token, "ref.null requires ref type", c.error);
-        return nullptr;
-    }
-
-    return new(c.lifo) AstRefNull(vt);
+    return new(c.lifo) AstRefNull();
 }
 
 static AstExpr*
 ParseExprBody(WasmParseContext& c, WasmToken token, bool inParens)
 {
     if (!CheckRecursionLimitDontReport(c.stackLimit)) {
         return nullptr;
     }
@@ -5777,17 +5765,17 @@ ResolveStructNarrow(Resolver& r, AstStru
 
     return ResolveExpr(r, s.ptr());
 }
 #endif
 
 static bool
 ResolveRefNull(Resolver& r, AstRefNull& s)
 {
-    return ResolveType(r, s.baseType());
+    return true;
 }
 
 static bool
 ResolveExpr(Resolver& r, AstExpr& expr)
 {
     switch (expr.kind()) {
       case AstExprKind::Nop:
       case AstExprKind::Pop:
@@ -6731,18 +6719,17 @@ EncodeStructNarrow(Encoder& e, AstStruct
     }
     return true;
 }
 #endif
 
 static bool
 EncodeRefNull(Encoder& e, AstRefNull& s)
 {
-    return e.writeOp(Op::RefNull) &&
-           e.writeValType(s.baseType().type());
+    return e.writeOp(Op::RefNull);
 }
 
 static bool
 EncodeExpr(Encoder& e, AstExpr& expr)
 {
     switch (expr.kind()) {
       case AstExprKind::Pop:
         return true;
--- a/js/src/wasm/WasmTypes.cpp
+++ b/js/src/wasm/WasmTypes.cpp
@@ -64,16 +64,17 @@ Val::Val(const LitVal& val)
 {
     type_ = val.type();
     switch (type_.code()) {
       case ValType::I32: u.i32_ = val.i32(); return;
       case ValType::F32: u.f32_ = val.f32(); return;
       case ValType::I64: u.i64_ = val.i64(); return;
       case ValType::F64: u.f64_ = val.f64(); return;
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::AnyRef: u.ptr_ = val.ptr(); return;
     }
     MOZ_CRASH();
 }
 
 void
 Val::writePayload(uint8_t* dst) const
 {
@@ -82,16 +83,17 @@ Val::writePayload(uint8_t* dst) const
       case ValType::F32:
         memcpy(dst, &u.i32_, sizeof(u.i32_));
         return;
       case ValType::I64:
       case ValType::F64:
         memcpy(dst, &u.i64_, sizeof(u.i64_));
         return;
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::AnyRef:
         MOZ_ASSERT(*(JSObject**)dst == nullptr, "should be null so no need for a pre-barrier");
         memcpy(dst, &u.ptr_, sizeof(JSObject*));
         // Either the written location is in the global data section in the
         // WasmInstanceObject, or the Cell of a WasmGlobalObject:
         // - WasmInstanceObjects are always tenured and u.ptr_ may point to a
         // nursery object, so we need a post-barrier since the global data of
         // an instance is effectively a field of the WasmInstanceObject.
@@ -103,17 +105,17 @@ Val::writePayload(uint8_t* dst) const
         return;
     }
     MOZ_CRASH("unexpected Val type");
 }
 
 void
 Val::trace(JSTracer* trc)
 {
-    if (type_.isValid() && type_.isRefOrAnyRef() && u.ptr_) {
+    if (type_.isValid() && type_.isReference() && u.ptr_) {
         TraceManuallyBarrieredEdge(trc, &u.ptr_, "wasm ref/anyref global");
     }
 }
 
 bool
 wasm::IsRoundingFunction(SymbolicAddress callee, jit::RoundingMode* mode)
 {
     switch (callee) {
@@ -195,16 +197,17 @@ IsImmediateType(ValType vt)
 {
     switch (vt.code()) {
       case ValType::I32:
       case ValType::I64:
       case ValType::F32:
       case ValType::F64:
       case ValType::AnyRef:
         return true;
+      case ValType::NullRef:
       case ValType::Ref:
         return false;
     }
     MOZ_CRASH("bad ValType");
 }
 
 static unsigned
 EncodeImmediateType(ValType vt)
@@ -216,16 +219,17 @@ EncodeImmediateType(ValType vt)
       case ValType::I64:
         return 1;
       case ValType::F32:
         return 2;
       case ValType::F64:
         return 3;
       case ValType::AnyRef:
         return 4;
+      case ValType::NullRef:
       case ValType::Ref:
         break;
     }
     MOZ_CRASH("bad ValType");
 }
 
 /* static */ bool
 FuncTypeIdDesc::isGlobal(const FuncType& funcType)
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -288,38 +288,40 @@ class ExprType
 #ifdef DEBUG
     bool isValidCode() {
         switch (UnpackTypeCodeType(tc_)) {
           case TypeCode::I32:
           case TypeCode::I64:
           case TypeCode::F32:
           case TypeCode::F64:
           case TypeCode::AnyRef:
+          case TypeCode::NullRef:
           case TypeCode::Ref:
           case TypeCode::BlockVoid:
           case TypeCode::Limit:
             return true;
           default:
             return false;
         }
     }
 #endif
 
   public:
     enum Code {
-        Void   = uint8_t(TypeCode::BlockVoid),
-
-        I32    = uint8_t(TypeCode::I32),
-        I64    = uint8_t(TypeCode::I64),
-        F32    = uint8_t(TypeCode::F32),
-        F64    = uint8_t(TypeCode::F64),
-        AnyRef = uint8_t(TypeCode::AnyRef),
-        Ref    = uint8_t(TypeCode::Ref),
-
-        Limit  = uint8_t(TypeCode::Limit)
+        Void    = uint8_t(TypeCode::BlockVoid),
+
+        I32     = uint8_t(TypeCode::I32),
+        I64     = uint8_t(TypeCode::I64),
+        F32     = uint8_t(TypeCode::F32),
+        F64     = uint8_t(TypeCode::F64),
+        AnyRef  = uint8_t(TypeCode::AnyRef),
+        NullRef = uint8_t(TypeCode::NullRef),
+        Ref     = uint8_t(TypeCode::Ref),
+
+        Limit   = uint8_t(TypeCode::Limit)
     };
 
     ExprType() : tc_() {}
 
     ExprType(const ExprType& that) : tc_(that.tc_) {}
 
     MOZ_IMPLICIT ExprType(Code c)
       : tc_(PackTypeCode(TypeCode(c)))
@@ -360,19 +362,19 @@ class ExprType
     bool isValid() const {
         return IsValid(tc_);
     }
 
     bool isRef() const {
         return UnpackTypeCodeType(tc_) == TypeCode::Ref;
     }
 
-    bool isRefOrAnyRef() const {
+    bool isReference() const {
         TypeCode tc = UnpackTypeCodeType(tc_);
-        return tc == TypeCode::Ref || tc == TypeCode::AnyRef;
+        return tc == TypeCode::Ref || tc == TypeCode::AnyRef || tc == TypeCode::NullRef;
     }
 
     bool operator ==(const ExprType& that) const {
         return tc_ == that.tc_;
     }
 
     bool operator !=(const ExprType& that) const {
         return tc_ != that.tc_;
@@ -398,33 +400,35 @@ class ValType
 #ifdef DEBUG
     bool isValidCode() {
         switch (UnpackTypeCodeType(tc_)) {
           case TypeCode::I32:
           case TypeCode::I64:
           case TypeCode::F32:
           case TypeCode::F64:
           case TypeCode::AnyRef:
+          case TypeCode::NullRef:
           case TypeCode::Ref:
             return true;
           default:
             return false;
         }
     }
 #endif
 
   public:
     enum Code {
-        I32    = uint8_t(TypeCode::I32),
-        I64    = uint8_t(TypeCode::I64),
-        F32    = uint8_t(TypeCode::F32),
-        F64    = uint8_t(TypeCode::F64),
-
-        AnyRef = uint8_t(TypeCode::AnyRef),
-        Ref    = uint8_t(TypeCode::Ref),
+        I32     = uint8_t(TypeCode::I32),
+        I64     = uint8_t(TypeCode::I64),
+        F32     = uint8_t(TypeCode::F32),
+        F64     = uint8_t(TypeCode::F64),
+
+        AnyRef  = uint8_t(TypeCode::AnyRef),
+        NullRef = uint8_t(TypeCode::NullRef),
+        Ref     = uint8_t(TypeCode::Ref),
     };
 
     ValType() : tc_(InvalidPackedTypeCode()) {}
 
     MOZ_IMPLICIT ValType(Code c)
       : tc_(PackTypeCode(TypeCode(c)))
     {
         MOZ_ASSERT(isValidCode());
@@ -471,19 +475,19 @@ class ValType
     bool isValid() const {
         return IsValid(tc_);
     }
 
     bool isRef() const {
         return UnpackTypeCodeType(tc_) == TypeCode::Ref;
     }
 
-    bool isRefOrAnyRef() const {
+    bool isReference() const {
         TypeCode tc = UnpackTypeCodeType(tc_);
-        return tc == TypeCode::Ref || tc == TypeCode::AnyRef;
+        return tc == TypeCode::Ref || tc == TypeCode::AnyRef || tc == TypeCode::NullRef;
     }
 
     bool operator ==(const ValType& that) const {
         return tc_ == that.tc_;
     }
 
     bool operator !=(const ValType& that) const {
         return tc_ != that.tc_;
@@ -509,40 +513,42 @@ SizeOf(ValType vt)
     switch (vt.code()) {
       case ValType::I32:
       case ValType::F32:
         return 4;
       case ValType::I64:
       case ValType::F64:
         return 8;
       case ValType::AnyRef:
+      case ValType::NullRef:
       case ValType::Ref:
         return sizeof(intptr_t);
     }
     MOZ_CRASH("Invalid ValType");
 }
 
 static inline jit::MIRType
 ToMIRType(ValType vt)
 {
     switch (vt.code()) {
-      case ValType::I32:    return jit::MIRType::Int32;
-      case ValType::I64:    return jit::MIRType::Int64;
-      case ValType::F32:    return jit::MIRType::Float32;
-      case ValType::F64:    return jit::MIRType::Double;
-      case ValType::Ref:    return jit::MIRType::Pointer;
-      case ValType::AnyRef: return jit::MIRType::Pointer;
+      case ValType::I32:     return jit::MIRType::Int32;
+      case ValType::I64:     return jit::MIRType::Int64;
+      case ValType::F32:     return jit::MIRType::Float32;
+      case ValType::F64:     return jit::MIRType::Double;
+      case ValType::Ref:     return jit::MIRType::Pointer;
+      case ValType::AnyRef:  return jit::MIRType::Pointer;
+      case ValType::NullRef: return jit::MIRType::Pointer;
     }
     MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("bad type");
 }
 
 static inline bool
 IsNumberType(ValType vt)
 {
-    return !vt.isRefOrAnyRef();
+    return !vt.isReference();
 }
 
 // ExprType utilities
 
 inline
 ExprType::ExprType(const ValType& t)
   : tc_(t.packed())
 {}
@@ -571,16 +577,17 @@ ToCString(ExprType type)
 {
     switch (type.code()) {
       case ExprType::Void:    return "void";
       case ExprType::I32:     return "i32";
       case ExprType::I64:     return "i64";
       case ExprType::F32:     return "f32";
       case ExprType::F64:     return "f64";
       case ExprType::AnyRef:  return "anyref";
+      case ExprType::NullRef: return "nullref";
       case ExprType::Ref:     return "ref";
       case ExprType::Limit:;
     }
     MOZ_CRASH("bad expression type");
 }
 
 static inline const char*
 ToCString(ValType type)
@@ -703,29 +710,30 @@ class LitVal
 
     explicit LitVal(uint32_t i32) : type_(ValType::I32) { u.i32_ = i32; }
     explicit LitVal(uint64_t i64) : type_(ValType::I64) { u.i64_ = i64; }
 
     explicit LitVal(float f32) : type_(ValType::F32) { u.f32_ = f32; }
     explicit LitVal(double f64) : type_(ValType::F64) { u.f64_ = f64; }
 
     explicit LitVal(ValType refType, JSObject* ptr) : type_(refType) {
-        MOZ_ASSERT(refType.isRefOrAnyRef());
+        MOZ_ASSERT(refType.isReference());
+        MOZ_ASSERT(refType != ValType::NullRef);
         MOZ_ASSERT(ptr == nullptr, "use Val for non-nullptr ref types to get tracing");
         u.ptr_ = ptr;
     }
 
     ValType type() const { return type_; }
     static constexpr size_t sizeofLargestValue() { return sizeof(u); }
 
     uint32_t i32() const { MOZ_ASSERT(type_ == ValType::I32); return u.i32_; }
     uint64_t i64() const { MOZ_ASSERT(type_ == ValType::I64); return u.i64_; }
     const float& f32() const { MOZ_ASSERT(type_ == ValType::F32); return u.f32_; }
     const double& f64() const { MOZ_ASSERT(type_ == ValType::F64); return u.f64_; }
-    JSObject* ptr() const { MOZ_ASSERT(type_.isRefOrAnyRef()); return u.ptr_; }
+    JSObject* ptr() const { MOZ_ASSERT(type_.isReference()); return u.ptr_; }
 };
 
 typedef Vector<LitVal, 0, SystemAllocPolicy> LitValVector;
 
 // A Val is a LitVal that can contain pointers to JSObjects, thanks to their
 // trace implementation. Since a Val is able to store a pointer to a JSObject,
 // it needs to be traced during compilation in case the pointee is moved.
 // The classic shorthands for Rooted things are defined after this class, for
@@ -735,17 +743,17 @@ class MOZ_NON_PARAM Val : public LitVal
 {
   public:
     Val() : LitVal() {}
     explicit Val(const LitVal& val);
     explicit Val(uint32_t i32)  : LitVal(i32) {}
     explicit Val(uint64_t i64)  : LitVal(i64) {}
     explicit Val(float f32)     : LitVal(f32) {}
     explicit Val(double f64)    : LitVal(f64) {}
-    explicit Val(JSObject* obj) : LitVal(ValType::AnyRef, nullptr) { u.ptr_ = obj; }
+    explicit Val(ValType type, JSObject* obj) : LitVal(type, nullptr) { u.ptr_ = obj; }
     void writePayload(uint8_t* dst) const;
     void trace(JSTracer* trc);
 };
 
 typedef Rooted<Val> RootedVal;
 typedef Handle<Val> HandleVal;
 typedef MutableHandle<Val> MutableHandleVal;
 
@@ -804,21 +812,21 @@ class FuncType
         for (ValType arg : args()) {
             if (arg == ValType::I64) {
                 return true;
             }
         }
         return false;
     }
     bool temporarilyUnsupportedAnyRef() const {
-        if (ret().isRefOrAnyRef()) {
+        if (ret().isReference()) {
             return true;
         }
         for (ValType arg : args()) {
-            if (arg.isRefOrAnyRef()) {
+            if (arg.isReference()) {
                 return true;
             }
         }
         return false;
     }
 #ifdef WASM_PRIVATE_REFTYPES
     bool exposesRef() const {
         for (const ValType& arg : args()) {
@@ -1053,31 +1061,33 @@ class GlobalDesc
     bool isWasm() const { return !isConstant() && u.var.isWasm_; }
 
   public:
     GlobalDesc() = default;
 
     explicit GlobalDesc(InitExpr initial, bool isMutable, ModuleKind kind = ModuleKind::Wasm)
       : kind_((isMutable || !initial.isVal()) ? GlobalKind::Variable : GlobalKind::Constant)
     {
+        MOZ_ASSERT(initial.type() != ValType::NullRef);
         if (isVariable()) {
             u.var.val.initial_ = initial;
             u.var.isMutable_ = isMutable;
             u.var.isWasm_ = kind == Wasm;
             u.var.isExport_ = false;
             u.var.offset_ = UINT32_MAX;
         } else {
             u.cst_ = initial.val();
         }
     }
 
     explicit GlobalDesc(ValType type, bool isMutable, uint32_t importIndex,
                         ModuleKind kind = ModuleKind::Wasm)
       : kind_(GlobalKind::Import)
     {
+        MOZ_ASSERT(type != ValType::NullRef);
         u.var.val.import.type_ = type;
         u.var.val.import.index_ = importIndex;
         u.var.isMutable_ = isMutable;
         u.var.isWasm_ = kind == Wasm;
         u.var.isExport_ = false;
         u.var.offset_ = UINT32_MAX;
     }
 
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -1000,18 +1000,17 @@ DecodeFunctionBodyExprs(const ModuleEnvi
             }
             CHECK(iter.readComparison(ValType::AnyRef, &nothing, &nothing));
             break;
           }
           case uint16_t(Op::RefNull): {
             if (env.gcTypesEnabled() == HasGcTypes::False) {
                 return iter.unrecognizedOpcode(&op);
             }
-            ValType unusedType;
-            CHECK(iter.readRefNull(&unusedType));
+            CHECK(iter.readRefNull());
             break;
           }
           case uint16_t(Op::RefIsNull): {
             if (env.gcTypesEnabled() == HasGcTypes::False) {
                 return iter.unrecognizedOpcode(&op);
             }
             CHECK(iter.readConversion(ValType::AnyRef, ValType::I32, &nothing));
             break;
@@ -1447,24 +1446,28 @@ DecodeGCFeatureOptInSection(Decoder& d, 
     if (!d.readVarU32(&version)) {
         return d.fail("expected gc feature version");
     }
 
     // For documentation of what's in the various versions, see
     // https://github.com/lars-t-hansen/moz-gc-experiments
     //
     // Version 1 is complete.
-    // Version 2 is in progress, currently backward compatible with version 1.
+    // Version 2 is in progress.
 
     switch (version) {
       case 1:
+        return d.fail("Wasm GC feature version 1 is no longer supported by this engine.\n"
+                      "The current version is 2, which is not backward-compatible:\n"
+                      " - The old encoding of ref.null is no longer accepted.");
       case 2:
         break;
       default:
-        return d.fail("unsupported version of the gc feature");
+        return d.fail("The specified Wasm GC feature version is unknown.\n"
+                      "The current version is 2.");
     }
 
     env->gcFeatureOptIn = HasGcTypes::True;
     return d.finishSection(*range, "gcfeatureoptin");
 }
 #endif
 
 static bool
@@ -1974,18 +1977,17 @@ DecodeMemorySection(Decoder& d, ModuleEn
             return false;
         }
     }
 
     return d.finishSection(*range, "memory");
 }
 
 static bool
-DecodeInitializerExpression(Decoder& d, HasGcTypes gcTypesEnabled, const GlobalDescVector& globals,
-                            ValType expected, uint32_t numTypes, InitExpr* init)
+DecodeInitializerExpression(Decoder& d, ModuleEnvironment* env, ValType expected, InitExpr* init)
 {
     OpBytes op;
     if (!d.readOp(&op)) {
         return d.fail("failed to read initializer type");
     }
 
     switch (op.b0) {
       case uint16_t(Op::I32Const): {
@@ -2016,48 +2018,48 @@ DecodeInitializerExpression(Decoder& d, 
         double f64;
         if (!d.readFixedF64(&f64)) {
             return d.fail("failed to read initializer f64 expression");
         }
         *init = InitExpr(LitVal(f64));
         break;
       }
       case uint16_t(Op::RefNull): {
-        if (gcTypesEnabled == HasGcTypes::False) {
+        if (env->gcTypesEnabled() == HasGcTypes::False) {
             return d.fail("unexpected initializer expression");
         }
-        uint8_t valType;
-        uint32_t refTypeIndex;
-        if (!d.readValType(&valType, &refTypeIndex)) {
-            return false;
+        if (!expected.isReference()) {
+            return d.fail("type mismatch: initializer type and expected type don't match");
         }
-        if (valType == uint8_t(ValType::AnyRef)) {
-            *init = InitExpr(LitVal(ValType::AnyRef, nullptr));
-        } else if (valType == uint8_t(ValType::Ref)) {
-            if (refTypeIndex >= numTypes) {
-                return d.fail("invalid reference type for ref.null");
-            }
-            *init = InitExpr(LitVal(ValType(ValType::Ref, refTypeIndex), nullptr));
-        } else {
-            return d.fail("expected anyref/ref as type for ref.null");
-        }
+        *init = InitExpr(LitVal(expected, nullptr));
         break;
       }
       case uint16_t(Op::GetGlobal): {
         uint32_t i;
+        const GlobalDescVector& globals = env->globals;
         if (!d.readVarU32(&i)) {
             return d.fail("failed to read get_global index in initializer expression");
         }
         if (i >= globals.length()) {
             return d.fail("global index out of range in initializer expression");
         }
         if (!globals[i].isImport() || globals[i].isMutable()) {
             return d.fail("initializer expression must reference a global immutable import");
         }
-        *init = InitExpr(i, globals[i].type());
+        if (expected.isReference()) {
+            if (!(env->gcTypesEnabled() == HasGcTypes::True &&
+                  globals[i].type().isReference() &&
+                  env->isRefSubtypeOf(globals[i].type(), expected)))
+            {
+                return d.fail("type mismatch: initializer type and expected type don't match");
+            }
+            *init = InitExpr(i, expected);
+        } else {
+            *init = InitExpr(i, globals[i].type());
+        }
         break;
       }
       default: {
         return d.fail("unexpected initializer expression");
       }
     }
 
     if (expected != init->type()) {
@@ -2101,19 +2103,17 @@ DecodeGlobalSection(Decoder& d, ModuleEn
     for (uint32_t i = 0; i < numDefs; i++) {
         ValType type;
         bool isMutable;
         if (!DecodeGlobalType(d, env->types, env->gcTypesEnabled(), &type, &isMutable)) {
             return false;
         }
 
         InitExpr initializer;
-        if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, type,
-                                         env->types.length(), &initializer))
-        {
+        if (!DecodeInitializerExpression(d, env, type, &initializer)) {
             return false;
         }
 
         env->globals.infallibleAppend(GlobalDesc(initializer, isMutable));
     }
 
     return d.finishSection(*range, "global");
 }
@@ -2355,19 +2355,17 @@ DecodeElemSection(Decoder& d, ModuleEnvi
         }
 
         seg->tableIndex = tableIndex;
 
         if (initializerKind == InitializerKind::Active ||
             initializerKind == InitializerKind::ActiveWithIndex)
         {
             InitExpr offset;
-            if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, ValType::I32,
-                                             env->types.length(), &offset))
-            {
+            if (!DecodeInitializerExpression(d, env, ValType::I32, &offset)) {
                 return false;
             }
             seg->offsetIfActive.emplace(offset);
         }
 
         uint32_t numElems;
         if (!d.readVarU32(&numElems)) {
             return d.fail("expected segment size");
@@ -2614,19 +2612,17 @@ DecodeDataSection(Decoder& d, ModuleEnvi
             }
         }
 
         DataSegmentEnv seg;
         if (initializerKind == InitializerKind::Active ||
             initializerKind == InitializerKind::ActiveWithIndex)
         {
             InitExpr segOffset;
-            if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, ValType::I32,
-                                             env->types.length(), &segOffset))
-            {
+            if (!DecodeInitializerExpression(d, env, ValType::I32, &segOffset)) {
                 return false;
             }
             seg.offsetIfActive.emplace(segOffset);
         }
 
         if (!d.readVarU32(&seg.length)) {
             return d.fail("expected segment size");
         }
--- a/js/src/wasm/WasmValidate.h
+++ b/js/src/wasm/WasmValidate.h
@@ -247,16 +247,29 @@ struct ModuleEnvironment
         return kind == ModuleKind::AsmJS;
     }
     bool debugEnabled() const {
         return compilerEnv->debug() == DebugEnabled::True;
     }
     bool funcIsImport(uint32_t funcIndex) const {
         return funcIndex < funcImportGlobalDataOffsets.length();
     }
+    bool isRefSubtypeOf(ValType one, ValType two) const {
+        MOZ_ASSERT(one.isReference());
+        MOZ_ASSERT(two.isReference());
+        MOZ_ASSERT(gcTypesEnabled() == HasGcTypes::True);
+        return one == two || two == ValType::AnyRef || one == ValType::NullRef ||
+               (one.isRef() && two.isRef() && isStructPrefixOf(two, one));
+    }
+
+  private:
+    bool isStructPrefixOf(ValType a, ValType b) const {
+        const StructType& other = types[a.refTypeIndex()].structType();
+        return types[b.refTypeIndex()].structType().hasPrefix(other);
+    }
 };
 
 // The Encoder class appends bytes to the Bytes object it is given during
 // construction. The client is responsible for the Bytes's lifetime and must
 // keep the Bytes alive as long as the Encoder is used.
 
 class Encoder
 {