Merge mozilla-central to mozilla-beta. a=merge CLOSED TREE DEVEDITION_63_0b3_BUILD1 DEVEDITION_63_0b3_RELEASE FENNEC_63_0b3_BUILD1 FENNEC_63_0b3_RELEASE FIREFOX_63_0b3_BUILD1 FIREFOX_63_0b3_RELEASE
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 04 Sep 2018 20:09:16 +0300
changeset 492324 0269319281578bff4e01d77a21350bf91ba08620
parent 492322 0311d9ebb702d915230a391f75fd1f149afbbf94 (current diff)
parent 492323 034c5ef24e98b0ce85fa849face079f568eb397c (diff)
child 492325 9a829d3b72aee067781e7f4efa2020cc0e63b579
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone63.0
Merge mozilla-central to mozilla-beta. a=merge CLOSED TREE
js/src/jit-test/tests/wasm/gc/gc-feature-opt-in.js
--- a/js/src/jit-test/lib/wasm-binary.js
+++ b/js/src/jit-test/lib/wasm-binary.js
@@ -19,17 +19,16 @@ const functionId       = 3;
 const tableId          = 4;
 const memoryId         = 5;
 const globalId         = 6;
 const exportId         = 7;
 const startId          = 8;
 const elemId           = 9;
 const codeId           = 10;
 const dataId           = 11;
-const gcFeatureOptInId = 42;
 
 // User-defined section names
 const nameName         = "name";
 
 // Name section name types
 const nameTypeModule   = 0;
 const nameTypeFunction = 1;
 const nameTypeLocal    = 2;
@@ -173,20 +172,16 @@ function moduleWithSections(sectionArray
     for (let section of sectionArray) {
         bytes.push(section.name);
         bytes.push(...varU32(section.body.length));
         bytes.push(...section.body);
     }
     return toU8(bytes);
 }
 
-function gcFeatureOptInSection(version) {
-    return { name: gcFeatureOptInId, body: [ version & 0x7F ] }
-}
-
 function sigSection(sigs) {
     var body = [];
     body.push(...varU32(sigs.length));
     for (let sig of sigs) {
         body.push(...varU32(FuncCode));
         body.push(...varU32(sig.args.length));
         for (let arg of sig.args)
             body.push(...varU32(arg));
--- a/js/src/jit-test/tests/wasm/binary.js
+++ b/js/src/jit-test/tests/wasm/binary.js
@@ -42,19 +42,19 @@ assertErrorMessage(() => wasmEval(toU8(m
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(globalId))), CompileError, sectionError("global"));
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(exportId))), CompileError, sectionError("export"));
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(startId))), CompileError, sectionError("start"));
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(elemId))), CompileError, sectionError("elem"));
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(codeId))), CompileError, sectionError("code"));
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(dataId))), CompileError, sectionError("data"));
 
 // unknown sections are unconditionally rejected
-assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(37))), CompileError, unknownSection);
-assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(37, 0))), CompileError, unknownSection);
-assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(37, 1, 0))), CompileError, unknownSection);
+assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(42))), CompileError, unknownSection);
+assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(42, 0))), CompileError, unknownSection);
+assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(42, 1, 0))), CompileError, unknownSection);
 
 // user sections have special rules
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0))), CompileError, sectionError("custom"));  // no length
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 0))), CompileError, sectionError("custom"));  // no id
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 0, 0))), CompileError, sectionError("custom"));  // payload too small to have id length
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 1, 1))), CompileError, sectionError("custom"));  // id not present
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 1, 1, 65))), CompileError, sectionError("custom"));  // id length doesn't fit in section
 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 1, 0, 0))), CompileError, sectionError("custom"));  // second, unfinished custom section
--- a/js/src/jit-test/tests/wasm/gc/anyref-global-postbarrier.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref-global-postbarrier.js
@@ -7,37 +7,34 @@ 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))
         (func (export "f")
             get_global 0
             ref.null anyref
             set_global 0
             set_global 0
         )
     )`).exports.f();
 })();
 
 let exportsPlain = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
     (global i32 (i32.const 42))
     (global $g (mut anyref) (ref.null anyref))
     (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))
     (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);
 
--- 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,16 +1,15 @@
 if (!wasmGcEnabled()) {
     quit(0);
 }
 
 const { startProfiling, endProfiling, assertEqPreciseStacks, isSingleStepProfilingEnabled } = WasmHelpers;
 
 let e = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
     (global $g (mut anyref) (ref.null anyref))
     (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
--- 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,15 +1,14 @@
 if (!wasmGcEnabled()) {
     quit(0);
 }
 
 gczeal(14, 1);
 let { exports } = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
     (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
@@ -9,67 +9,63 @@ function Baguette(calories) {
     this.calories = calories;
 }
 
 // Type checking.
 
 const { validate, CompileError } = WebAssembly;
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
     (func (result anyref)
         i32.const 42
     )
 )`), CompileError, mismatchError('i32', 'anyref'));
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
     (func (result anyref)
         i32.const 0
         ref.null anyref
         i32.const 42
         select
     )
 )`), CompileError, /select operand types/);
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
     (func (result i32)
         ref.null anyref
         if
             i32.const 42
         end
     )
 )`), CompileError, mismatchError('anyref', '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 (func (drop (ref.null anyref))))",
+    "(module (func $test (local anyref)))",
+    "(module (func $test (param anyref)))",
+    "(module (func $test (result anyref) (ref.null anyref)))",
+    "(module (func $test (block anyref (unreachable)) unreachable))",
+    "(module (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
+    `(module (import "a" "b" (param anyref)))`,
+    `(module (import "a" "b" (result anyref)))`,
+    `(module (global anyref (ref.null anyref)))`,
+    `(module (global (mut anyref) (ref.null anyref)))`,
 ];
 
 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)
     (func (export "is_null") (result i32)
         ref.null anyref
         ref.is_null
     )
 
     (func $sum (result i32) (param i32)
         get_local 0
         i32.const 42
@@ -97,17 +93,16 @@ let { exports } = wasmEvalText(`(module
 
 assertEq(exports.is_null(), 1);
 assertEq(exports.is_null_spill(), 1);
 assertEq(exports.is_null_local(), 1);
 
 // Anyref param and result in wasm functions.
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
     (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
@@ -155,33 +150,31 @@ 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)
     (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)
         (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)");
@@ -238,17 +231,16 @@ 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)
     (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;
 
@@ -293,17 +285,16 @@ let imports = {
         },
         ret() {
             return imports.myBaguette;
         }
     }
 };
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
     (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
@@ -322,17 +313,16 @@ 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)
     (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
@@ -406,39 +396,38 @@ 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 (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 (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 (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)
     (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_getglob  anyref (get_global $g_imp_imm_bread))
--- a/js/src/jit-test/tests/wasm/gc/binary.js
+++ b/js/src/jit-test/tests/wasm/gc/binary.js
@@ -3,20 +3,17 @@ if (!wasmGcEnabled()) {
 }
 
 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])])),
-                       WebAssembly.CompileError,
-                       errorMessage);
+    assertErrorMessage(() => new WebAssembly.Module(moduleWithSections([v2vSigSection, declSection([0]), bodySection([body])])), WebAssembly.CompileError, errorMessage);
 }
 
 const invalidRefNullBody = funcBody({locals:[], body:[
     RefNull,
     RefCode,
     0x42,
 
     RefNull,
--- a/js/src/jit-test/tests/wasm/gc/debugger.js
+++ b/js/src/jit-test/tests/wasm/gc/debugger.js
@@ -1,25 +1,24 @@
 if (!wasmGcEnabled() || !wasmDebuggingIsSupported()) {
     quit(0);
 }
 
 (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 (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)
         (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
@@ -1,28 +1,28 @@
 if (wasmGcEnabled()) {
     quit();
 }
 
 const { CompileError, validate } = WebAssembly;
 
-const UNRECOGNIZED_OPCODE_OR_BAD_TYPE = /unrecognized opcode|reference types not enabled|invalid inline block type/;
+const UNRECOGNIZED_OPCODE_OR_BAD_TYPE = /(unrecognized opcode|bad type|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 (func (drop (ref.null anyref))))",
+    "(module (func $test (local anyref)))",
+    "(module (func $test (param anyref)))",
+    "(module (func $test (result anyref) (ref.null anyref)))",
+    "(module (func $test (block anyref (unreachable)) unreachable))",
+    "(module (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
+    `(module (import "a" "b" (param anyref)))`,
+    `(module (import "a" "b" (result anyref)))`,
 ];
 
 for (let src of simpleTests) {
     print(src)
     assertErrorMessage(() => wasmEvalText(src), CompileError, UNRECOGNIZED_OPCODE_OR_BAD_TYPE);
     assertValidateError(src);
 }
deleted file mode 100644
--- a/js/src/jit-test/tests/wasm/gc/gc-feature-opt-in.js
+++ /dev/null
@@ -1,120 +0,0 @@
-if (!wasmGcEnabled()) {
-    quit(0);
-}
-
-// 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
-
-assertErrorMessage(() => new WebAssembly.Module(bad_order),
-                   WebAssembly.CompileError,
-                   /expected custom section/);
-
-// Version numbers.  Version 1 is good, version 2 is bad.
-
-new WebAssembly.Module(wasmTextToBinary(
-    `(module
-      (gc_feature_opt_in 1))`));
-
-assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
-    `(module
-      (gc_feature_opt_in 2))`)),
-                   WebAssembly.CompileError,
-                   /unsupported version of the gc feature/);
-
-// Struct types are only available if we opt in.
-
-new WebAssembly.Module(wasmTextToBinary(
-    `(module
-      (gc_feature_opt_in 1)
-      (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)
-      (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)
-      (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)
-      (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)))`));
-
-assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
-    `(module
-      (global (mut anyref) (ref.null anyref)))`)),
-                   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)))`)),
-                   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/ref-global.js
+++ b/js/src/jit-test/tests/wasm/gc/ref-global.js
@@ -2,17 +2,16 @@ if (!wasmGcEnabled())
     quit(0);
 
 // 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)
 
           (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)))
@@ -38,30 +37,28 @@ if (!wasmGcEnabled())
     ins.clear();                // Should not crash
 }
 
 // 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)
           (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)
           (type $box (struct (field $val i32)))
           (global $boxg (export "box") (mut (ref $box)) (ref.null (ref $box))))`);
 
     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
@@ -47,302 +47,269 @@ if (!wasmGcEnabled())
 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)
       (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)
       (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)
       (type $box (struct (field $x i32)))
       (func (export "f") (result (ref $box)) (ref.null (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (func (export "f") (result anyref) (ref.null anyref)))`),
          "object");
 
 // Imported function can't take ref parameter, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (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)
       (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)
       (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)
       (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)
       (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)
       (import "m" "g" (global (mut anyref))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (type $box (struct (field $val i32)))
       (global $boxg (export "box") (mut (ref $box)) (ref.null (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (type $box (struct (field $val i32)))
       (global $boxg (export "box") (ref $box) (ref.null (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (global $boxg (export "box") (mut anyref) (ref.null anyref)))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (global $boxg (export "box") anyref (ref.null anyref)))`),
          "object");
 
 // Exported table cannot reference functions that are exposed for Ref, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (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))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
       (func $f1 (result anyref) (ref.null anyref)))`),
          "object");
 
 // Imported table cannot reference functions that are exposed for Ref, though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (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))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
       (func $f1 (result anyref) (ref.null anyref)))`),
          "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)
       (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))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (type $fn (func (param anyref)))
       (table (export "tbl") 1 anyfunc)
       (func (param i32)
        (call_indirect $fn (ref.null anyref) (get_local 0))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (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))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
       (type $fn (func (param anyref)))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32)
        (call_indirect $fn (ref.null anyref) (get_local 0))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
       (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)
           (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))))`);
     let i = new WebAssembly.Instance(m).exports;
--- a/js/src/jit-test/tests/wasm/gc/ref.js
+++ b/js/src/jit-test/tests/wasm/gc/ref.js
@@ -1,19 +1,18 @@
 if (!wasmGcEnabled()) {
     assertErrorMessage(() => wasmEvalText(`(module (func (param (ref 0)) (unreachable)))`),
-                       WebAssembly.CompileError, /reference types not enabled/);
+                       WebAssembly.CompileError, /bad type/);
     quit(0);
 }
 
 // Parsing and resolving.
 
 var bin = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
       (type $cons (struct
                    (field $car i32)
                    (field $cdr (ref $cons))))
 
       (type $odd (struct
                   (field $x i32)
                   (field $to_even (ref $even))))
 
@@ -63,152 +62,137 @@ var bin = wasmTextToBinary(
 // 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)
  (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)
  (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)
- (func (param (ref $odd)) (unreachable)))
+  (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)
  (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)
  (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)
  (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)
  (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)
  (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)
  (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)
  (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)
  (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)
  (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)
  (type $x (func (param i32)))
  (func $f (param (ref $x)) (unreachable)))
 `),
 SyntaxError, /Type label.*not found/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (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)
  (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,19 +1,16 @@
 if (!wasmGcEnabled()) {
-    assertErrorMessage(() => wasmEvalText(`(module
-                                            (gc_feature_opt_in 1)
-                                            (type $s (struct)))`),
+    assertErrorMessage(() => wasmEvalText(`(module (type $s (struct)))`),
                        WebAssembly.CompileError, /Structure types not enabled/);
     quit();
 }
 
 var bin = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
 
       (table 2 anyfunc)
       (elem (i32.const 0) $doit $doitagain)
 
       ;; Type array has a mix of types
 
       (type $f1 (func (param i32) (result i32)))
 
@@ -71,95 +68,82 @@ assertEq(ins.hello(4.0, 1), 16.0)
 
 assertEq(ins.x1(12), 36)
 assertEq(ins.x2(8), Math.PI)
 
 // The field name is optional, so this should work.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (type $s (struct (field i32))))
 `)
 
 // Empty structs are OK.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (type $s (struct)))
 `)
 
 // Multiply defined structures.
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (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)
  (type $s))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (type $s (field $x i32)))
 `),
 SyntaxError, /bad type definition/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (type $s (struct (field $x i31))))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (type $s (struct (fjeld $x i32))))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (type $s (struct abracadabra)))
 `),
 SyntaxError, /parsing wasm text/);
 
 // Function should not reference struct type: syntactic test
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
  (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/);
 
 // 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
-
                           0x01,                   // Type section
                           0x03,                   // Section size
                           0x01,                   // One type
                           0x50,                   // Struct
                           0x00,                   // Zero fields
 
                           0x03,                   // Function section
                           0x02,                   // Section size
--- a/js/src/wasm/WasmAST.h
+++ b/js/src/wasm/WasmAST.h
@@ -1228,19 +1228,16 @@ class AstModule : public AstNode
 
     LifoAlloc&           lifo_;
     TypeDefVector        types_;
     FuncTypeMap          funcTypeMap_;
     ImportVector         imports_;
     NameVector           funcImportNames_;
     AstResizableVector   tables_;
     AstResizableVector   memories_;
-#ifdef ENABLE_WASM_GC
-    uint32_t             gcFeatureOptIn_;
-#endif
     ExportVector         exports_;
     Maybe<AstStartFunc>  startFunc_;
     FuncVector           funcs_;
     AstDataSegmentVector dataSegments_;
     AstElemSegmentVector elemSegments_;
     AstGlobalVector      globals_;
 
     size_t numGlobalImports_;
@@ -1249,44 +1246,32 @@ class AstModule : public AstNode
     explicit AstModule(LifoAlloc& lifo)
       : lifo_(lifo),
         types_(lifo),
         funcTypeMap_(lifo),
         imports_(lifo),
         funcImportNames_(lifo),
         tables_(lifo),
         memories_(lifo),
-#ifdef ENABLE_WASM_GC
-        gcFeatureOptIn_(0),
-#endif
         exports_(lifo),
         funcs_(lifo),
         dataSegments_(lifo),
         elemSegments_(lifo),
         globals_(lifo),
         numGlobalImports_(0)
     {}
     bool addMemory(AstName name, const Limits& memory) {
         return memories_.append(AstResizable(memory, false, name));
     }
     bool hasMemory() const {
         return !!memories_.length();
     }
     const AstResizableVector& memories() const {
         return memories_;
     }
-#ifdef ENABLE_WASM_GC
-    bool addGcFeatureOptIn(uint32_t version) {
-        gcFeatureOptIn_ = version;
-        return true;
-    }
-    uint32_t gcFeatureOptIn() const {
-        return gcFeatureOptIn_;
-    }
-#endif
     bool addTable(AstName name, const Limits& table) {
         return tables_.append(AstResizable(table, false, name));
     }
     bool hasTable() const {
         return !!tables_.length();
     }
     const AstResizableVector& tables() const {
         return tables_;
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -9962,22 +9962,22 @@ BaseCompiler::emitBody()
           // Memory Related
           case uint16_t(Op::GrowMemory):
             CHECK_NEXT(emitGrowMemory());
           case uint16_t(Op::CurrentMemory):
             CHECK_NEXT(emitCurrentMemory());
 
 #ifdef ENABLE_WASM_GC
           case uint16_t(Op::RefNull):
-            if (env_.gcTypesEnabled() == HasGcTypes::False)
+            if (env_.gcTypesEnabled == HasGcTypes::False)
                 return iter_.unrecognizedOpcode(&op);
             CHECK_NEXT(emitRefNull());
             break;
           case uint16_t(Op::RefIsNull):
-            if (env_.gcTypesEnabled() == HasGcTypes::False)
+            if (env_.gcTypesEnabled == HasGcTypes::False)
                 return iter_.unrecognizedOpcode(&op);
             CHECK_NEXT(emitConversion(emitRefIsNull, ValType::AnyRef, ValType::I32));
             break;
 #endif
 
           // "Miscellaneous" operations
           case uint16_t(Op::MiscPrefix): {
             switch (op.b1) {
@@ -10370,17 +10370,17 @@ js::wasm::BaselineCompileFunctions(const
     for (const FuncCompileInput& func : inputs) {
         Decoder d(func.begin, func.end, func.lineOrBytecode, error);
 
         // Build the local types vector.
 
         ValTypeVector locals;
         if (!locals.appendAll(env.funcTypes[func.index]->args()))
             return false;
-        if (!DecodeLocalEntries(d, env.kind, env.types, env.gcTypesEnabled(), &locals))
+        if (!DecodeLocalEntries(d, env.kind, env.types, env.gcTypesEnabled, &locals))
             return false;
 
         // One-pass baseline compilation.
 
         BaseCompiler f(env, func, locals, d, &alloc, &masm);
         if (!f.init())
             return false;
         if (!f.emitFunction())
--- a/js/src/wasm/WasmBinaryConstants.h
+++ b/js/src/wasm/WasmBinaryConstants.h
@@ -33,20 +33,17 @@ enum class SectionId
     Function                             = 3,
     Table                                = 4,
     Memory                               = 5,
     Global                               = 6,
     Export                               = 7,
     Start                                = 8,
     Elem                                 = 9,
     Code                                 = 10,
-    Data                                 = 11,
-#ifdef ENABLE_WASM_GC
-    GcFeatureOptIn                       = 42 // Arbitrary, but fits in 7 bits
-#endif
+    Data                                 = 11
 };
 
 enum class TypeCode
 {
     I32                                  = 0x7f,  // SLEB128(-0x01)
     I64                                  = 0x7e,  // SLEB128(-0x02)
     F32                                  = 0x7d,  // SLEB128(-0x03)
     F64                                  = 0x7c,  // SLEB128(-0x04)
--- a/js/src/wasm/WasmCode.cpp
+++ b/js/src/wasm/WasmCode.cpp
@@ -623,17 +623,17 @@ struct ProjectLazyFuncIndex
     uint32_t operator[](size_t index) const {
         return funcExports[index].funcIndex;
     }
 };
 
 static constexpr unsigned LAZY_STUB_LIFO_DEFAULT_CHUNK_SIZE = 8 * 1024;
 
 bool
-LazyStubTier::createMany(HasGcTypes gcTypesConfigured, const Uint32Vector& funcExportIndices,
+LazyStubTier::createMany(HasGcTypes gcTypesEnabled, const Uint32Vector& funcExportIndices,
                          const CodeTier& codeTier, size_t* stubSegmentIndex)
 {
     MOZ_ASSERT(funcExportIndices.length());
 
     LifoAlloc lifo(LAZY_STUB_LIFO_DEFAULT_CHUNK_SIZE);
     TempAllocator alloc(&lifo);
     JitContext jitContext(&alloc);
     WasmMacroAssembler masm(alloc);
@@ -647,17 +647,17 @@ LazyStubTier::createMany(HasGcTypes gcTy
     for (uint32_t funcExportIndex : funcExportIndices) {
         const FuncExport& fe = funcExports[funcExportIndex];
         numExpectedRanges += fe.funcType().temporarilyUnsupportedAnyRef() ? 1 : 2;
         void* calleePtr = moduleSegmentBase +
                           moduleRanges[fe.funcCodeRangeIndex()].funcNormalEntry();
         Maybe<ImmPtr> callee;
         callee.emplace(calleePtr, ImmPtr::NoCheckToken());
         if (!GenerateEntryStubs(masm, funcExportIndex, fe, callee, /* asmjs */ false,
-                                gcTypesConfigured, &codeRanges))
+                                gcTypesEnabled, &codeRanges))
         {
             return false;
         }
     }
     MOZ_ASSERT(codeRanges.length() == numExpectedRanges, "incorrect number of entries per function");
 
     masm.finish();
 
@@ -729,17 +729,17 @@ LazyStubTier::createMany(HasGcTypes gcTy
 bool
 LazyStubTier::createOne(uint32_t funcExportIndex, const CodeTier& codeTier)
 {
     Uint32Vector funcExportIndexes;
     if (!funcExportIndexes.append(funcExportIndex))
         return false;
 
     size_t stubSegmentIndex;
-    if (!createMany(codeTier.code().metadata().temporaryGcTypesConfigured, funcExportIndexes, codeTier,
+    if (!createMany(codeTier.code().metadata().temporaryHasGcTypes, funcExportIndexes, codeTier,
                     &stubSegmentIndex))
     {
         return false;
     }
 
     const UniqueLazyStubSegment& segment = stubSegments_[stubSegmentIndex];
     const CodeRangeVector& codeRanges = segment->codeRanges();
 
@@ -756,24 +756,24 @@ LazyStubTier::createOne(uint32_t funcExp
     const CodeRange& cr = codeRanges[codeRanges.length() - 1];
     MOZ_ASSERT(cr.isJitEntry());
 
     codeTier.code().setJitEntry(cr.funcIndex(), segment->base() + cr.begin());
     return true;
 }
 
 bool
-LazyStubTier::createTier2(HasGcTypes gcTypesConfigured, const Uint32Vector& funcExportIndices,
+LazyStubTier::createTier2(HasGcTypes gcTypesEnabled, const Uint32Vector& funcExportIndices,
                           const CodeTier& codeTier, Maybe<size_t>* outStubSegmentIndex)
 {
     if (!funcExportIndices.length())
         return true;
 
     size_t stubSegmentIndex;
-    if (!createMany(gcTypesConfigured, funcExportIndices, codeTier, &stubSegmentIndex))
+    if (!createMany(gcTypesEnabled, funcExportIndices, codeTier, &stubSegmentIndex))
         return false;
 
     outStubSegmentIndex->emplace(stubSegmentIndex);
     return true;
 }
 
 void
 LazyStubTier::setJitEntries(const Maybe<size_t>& stubSegmentIndex, const Code& code)
--- a/js/src/wasm/WasmCode.h
+++ b/js/src/wasm/WasmCode.h
@@ -363,28 +363,28 @@ typedef Vector<ExprType, 0, SystemAllocP
 // the former points to instances of the latter.  Additionally, the asm.js
 // subsystem subclasses the Metadata, adding more tier-invariant data, some of
 // which is serialized.  See AsmJS.cpp.
 
 struct MetadataCacheablePod
 {
     ModuleKind            kind;
     MemoryUsage           memoryUsage;
-    HasGcTypes            temporaryGcTypesConfigured;
+    HasGcTypes            temporaryHasGcTypes;
     uint32_t              minMemoryLength;
     uint32_t              globalDataLength;
     Maybe<uint32_t>       maxMemoryLength;
     Maybe<uint32_t>       startFuncIndex;
     Maybe<NameInBytecode> moduleName;
     bool                  filenameIsURL;
 
     explicit MetadataCacheablePod(ModuleKind kind)
       : kind(kind),
         memoryUsage(MemoryUsage::None),
-        temporaryGcTypesConfigured(HasGcTypes::False),
+        temporaryHasGcTypes(HasGcTypes::False),
         minMemoryLength(0),
         globalDataLength(0),
         filenameIsURL(false)
     {}
 };
 
 typedef uint8_t ModuleHash[8];
 
@@ -571,17 +571,17 @@ class LazyStubTier
     // Creates one lazy stub for the exported function, for which the jit entry
     // will be set to the lazily-generated one.
     bool createOne(uint32_t funcExportIndex, const CodeTier& codeTier);
 
     // Create one lazy stub for all the functions in funcExportIndices, putting
     // them in a single stub. Jit entries won't be used until
     // setJitEntries() is actually called, after the Code owner has committed
     // tier2.
-    bool createTier2(HasGcTypes gcTypesConfigured, const Uint32Vector& funcExportIndices,
+    bool createTier2(HasGcTypes gcTypesEnabled, const Uint32Vector& funcExportIndices,
                      const CodeTier& codeTier, Maybe<size_t>* stubSegmentIndex);
     void setJitEntries(const Maybe<size_t>& stubSegmentIndex, const Code& code);
 
     void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data) const;
 };
 
 // CodeTier contains all the data related to a given compilation tier. It is
 // built during module generation and then immutably stored in a Code.
--- a/js/src/wasm/WasmCompile.cpp
+++ b/js/src/wasm/WasmCompile.cpp
@@ -91,17 +91,17 @@ CompileArgs::initFromContext(JSContext* 
     bool gcEnabled = cx->options().wasmGc();
 #else
     bool gcEnabled = false;
 #endif
 
     baselineEnabled = cx->options().wasmBaseline() || gcEnabled;
     ionEnabled = cx->options().wasmIon() && !gcEnabled;
     sharedMemoryEnabled = cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
-    gcTypesConfigured = gcEnabled ? HasGcTypes::True : HasGcTypes::False;
+    gcTypesEnabled = gcEnabled ? HasGcTypes::True : HasGcTypes::False;
     testTiering = (cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2) && !gcEnabled;
 
     // Debug information such as source view or debug traps will require
     // additional memory and permanently stay in baseline code, so we try to
     // only enable it when a developer actually cares: when the debugger tab
     // is open.
     debugEnabled = cx->realm()->debuggerObservesAsmJS();
 
@@ -427,17 +427,17 @@ wasm::CompileBuffer(const CompileArgs& a
 
     Decoder d(bytecode.bytes, 0, error, warnings);
 
     CompileMode mode;
     Tier tier;
     DebugEnabled debug;
     InitialCompileFlags(args, d, &mode, &tier, &debug);
 
-    ModuleEnvironment env(mode, tier, debug, args.gcTypesConfigured,
+    ModuleEnvironment env(mode, tier, debug, args.gcTypesEnabled,
                           args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
     if (!DecodeModuleEnvironment(d, &env))
         return nullptr;
 
     ModuleGenerator mg(args, &env, nullptr, error);
     if (!mg.init())
         return nullptr;
 
@@ -453,17 +453,17 @@ wasm::CompileBuffer(const CompileArgs& a
 void
 wasm::CompileTier2(const CompileArgs& args, Module& module, Atomic<bool>* cancelled)
 {
     MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
 
     UniqueChars error;
     Decoder d(module.bytecode().bytes, 0, &error);
 
-    MOZ_ASSERT(args.gcTypesConfigured == HasGcTypes::False, "can't ion-compile with gc types yet");
+    MOZ_ASSERT(args.gcTypesEnabled == HasGcTypes::False, "can't ion-compile with gc types yet");
 
     ModuleEnvironment env(CompileMode::Tier2, Tier::Ion, DebugEnabled::False, HasGcTypes::False,
                           args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
     if (!DecodeModuleEnvironment(d, &env))
         return;
 
     ModuleGenerator mg(args, &env, cancelled, &error);
     if (!mg.init())
@@ -582,17 +582,17 @@ wasm::CompileStreaming(const CompileArgs
     {
         Decoder d(envBytes, 0, error, warnings);
 
         CompileMode mode;
         Tier tier;
         DebugEnabled debug;
         InitialCompileFlags(args, d, &mode, &tier, &debug);
 
-        env.emplace(mode, tier, debug, args.gcTypesConfigured,
+        env.emplace(mode, tier, debug, args.gcTypesEnabled,
                     args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
         if (!DecodeModuleEnvironment(d, env.ptr()))
             return nullptr;
 
         MOZ_ASSERT(d.done());
     }
 
     ModuleGenerator mg(args, env.ptr(), &cancelled, error);
--- a/js/src/wasm/WasmCompile.h
+++ b/js/src/wasm/WasmCompile.h
@@ -41,27 +41,27 @@ struct CompileArgs : ShareableBase<Compi
 {
     Assumptions assumptions;
     ScriptedCaller scriptedCaller;
     UniqueChars sourceMapURL;
     bool baselineEnabled;
     bool debugEnabled;
     bool ionEnabled;
     bool sharedMemoryEnabled;
-    HasGcTypes gcTypesConfigured;
+    HasGcTypes gcTypesEnabled;
     bool testTiering;
 
     CompileArgs(Assumptions&& assumptions, ScriptedCaller&& scriptedCaller)
       : assumptions(std::move(assumptions)),
         scriptedCaller(std::move(scriptedCaller)),
         baselineEnabled(false),
         debugEnabled(false),
         ionEnabled(false),
         sharedMemoryEnabled(false),
-        gcTypesConfigured(HasGcTypes::False),
+        gcTypesEnabled(HasGcTypes::False),
         testTiering(false)
     {}
 
     // If CompileArgs is constructed without arguments, initFromContext() must
     // be called to complete initialization.
     CompileArgs() = default;
     bool initFromContext(JSContext* cx, ScriptedCaller&& scriptedCaller);
 };
--- a/js/src/wasm/WasmGenerator.cpp
+++ b/js/src/wasm/WasmGenerator.cpp
@@ -827,17 +827,17 @@ ModuleGenerator::finishMetadata(const Sh
         MOZ_ASSERT(debugTrapFarJumpOffset >= last);
         last = debugTrapFarJumpOffset;
     }
 #endif
 
     // Copy over data from the ModuleEnvironment.
 
     metadata_->memoryUsage = env_->memoryUsage;
-    metadata_->temporaryGcTypesConfigured = env_->gcTypesConfigured;
+    metadata_->temporaryHasGcTypes = env_->gcTypesEnabled;
     metadata_->minMemoryLength = env_->minMemoryLength;
     metadata_->maxMemoryLength = env_->maxMemoryLength;
     metadata_->startFuncIndex = env_->startFuncIndex;
     metadata_->moduleName = env_->moduleName;
     metadata_->tables = std::move(env_->tables);
     metadata_->globals = std::move(env_->globals);
     metadata_->funcNames = std::move(env_->funcNames);
     metadata_->customSections = std::move(env_->customSections);
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -3498,17 +3498,17 @@ wasm::IonCompileFunctions(const ModuleEn
     for (const FuncCompileInput& func : inputs) {
         Decoder d(func.begin, func.end, func.lineOrBytecode, error);
 
         // Build the local types vector.
 
         ValTypeVector locals;
         if (!locals.appendAll(env.funcTypes[func.index]->args()))
             return false;
-        if (!DecodeLocalEntries(d, env.kind, env.types, env.gcTypesEnabled(), &locals))
+        if (!DecodeLocalEntries(d, env.kind, env.types, env.gcTypesEnabled, &locals))
             return false;
 
         // Set up for Ion compilation.
 
         const JitCompileOptions options;
         MIRGraph graph(&alloc);
         CompileInfo compileInfo(locals.length());
         MIRGenerator mir(nullptr, options, &alloc, &graph, &compileInfo,
--- a/js/src/wasm/WasmModule.cpp
+++ b/js/src/wasm/WasmModule.cpp
@@ -249,21 +249,21 @@ Module::finishTier2(UniqueLinkDataTier l
                 continue;
             MOZ_ASSERT(!env2->isAsmJS(), "only wasm functions are lazily exported");
             if (!stubs1->hasStub(fe.funcIndex()))
                 continue;
             if (!funcExportIndices.emplaceBack(i))
                 return false;
         }
 
-        HasGcTypes gcTypesConfigured = code().metadata().temporaryGcTypesConfigured;
+        HasGcTypes gcTypesEnabled = code().metadata().temporaryHasGcTypes;
         const CodeTier& tier2 = code().codeTier(Tier::Ion);
 
         Maybe<size_t> stub2Index;
-        if (!stubs2->createTier2(gcTypesConfigured, funcExportIndices, tier2, &stub2Index))
+        if (!stubs2->createTier2(gcTypesEnabled, funcExportIndices, tier2, &stub2Index))
             return false;
 
         // Now that we can't fail or otherwise abort tier2, make it live.
 
         MOZ_ASSERT(!code().hasTier2());
         code().commitTier2();
 
         stubs2->setJitEntries(stub2Index, code());
--- a/js/src/wasm/WasmOpIter.h
+++ b/js/src/wasm/WasmOpIter.h
@@ -627,17 +627,17 @@ OpIter<Policy>::Unify(StackType observed
         return true;
     }
 
     if (expected == StackType::Any) {
         *result = observed;
         return true;
     }
 
-    if (env_.gcTypesEnabled() == HasGcTypes::True && observed.isRefOrAnyRef() &&
+    if (env_.gcTypesEnabled == HasGcTypes::True && observed.isRefOrAnyRef() &&
         expected.isRefOrAnyRef() && IsSubtypeOf(observed, expected))
     {
         *result = expected;
         return true;
     }
 
     return false;
 }
@@ -656,17 +656,17 @@ OpIter<Policy>::Join(StackType one, Stac
         return true;
     }
 
     if (two == StackType::Any) {
         *result = one;
         return true;
     }
 
-    if (env_.gcTypesEnabled() == HasGcTypes::True && one.isRefOrAnyRef() && two.isRefOrAnyRef()) {
+    if (env_.gcTypesEnabled == HasGcTypes::True && one.isRefOrAnyRef() && two.isRefOrAnyRef()) {
         if (IsSubtypeOf(two, one)) {
             *result = one;
             return true;
         }
 
         if (IsSubtypeOf(one, two)) {
             *result = two;
             return true;
@@ -896,22 +896,22 @@ OpIter<Policy>::readBlockType(ExprType* 
       case uint8_t(ExprType::Void):
       case uint8_t(ExprType::I32):
       case uint8_t(ExprType::I64):
       case uint8_t(ExprType::F32):
       case uint8_t(ExprType::F64):
         known = true;
         break;
       case uint8_t(ExprType::Ref):
-        known = env_.gcTypesEnabled() == HasGcTypes::True &&
+        known = env_.gcTypesEnabled == HasGcTypes::True &&
                 uncheckedRefTypeIndex < MaxTypes &&
                 uncheckedRefTypeIndex < env_.types.length();
         break;
       case uint8_t(ExprType::AnyRef):
-        known = env_.gcTypesEnabled() == HasGcTypes::True;
+        known = env_.gcTypesEnabled == HasGcTypes::True;
         break;
       case uint8_t(ExprType::Limit):
         break;
     }
 
     if (!known)
         return fail("invalid inline block type");
 
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -292,17 +292,17 @@ CallFuncExport(MacroAssembler& masm, con
 }
 
 // Generate a stub that enters wasm from a C++ caller via the native ABI. The
 // signature of the entry point is Module::ExportFuncPtr. The exported wasm
 // function has an ABI derived from its specific signature, so this function
 // must map from the ABI of ExportFuncPtr to the export's signature's ABI.
 static bool
 GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe, const Maybe<ImmPtr>& funcPtr,
-                    HasGcTypes gcTypesConfigured, Offsets* offsets)
+                    HasGcTypes gcTypesEnabled, Offsets* offsets)
 {
     AssertExpectedSP(masm);
     masm.haltingAlign(CodeAlignment);
 
     offsets->begin = masm.currentOffset();
 
     // Save the return address if it wasn't already saved by the call insn.
 #ifdef JS_USE_LINK_REGISTER
@@ -347,17 +347,17 @@ GenerateInterpEntry(MacroAssembler& masm
     arg = abi.next(MIRType::Pointer);
     if (arg.kind() == ABIArg::GPR)
         masm.movePtr(arg.gpr(), WasmTlsReg);
     else
         masm.loadPtr(Address(masm.getStackPointer(), argBase + arg.offsetFromArgBase()), WasmTlsReg);
 
 #ifdef ENABLE_WASM_GC
     WasmPush(masm, WasmTlsReg);
-    if (gcTypesConfigured == HasGcTypes::True)
+    if (gcTypesEnabled == HasGcTypes::True)
         SuppressGC(masm, 1, scratch);
 #endif
 
     // Save 'argv' on the stack so that we can recover it after the call.
     WasmPush(masm, argv);
 
     // Since we're about to dynamically align the stack, reset the frame depth
     // so we can still assert static stack depth balancing.
@@ -406,17 +406,17 @@ GenerateInterpEntry(MacroAssembler& masm
     MOZ_ASSERT(masm.framePushed() == 0);
     masm.setFramePushed(FramePushedBeforeAlign);
 
     // Recover the 'argv' pointer which was saved before aligning the stack.
     WasmPop(masm, argv);
 
 #ifdef ENABLE_WASM_GC
     WasmPop(masm, WasmTlsReg);
-    if (gcTypesConfigured == HasGcTypes::True)
+    if (gcTypesEnabled == HasGcTypes::True)
         SuppressGC(masm, -1, WasmTlsReg);
 #endif
 
     // Store the return value in argv[0].
     StoreABIReturn(masm, fe, argv);
 
     // After the ReturnReg is stored into argv[0] but before fp is clobbered by
     // the PopRegsInMask(NonVolatileRegs) below, set the return value based on
@@ -514,17 +514,17 @@ GenerateJitEntryThrow(MacroAssembler& ma
 // Generate a stub that enters wasm from a jit code caller via the jit ABI.
 //
 // ARM64 note: This does not save the PseudoStackPointer so we must be sure to
 // recompute it on every return path, be it normal return or exception return.
 // The JIT code we return to assumes it is correct.
 
 static bool
 GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& fe,
-                 const Maybe<ImmPtr>& funcPtr, HasGcTypes gcTypesConfigured, Offsets* offsets)
+                 const Maybe<ImmPtr>& funcPtr, HasGcTypes gcTypesEnabled, Offsets* offsets)
 {
     AssertExpectedSP(masm);
 
     RegisterOrSP sp = masm.getStackPointer();
 
     GenerateJitEntryPrologue(masm, offsets);
 
     // The jit caller has set up the following stack layout (sp grows to the
@@ -727,30 +727,30 @@ GenerateJitEntry(MacroAssembler& masm, s
           }
         }
     }
 
     // Setup wasm register state.
     masm.loadWasmPinnedRegsFromTls();
 
 #ifdef ENABLE_WASM_GC
-    if (gcTypesConfigured == HasGcTypes::True) {
+    if (gcTypesEnabled == HasGcTypes::True) {
         masm.storePtr(WasmTlsReg, Address(sp, savedTlsOffset));
         SuppressGC(masm, 1, ScratchIonEntry);
     }
 #endif
 
     // Call into the real function. Note that, due to the throw stub, fp, tls
     // and pinned registers may be clobbered.
     masm.assertStackAlignment(WasmStackAlignment);
     CallFuncExport(masm, fe, funcPtr);
     masm.assertStackAlignment(WasmStackAlignment);
 
 #ifdef ENABLE_WASM_GC
-    if (gcTypesConfigured == HasGcTypes::True) {
+    if (gcTypesEnabled == HasGcTypes::True) {
         masm.loadPtr(Address(sp, savedTlsOffset), WasmTlsReg);
         SuppressGC(masm, -1, WasmTlsReg);
     }
 #endif
 
     // If fp is equal to the FailFP magic value (set by the throw stub), then
     // report the exception to the JIT caller by jumping into the exception
     // stub; otherwise the FP value is still set to the parent ion frame value.
@@ -1843,32 +1843,32 @@ GenerateDebugTrapStub(MacroAssembler& ma
 
     GenerateExitEpilogue(masm, 0, ExitReason::Fixed::DebugTrap, offsets);
 
     return FinishOffsets(masm, offsets);
 }
 
 bool
 wasm::GenerateEntryStubs(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& fe,
-                         const Maybe<ImmPtr>& callee, bool isAsmJS, HasGcTypes gcTypesConfigured,
+                         const Maybe<ImmPtr>& callee, bool isAsmJS, HasGcTypes gcTypesEnabled,
                          CodeRangeVector* codeRanges)
 {
     MOZ_ASSERT(!callee == fe.hasEagerStubs());
     MOZ_ASSERT_IF(isAsmJS, fe.hasEagerStubs());
 
     Offsets offsets;
-    if (!GenerateInterpEntry(masm, fe, callee, gcTypesConfigured, &offsets))
+    if (!GenerateInterpEntry(masm, fe, callee, gcTypesEnabled, &offsets))
         return false;
     if (!codeRanges->emplaceBack(CodeRange::InterpEntry, fe.funcIndex(), offsets))
         return false;
 
     if (isAsmJS || fe.funcType().temporarilyUnsupportedAnyRef())
         return true;
 
-    if (!GenerateJitEntry(masm, funcExportIndex, fe, callee, gcTypesConfigured, &offsets))
+    if (!GenerateJitEntry(masm, funcExportIndex, fe, callee, gcTypesEnabled, &offsets))
         return false;
     if (!codeRanges->emplaceBack(CodeRange::JitEntry, fe.funcIndex(), offsets))
         return false;
 
     return true;
 }
 
 bool
@@ -1909,17 +1909,17 @@ wasm::GenerateStubs(const ModuleEnvironm
     JitSpew(JitSpew_Codegen, "# Emitting wasm export stubs");
 
     Maybe<ImmPtr> noAbsolute;
     for (size_t i = 0; i < exports.length(); i++) {
         const FuncExport& fe = exports[i];
         if (!fe.hasEagerStubs())
             continue;
         if (!GenerateEntryStubs(masm, i, fe, noAbsolute, env.isAsmJS(),
-                                env.gcTypesConfigured, &code->codeRanges))
+                                env.gcTypesEnabled, &code->codeRanges))
         {
             return false;
         }
     }
 
     JitSpew(JitSpew_Codegen, "# Emitting wasm exit stubs");
 
     Offsets offsets;
--- a/js/src/wasm/WasmStubs.h
+++ b/js/src/wasm/WasmStubs.h
@@ -34,17 +34,17 @@ GenerateImportFunctions(const ModuleEnvi
 
 extern bool
 GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& imports,
               const FuncExportVector& exports, CompiledCode* code);
 
 extern bool
 GenerateEntryStubs(jit::MacroAssembler& masm, size_t funcExportIndex,
                    const FuncExport& funcExport, const Maybe<jit::ImmPtr>& callee,
-                   bool isAsmJS, HasGcTypes gcTypesConfigured, CodeRangeVector* codeRanges);
+                   bool isAsmJS, HasGcTypes gcTypesEnabled, CodeRangeVector* codeRanges);
 
 // An argument that will end up on the stack according to the system ABI, to be
 // passed to GenerateDirectCallFromJit. Since the direct JIT call creates its
 // own frame, it is its responsibility to put stack arguments to their expected
 // locations; so the caller of GenerateDirectCallFromJit can put them anywhere.
 
 class JitCallStackArg
 {
--- a/js/src/wasm/WasmTextToBinary.cpp
+++ b/js/src/wasm/WasmTextToBinary.cpp
@@ -92,19 +92,16 @@ class WasmToken
         Error,
         Export,
 #ifdef ENABLE_WASM_SATURATING_TRUNC_OPS
         ExtraConversionOpcode,
 #endif
         Field,
         Float,
         Func,
-#ifdef ENABLE_WASM_GC
-        GcFeatureOptIn,
-#endif
         GetGlobal,
         GetLocal,
         Global,
         GrowMemory,
         If,
         Import,
         Index,
         Memory,
@@ -370,19 +367,16 @@ class WasmToken
           case EndOfFile:
           case Equal:
           case End:
           case Error:
           case Export:
           case Field:
           case Float:
           case Func:
-#ifdef ENABLE_WASM_GC
-          case GcFeatureOptIn:
-#endif
           case Global:
           case Mutable:
           case Import:
           case Index:
           case Memory:
           case NegativeZero:
           case Local:
           case Module:
@@ -1171,18 +1165,16 @@ WasmTokenStream::next()
                     return WasmToken(WasmToken::UnaryOpcode, Op::F64Trunc, begin, cur_);
                 break;
             }
             break;
         }
         break;
 
       case 'g':
-        if (consume(u"gc_feature_opt_in"))
-            return WasmToken(WasmToken::GcFeatureOptIn, begin, cur_);
         if (consume(u"get_global"))
             return WasmToken(WasmToken::GetGlobal, begin, cur_);
         if (consume(u"get_local"))
             return WasmToken(WasmToken::GetLocal, begin, cur_);
         if (consume(u"global"))
             return WasmToken(WasmToken::Global, begin, cur_);
         if (consume(u"grow_memory"))
             return WasmToken(WasmToken::GrowMemory, begin, cur_);
@@ -3626,38 +3618,16 @@ ParseMemory(WasmParseContext& c, AstModu
 
     Limits memory;
     if (!ParseLimits(c, &memory, Shareable::True))
         return false;
 
     return module->addMemory(name, memory);
 }
 
-#ifdef ENABLE_WASM_GC
-// Custom section for experimental work.  The size of this section should always
-// be 1 byte, and that byte is a nonzero varint7 carrying the version number
-// being opted into.
-static bool
-ParseGcFeatureOptIn(WasmParseContext& c, AstModule* module)
-{
-    WasmToken token;
-    if (!c.ts.getIf(WasmToken::Index, &token)) {
-        c.ts.generateError(token, "GC feature version number required", c.error);
-        return false;
-    }
-
-    if (token.index() == 0 || token.index() > 127) {
-        c.ts.generateError(token, "invalid GC feature version number", c.error);
-        return false;
-    }
-
-    return module->addGcFeatureOptIn(token.index());
-}
-#endif
-
 static bool
 ParseStartFunc(WasmParseContext& c, WasmToken token, AstModule* module)
 {
     AstRef func;
     if (!c.ts.matchRef(&func, c.error))
         return false;
 
     if (!module->setStartFunc(AstStartFunc(func))) {
@@ -4085,23 +4055,16 @@ ParseModule(const char16_t* text, uintpt
                 return nullptr;
             break;
           }
           case WasmToken::Memory: {
             if (!ParseMemory(c, module))
                 return nullptr;
             break;
           }
-#ifdef ENABLE_WASM_GC
-          case WasmToken::GcFeatureOptIn: {
-            if (!ParseGcFeatureOptIn(c, module))
-                return nullptr;
-            break;
-          }
-#endif
           case WasmToken::Global: {
             if (!ParseGlobal(c, module))
                 return nullptr;
             break;
           }
           case WasmToken::Data: {
             AstDataSegment* segment = ParseDataSegment(c);
             if (!segment || !module->append(segment))
@@ -5400,36 +5363,16 @@ EncodeExpr(Encoder& e, AstExpr& expr)
 #endif
     }
     MOZ_CRASH("Bad expr kind");
 }
 
 /*****************************************************************************/
 // wasm AST binary serialization
 
-#ifdef ENABLE_WASM_GC
-static bool
-EncodeGcFeatureOptInSection(Encoder& e, AstModule& module)
-{
-    uint32_t optInVersion = module.gcFeatureOptIn();
-    if (!optInVersion)
-        return true;
-
-    size_t offset;
-    if (!e.startSection(SectionId::GcFeatureOptIn, &offset))
-        return false;
-
-    if (!e.writeVarU32(optInVersion))
-        return false;
-
-    e.finishSection(offset);
-    return true;
-}
-#endif
-
 static bool
 EncodeTypeSection(Encoder& e, AstModule& module)
 {
     if (module.types().empty())
         return true;
 
     size_t offset;
     if (!e.startSection(SectionId::Type, &offset))
@@ -5910,21 +5853,16 @@ EncodeModule(AstModule& module, Uint32Ve
     Encoder e(*bytes);
 
     if (!e.writeFixedU32(MagicNumber))
         return false;
 
     if (!e.writeFixedU32(EncodingVersion))
         return false;
 
-#ifdef ENABLE_WASM_GC
-    if (!EncodeGcFeatureOptInSection(e, module))
-        return false;
-#endif
-
     if (!EncodeTypeSection(e, module))
         return false;
 
     if (!EncodeImportSection(e, module))
         return false;
 
     if (!EncodeFunctionSection(e, module))
         return false;
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -392,22 +392,22 @@ DecodeValType(Decoder& d, ModuleKind kin
       case uint8_t(ValType::I32):
       case uint8_t(ValType::F32):
       case uint8_t(ValType::F64):
       case uint8_t(ValType::I64):
         *type = ValType(ValType::Code(uncheckedCode));
         return true;
       case uint8_t(ValType::AnyRef):
         if (gcTypesEnabled == HasGcTypes::False)
-            return d.fail("reference types not enabled");
+            break;
         *type = ValType(ValType::Code(uncheckedCode));
         return true;
       case uint8_t(ValType::Ref): {
         if (gcTypesEnabled == HasGcTypes::False)
-            return d.fail("reference types not enabled");
+            break;
         if (uncheckedRefTypeIndex >= numTypes)
             return d.fail("ref index out of range");
         // We further validate ref types in the caller.
         *type = ValType(ValType::Code(uncheckedCode), uncheckedRefTypeIndex);
         return true;
       }
       default:
         break;
@@ -858,24 +858,24 @@ DecodeFunctionBodyExprs(const ModuleEnvi
 #endif
               default:
                 return iter.unrecognizedOpcode(&op);
             }
             break;
           }
 #ifdef ENABLE_WASM_GC
           case uint16_t(Op::RefNull): {
-            if (env.gcTypesEnabled() == HasGcTypes::False)
+            if (env.gcTypesEnabled == HasGcTypes::False)
                 return iter.unrecognizedOpcode(&op);
             ValType unusedType;
             CHECK(iter.readRefNull(&unusedType));
             break;
           }
           case uint16_t(Op::RefIsNull): {
-            if (env.gcTypesEnabled() == HasGcTypes::False)
+            if (env.gcTypesEnabled == HasGcTypes::False)
                 return iter.unrecognizedOpcode(&op);
             CHECK(iter.readConversion(ValType::AnyRef, ValType::I32, &nothing));
             break;
           }
 #endif
           case uint16_t(Op::ThreadPrefix): {
 #ifdef ENABLE_WASM_THREAD_OPS
             switch (op.b1) {
@@ -1065,17 +1065,17 @@ wasm::ValidateFunctionBody(const ModuleE
     const FuncType& funcType = *env.funcTypes[funcIndex];
 
     ValTypeVector locals;
     if (!locals.appendAll(funcType.args()))
         return false;
 
     const uint8_t* bodyBegin = d.currentPosition();
 
-    if (!DecodeLocalEntries(d, ModuleKind::Wasm, env.types, env.gcTypesEnabled(), &locals))
+    if (!DecodeLocalEntries(d, ModuleKind::Wasm, env.types, env.gcTypesEnabled, &locals))
         return false;
 
     if (!DecodeFunctionBodyExprs(env, funcType, locals, bodyBegin + bodySize, &d))
         return false;
 
     return true;
 }
 
@@ -1149,34 +1149,34 @@ DecodeFuncType(Decoder& d, ModuleEnviron
     if (numArgs > MaxParams)
         return d.fail("too many arguments in signature");
 
     ValTypeVector args;
     if (!args.resize(numArgs))
         return false;
 
     for (uint32_t i = 0; i < numArgs; i++) {
-        if (!DecodeValType(d, ModuleKind::Wasm, env->types.length(), env->gcTypesEnabled(), &args[i]))
+        if (!DecodeValType(d, ModuleKind::Wasm, env->types.length(), env->gcTypesEnabled, &args[i]))
             return false;
         if (!ValidateRefType(d, typeState, args[i]))
             return false;
     }
 
     uint32_t numRets;
     if (!d.readVarU32(&numRets))
         return d.fail("bad number of function returns");
 
     if (numRets > 1)
         return d.fail("too many returns in signature");
 
     ExprType result = ExprType::Void;
 
     if (numRets == 1) {
         ValType type;
-        if (!DecodeValType(d, ModuleKind::Wasm, env->types.length(), env->gcTypesEnabled(), &type))
+        if (!DecodeValType(d, ModuleKind::Wasm, env->types.length(), env->gcTypesEnabled, &type))
             return false;
         if (!ValidateRefType(d, typeState, type))
             return false;
 
         result = ExprType(type);
     }
 
     if ((*typeState)[typeIndex] != TypeState::None)
@@ -1186,17 +1186,17 @@ DecodeFuncType(Decoder& d, ModuleEnviron
     (*typeState)[typeIndex] = TypeState::Func;
 
     return true;
 }
 
 static bool
 DecodeStructType(Decoder& d, ModuleEnvironment* env, TypeStateVector* typeState, uint32_t typeIndex)
 {
-    if (env->gcTypesEnabled() == HasGcTypes::False)
+    if (env->gcTypesEnabled == HasGcTypes::False)
         return d.fail("Structure types not enabled");
 
     uint32_t numFields;
     if (!d.readVarU32(&numFields))
         return d.fail("Bad number of fields");
 
     if (numFields > MaxStructFields)
         return d.fail("too many fields in structure");
@@ -1209,59 +1209,31 @@ DecodeStructType(Decoder& d, ModuleEnvir
 
     for (uint32_t i = 0; i < numFields; i++) {
         uint8_t flags;
         if (!d.readFixedU8(&flags))
             return d.fail("expected flag");
         if ((flags & ~uint8_t(FieldFlags::AllowedMask)) != 0)
             return d.fail("garbage flag bits");
         fields[i].isMutable = flags & uint8_t(FieldFlags::Mutable);
-        if (!DecodeValType(d, ModuleKind::Wasm, env->types.length(), env->gcTypesEnabled(), &fields[i].type))
+        if (!DecodeValType(d, ModuleKind::Wasm, env->types.length(), env->gcTypesEnabled, &fields[i].type))
             return false;
         if (!ValidateRefType(d, typeState, fields[i].type))
             return false;
     }
 
     if ((*typeState)[typeIndex] != TypeState::None && (*typeState)[typeIndex] != TypeState::ForwardStruct)
         return d.fail("struct type entry referenced as function");
 
     env->types[typeIndex] = TypeDef(StructType(std::move(fields)));
     (*typeState)[typeIndex] = TypeState::Struct;
 
     return true;
 }
 
-#ifdef ENABLE_WASM_GC
-static bool
-DecodeGCFeatureOptInSection(Decoder& d, ModuleEnvironment* env)
-{
-    MaybeSectionRange range;
-    if (!d.startSection(SectionId::GcFeatureOptIn, env, &range, "type"))
-        return false;
-    if (!range)
-        return true;
-
-    uint32_t version;
-    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
-    //
-    // When we evolve the engine to handle v2, we will continue to recognize v1
-    // here if v2 is fully backwards compatible with v1.
-
-    if (version != 1)
-        return d.fail("unsupported version of the gc feature");
-
-    env->gcFeatureOptIn = HasGcTypes::True;
-    return d.finishSection(*range, "gcfeatureoptin");
-}
-#endif
-
 static bool
 DecodeTypeSection(Decoder& d, ModuleEnvironment* env)
 {
     MaybeSectionRange range;
     if (!d.startSection(SectionId::Type, env, &range, "type"))
         return false;
     if (!range)
         return true;
@@ -1559,17 +1531,17 @@ DecodeImport(Decoder& d, ModuleEnvironme
       case DefinitionKind::Memory: {
         if (!DecodeMemoryLimits(d, env))
             return false;
         break;
       }
       case DefinitionKind::Global: {
         ValType type;
         bool isMutable;
-        if (!DecodeGlobalType(d, env->types, env->gcTypesEnabled(), &type, &isMutable))
+        if (!DecodeGlobalType(d, env->types, env->gcTypesEnabled, &type, &isMutable))
             return false;
         if (!GlobalIsJSCompatible(d, type, isMutable))
             return false;
         if (!env->globals.append(GlobalDesc(type, isMutable, env->globals.length())))
             return false;
         if (env->globals.length() > MaxGlobals)
             return d.fail("too many globals");
         break;
@@ -1791,21 +1763,21 @@ DecodeGlobalSection(Decoder& d, ModuleEn
         return d.fail("too many globals");
 
     if (!env->globals.reserve(numGlobals.value()))
         return false;
 
     for (uint32_t i = 0; i < numDefs; i++) {
         ValType type;
         bool isMutable;
-        if (!DecodeGlobalType(d, env->types, env->gcTypesEnabled(), &type, &isMutable))
+        if (!DecodeGlobalType(d, env->types, env->gcTypesEnabled, &type, &isMutable))
             return false;
 
         InitExpr initializer;
-        if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, type,
+        if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, type,
                                          env->types.length(), &initializer))
         {
             return false;
         }
 
         env->globals.infallibleAppend(GlobalDesc(initializer, isMutable));
     }
 
@@ -1984,17 +1956,17 @@ DecodeElemSection(Decoder& d, ModuleEnvi
         if (!d.readVarU32(&tableIndex))
             return d.fail("expected table index");
 
         MOZ_ASSERT(env->tables.length() <= 1);
         if (tableIndex >= env->tables.length())
             return d.fail("table index out of range");
 
         InitExpr offset;
-        if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, ValType::I32,
+        if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, ValType::I32,
                                          env->types.length(), &offset))
         {
             return false;
         }
 
         uint32_t numElems;
         if (!d.readVarU32(&numElems))
             return d.fail("expected segment size");
@@ -2064,21 +2036,16 @@ wasm::StartsCodeSection(const uint8_t* b
 }
 
 bool
 wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env)
 {
     if (!DecodePreamble(d))
         return false;
 
-#ifdef ENABLE_WASM_GC
-    if (!DecodeGCFeatureOptInSection(d, env))
-        return false;
-#endif
-
     if (!DecodeTypeSection(d, env))
         return false;
 
     if (!DecodeImportSection(d, env))
         return false;
 
     if (!DecodeFunctionSection(d, env))
         return false;
@@ -2176,17 +2143,17 @@ DecodeDataSection(Decoder& d, ModuleEnvi
 
         if (linearMemoryIndex != 0)
             return d.fail("linear memory index must currently be 0");
 
         if (!env->usesMemory())
             return d.fail("data segment requires a memory section");
 
         DataSegment seg;
-        if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, ValType::I32,
+        if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, ValType::I32,
                                          env->types.length(), &seg.offset))
         {
             return false;
         }
 
         if (!d.readVarU32(&seg.length))
             return d.fail("expected segment size");
 
--- a/js/src/wasm/WasmValidate.h
+++ b/js/src/wasm/WasmValidate.h
@@ -55,40 +55,21 @@ typedef Maybe<SectionRange> MaybeSection
 
 struct ModuleEnvironment
 {
     // Constant parameters for the entire compilation:
     const DebugEnabled        debug;
     const ModuleKind          kind;
     const CompileMode         mode;
     const Shareable           sharedMemoryEnabled;
-    // `gcTypesConfigured` reflects the value of the flags --wasm-gc and
-    // javascript.options.wasm_gc.  These flags will disappear eventually, thus
-    // allowing the removal of this variable and its replacement everywhere by
-    // the value HasGcTypes::True.
-    //
-    // For now, the value is used (a) in the value of gcTypesEnabled(), which
-    // controls whether ref types and struct types and associated instructions
-    // are accepted during validation, and (b) to control whether we emit code
-    // to suppress GC while wasm activations are on the stack.
-    const HasGcTypes          gcTypesConfigured;
+    const HasGcTypes          gcTypesEnabled;
     const Tier                tier;
 
     // Module fields decoded from the module environment (or initialized while
     // validating an asm.js module) and immutable during compilation:
-#ifdef ENABLE_WASM_GC
-    // `gcFeatureOptIn` reflects the presence in a module of a GcFeatureOptIn
-    // section.  This variable will be removed eventually, allowing it to be
-    // replaced everywhere by the value HasGcTypes::True.
-    //
-    // The flag is used in the value of gcTypesEnabled(), which controls whether
-    // ref types and struct types and associated instructions are accepted
-    // during validation.
-    HasGcTypes                gcFeatureOptIn;
-#endif
     MemoryUsage               memoryUsage;
     uint32_t                  minMemoryLength;
     Maybe<uint32_t>           maxMemoryLength;
     TypeDefVector             types;
     FuncTypeWithIdPtrVector   funcTypes;
     Uint32Vector              funcImportGlobalDataOffsets;
     GlobalDescVector          globals;
     TableDescVector           tables;
@@ -110,21 +91,18 @@ struct ModuleEnvironment
                                DebugEnabled debug,
                                HasGcTypes hasGcTypes,
                                Shareable sharedMemoryEnabled,
                                ModuleKind kind = ModuleKind::Wasm)
       : debug(debug),
         kind(kind),
         mode(mode),
         sharedMemoryEnabled(sharedMemoryEnabled),
-        gcTypesConfigured(hasGcTypes),
+        gcTypesEnabled(hasGcTypes),
         tier(tier),
-#ifdef ENABLE_WASM_GC
-        gcFeatureOptIn(HasGcTypes::False),
-#endif
         memoryUsage(MemoryUsage::None),
         minMemoryLength(0)
     {}
 
     size_t numTables() const {
         return tables.length();
     }
     size_t numTypes() const {
@@ -134,23 +112,16 @@ struct ModuleEnvironment
         return funcTypes.length();
     }
     size_t numFuncImports() const {
         return funcImportGlobalDataOffsets.length();
     }
     size_t numFuncDefs() const {
         return funcTypes.length() - funcImportGlobalDataOffsets.length();
     }
-#ifdef ENABLE_WASM_GC
-    HasGcTypes gcTypesEnabled() const {
-        if (gcTypesConfigured == HasGcTypes::True)
-            return gcFeatureOptIn;
-        return HasGcTypes::False;
-    }
-#endif
     bool usesMemory() const {
         return memoryUsage != MemoryUsage::None;
     }
     bool usesSharedMemory() const {
         return memoryUsage == MemoryUsage::Shared;
     }
     bool isAsmJS() const {
         return kind == ModuleKind::AsmJS;
@@ -353,17 +324,16 @@ class Encoder
 
     // A "section" is a contiguous range of bytes that stores its own size so
     // that it may be trivially skipped without examining the contents. Sections
     // require backpatching since the size of the section is only known at the
     // end while the size's varU32 must be stored at the beginning. Immediately
     // after the section length is the string id of the section.
 
     MOZ_MUST_USE bool startSection(SectionId id, size_t* offset) {
-        MOZ_ASSERT(uint32_t(id) < 128);
         return writeVarU32(uint32_t(id)) &&
                writePatchableVarU32(offset);
     }
     void finishSection(size_t offset) {
         return patchVarU32(offset, bytes_.length() - offset - varU32ByteLength(offset));
     }
 };