Repository: bytecodealliance/wasmtime
Pull request #8808 (2024-06-14 18:21:50)

Disable `call-hook` crate feature by default
This commit disables the `call-hook` feature for the Wasmtime crate added in #8795 by default. The rationale is that this has a slight cost to all embeddings even if the feature isn't used and it's not expected to be that widely used of a feature, so off-by-default seems like a more appropriate default.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index b86ca3ccb..83f915183 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -297,16 +297,14 @@ jobs:
     - run: (cd docs && mdbook test -L ../target/debug/deps)
 
     # Build Rust API documentation.
-    # We pass in the `component-model` feature
-    # to match the docs.rs metadata in
-    # crates/wasmtime/Cargo.toml.
+    #
+    # Enable extra features in crates as well to ensure they're documented
     - run: |
         cargo doc --no-deps --workspace \
           --exclude wasmtime-cli \
           --exclude test-programs \
-          --exclude wasi-http-tests \
           --exclude cranelift-codegen-meta \
-          --features component-model
+          --features call-hook
       env:
         RUSTDOCFLAGS: --cfg=docsrs
     - run: cargo doc --package cranelift-codegen-meta --document-private-items
diff --git a/Cargo.toml b/Cargo.toml
index 38611f585..3f3115cd3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -82,7 +82,7 @@ rustix = { workspace = true, features = ["mm", "param", "process"] }
 
 [dev-dependencies]
 # depend again on wasmtime to activate its default features for tests
-wasmtime = { workspace = true, features = ['component-model', 'async', 'default', 'winch', 'debug-builtins', 'all-arch'] }
+wasmtime = { workspace = true, features = ['default', 'winch', 'all-arch', 'call-hook'] }
 env_logger = { workspace = true }
 log = { workspace = true }
 filecheck = { workspace = true }
diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs
index 909f80160..6019ce2d2 100644
--- a/cranelift/codegen/meta/src/shared/instructions.rs
+++ b/cranelift/codegen/meta/src/shared/instructions.rs
@@ -144,20 +144,6 @@ fn define_control_flow(
         .can_trap(),
     );
 
-    ig.push(
-        Inst::new(
-            "resumable_trap",
-            r#"
-        A resumable trap.
-
-        This instruction allows non-conditional traps to be used as non-terminal instructions.
-        "#,
-            &formats.trap,
-        )
-        .operands_in(vec![Operand::new("code", &imm.trapcode)])
-        .can_trap(),
-    );
-
     ig.push(
         Inst::new(
             "trapnz",
@@ -175,23 +161,6 @@ fn define_control_flow(
         .can_trap(),
     );
 
-    ig.push(
-        Inst::new(
-            "resumable_trapnz",
-            r#"
-        A resumable trap to be called when the passed condition is non-zero.
-
-        If ``c`` is zero, execution continues at the following instruction.
-        "#,
-            &formats.cond_trap,
-        )
-        .operands_in(vec![
-            Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
-            Operand::new("code", &imm.trapcode),
-        ])
-        .can_trap(),
-    );
-
     ig.push(
         Inst::new(
             "return",
diff --git a/cranelift/codegen/src/ir/instructions.rs b/cranelift/codegen/src/ir/instructions.rs
index 9b72e239b..9a9254264 100644
--- a/cranelift/codegen/src/ir/instructions.rs
+++ b/cranelift/codegen/src/ir/instructions.rs
@@ -193,14 +193,6 @@ impl Opcode {
     pub fn constraints(self) -> OpcodeConstraints {
         OPCODE_CONSTRAINTS[self as usize - 1]
     }
-
-    /// Returns true if the instruction is a resumable trap.
-    pub fn is_resumable_trap(&self) -> bool {
-        match self {
-            Opcode::ResumableTrap | Opcode::ResumableTrapnz => true,
-            _ => false,
-        }
-    }
 }
 
 // This trait really belongs in cranelift-reader where it is used by the `.clif` file parser, but since
diff --git a/cranelift/codegen/src/ir/trapcode.rs b/cranelift/codegen/src/ir/trapcode.rs
index fc31e3d2a..3ac4953d2 100644
--- a/cranelift/codegen/src/ir/trapcode.rs
+++ b/cranelift/codegen/src/ir/trapcode.rs
@@ -46,7 +46,6 @@ pub enum TrapCode {
     UnreachableCodeReached,
 
     /// Execution has potentially run too long and may be interrupted.
-    /// This trap is resumable.
     Interrupt,
 
     /// A user-defined trap code.
diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs
index 6fc2a9598..54e2a4f77 100644
--- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs
@@ -1114,10 +1114,7 @@ impl MachInst for Inst {
 
     fn is_safepoint(&self) -> bool {
         match self {
-            &Inst::Call { .. }
-            | &Inst::CallInd { .. }
-            | &Inst::TrapIf { .. }
-            | &Inst::Udf { .. } => true,
+            Inst::Call { .. } | Inst::CallInd { .. } => true,
             _ => false,
         }
     }
diff --git a/cranelift/codegen/src/isa/aarch64/lower.isle b/cranelift/codegen/src/isa/aarch64/lower.isle
index dc7ed36e4..5fd9bf67e 100644
--- a/cranelift/codegen/src/isa/aarch64/lower.isle
+++ b/cranelift/codegen/src/isa/aarch64/lower.isle
@@ -1936,11 +1936,6 @@
 (rule (lower (trap trap_code))
       (side_effect (udf trap_code)))
 
-;;;; Rules for `resumable_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(rule (lower (resumable_trap trap_code))
-      (side_effect (udf trap_code)))
-
 ;;;; Rules for `select` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (rule (lower (has_type ty
diff --git a/cranelift/codegen/src/isa/riscv64/inst/mod.rs b/cranelift/codegen/src/isa/riscv64/inst/mod.rs
index eee4af1cc..a846c6024 100644
--- a/cranelift/codegen/src/isa/riscv64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/riscv64/inst/mod.rs
@@ -731,10 +731,7 @@ impl MachInst for Inst {
 
     fn is_safepoint(&self) -> bool {
         match self {
-            &Inst::Call { .. }
-            | &Inst::CallInd { .. }
-            | &Inst::TrapIf { .. }
-            | &Inst::Udf { .. } => true,
+            Inst::Call { .. } | Inst::CallInd { .. } => true,
             _ => false,
         }
     }
diff --git a/cranelift/codegen/src/isa/riscv64/lower.isle b/cranelift/codegen/src/isa/riscv64/lower.isle
index 2e10a253a..d287e0c7b 100644
--- a/cranelift/codegen/src/isa/riscv64/lower.isle
+++ b/cranelift/codegen/src/isa/riscv64/lower.isle
@@ -2027,11 +2027,6 @@
   (lower (trap code))
   (udf code))
 
-;;;;;  Rules for `resumable_trap`;;;;;;;;;
-(rule
-  (lower (resumable_trap code))
-  (udf code))
-
 ;;;;;  Rules for `uload8`;;;;;;;;;
 (rule (lower (uload8 flags addr offset))
   (gen_load (amode addr offset) (LoadOP.Lbu) flags))
diff --git a/cranelift/codegen/src/isa/s390x/inst/mod.rs b/cranelift/codegen/src/isa/s390x/inst/mod.rs
index b9550a983..6b1d9f531 100644
--- a/cranelift/codegen/src/isa/s390x/inst/mod.rs
+++ b/cranelift/codegen/src/isa/s390x/inst/mod.rs
@@ -1073,13 +1073,7 @@ impl MachInst for Inst {
 
     fn is_safepoint(&self) -> bool {
         match self {
-            &Inst::Call { .. }
-            | &Inst::CallInd { .. }
-            | &Inst::Trap { .. }
-            | Inst::TrapIf { .. }
-            | &Inst::CmpTrapRR { .. }
-            | &Inst::CmpTrapRSImm16 { .. }
-            | &Inst::CmpTrapRUImm16 { .. } => true,
+            Inst::Call { .. } | Inst::CallInd { .. } => true,
             _ => false,
         }
     }
diff --git a/cranelift/codegen/src/isa/s390x/lower.isle b/cranelift/codegen/src/isa/s390x/lower.isle
index 40f748302..977a28c02 100644
--- a/cranelift/codegen/src/isa/s390x/lower.isle
+++ b/cranelift/codegen/src/isa/s390x/lower.isle
@@ -3800,12 +3800,6 @@
       (side_effect (trap_impl trap_code)))
 
 
-;;;; Rules for `resumable_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(rule (lower (resumable_trap trap_code))
-      (side_effect (trap_impl trap_code)))
-
-
 ;;;; Rules for `trapz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (rule (lower (trapz val trap_code))
@@ -3818,12 +3812,6 @@
       (side_effect (trap_if_bool (value_nonzero val) trap_code)))
 
 
-;;;; Rules for `resumable_trapnz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(rule (lower (resumable_trapnz val trap_code))
-      (side_effect (trap_if_bool (value_nonzero val) trap_code)))
-
-
 ;;;; Rules for `debugtrap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (rule (lower (debugtrap))
diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs
index 34e6647f6..fd8c375e6 100644
--- a/cranelift/codegen/src/isa/x64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/x64/inst/mod.rs
@@ -2687,10 +2687,7 @@ impl MachInst for Inst {
 
     fn is_safepoint(&self) -> bool {
         match self {
-            Inst::CallKnown { .. }
-            | Inst::CallUnknown { .. }
-            | Inst::TrapIf { .. }
-            | Inst::Ud2 { .. } => true,
+            Inst::CallKnown { .. } | Inst::CallUnknown { .. } => true,
             _ => false,
         }
     }
diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle
index 9857f8dd2..92d8b7478 100644
--- a/cranelift/codegen/src/isa/x64/lower.isle
+++ b/cranelift/codegen/src/isa/x64/lower.isle
@@ -1821,11 +1821,6 @@
         (x64_add_with_flags_paired ty b a)
         (trap_if (CC.B) tc)))
 
-;;;; Rules for `resumable_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(rule (lower (resumable_trap code))
-      (side_effect (x64_ud2 code)))
-
 ;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 ;; N.B.: the Ret itself is generated by the ABI.
diff --git a/cranelift/codegen/src/legalizer/mod.rs b/cranelift/codegen/src/legalizer/mod.rs
index b8de7bcd7..fb14a5d8f 100644
--- a/cranelift/codegen/src/legalizer/mod.rs
+++ b/cranelift/codegen/src/legalizer/mod.rs
@@ -64,8 +64,7 @@ pub fn simple_legalize(func: &mut ir::Function, cfg: &mut ControlFlowGraph, isa:
             match pos.func.dfg.insts[inst] {
                 // control flow
                 InstructionData::CondTrap {
-                    opcode:
-                        opcode @ (ir::Opcode::Trapnz | ir::Opcode::Trapz | ir::Opcode::ResumableTrapnz),
+                    opcode: opcode @ (ir::Opcode::Trapnz | ir::Opcode::Trapz),
                     arg,
                     code,
                 } => {
@@ -283,7 +282,7 @@ fn expand_cond_trap(
     // Parse the instruction.
     let trapz = match opcode {
         ir::Opcode::Trapz => true,
-        ir::Opcode::Trapnz | ir::Opcode::ResumableTrapnz => false,
+        ir::Opcode::Trapnz => false,
         _ => panic!("Expected cond trap: {}", func.dfg.display_inst(inst)),
     };
 
@@ -331,10 +330,6 @@ fn expand_cond_trap(
         ir::Opcode::Trapz | ir::Opcode::Trapnz => {
             pos.ins().trap(code);
         }
-        ir::Opcode::ResumableTrapnz => {
-            pos.ins().resumable_trap(code);
-            pos.ins().jump(new_block_resume, &[]);
-        }
         _ => unreachable!(),
     }
 
diff --git a/cranelift/fuzzgen/src/function_generator.rs b/cranelift/fuzzgen/src/function_generator.rs
index 31d3cea93..af345c73b 100644
--- a/cranelift/fuzzgen/src/function_generator.rs
+++ b/cranelift/fuzzgen/src/function_generator.rs
@@ -888,9 +888,7 @@ static OPCODE_SIGNATURES: Lazy<Vec<OpcodeSignature>> = Lazy::new(|| {
                 (Opcode::Debugtrap),
                 (Opcode::Trap),
                 (Opcode::Trapz),
-                (Opcode::ResumableTrap),
                 (Opcode::Trapnz),
-                (Opcode::ResumableTrapnz),
                 (Opcode::CallIndirect, &[I32]),
                 (Opcode::FuncAddr),
                 (Opcode::X86Pshufb),
diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs
index 96d465966..bb9703bfc 100644
--- a/cranelift/interpreter/src/step.rs
+++ b/cranelift/interpreter/src/step.rs
@@ -353,10 +353,8 @@ where
         }
         Opcode::Trap => ControlFlow::Trap(CraneliftTrap::User(trap_code())),
         Opcode::Debugtrap => ControlFlow::Trap(CraneliftTrap::Debug),
-        Opcode::ResumableTrap => ControlFlow::Trap(CraneliftTrap::Resumable),
         Opcode::Trapz => trap_when(!arg(0).into_bool()?, CraneliftTrap::User(trap_code())),
         Opcode::Trapnz => trap_when(arg(0).into_bool()?, CraneliftTrap::User(trap_code())),
-        Opcode::ResumableTrapnz => trap_when(arg(0).into_bool()?, CraneliftTrap::Resumable),
         Opcode::Return => ControlFlow::Return(args()),
         Opcode::Call | Opcode::ReturnCall => {
             let func_ref = if let InstructionData::Call { func_ref, .. } = inst {
@@ -1330,8 +1328,6 @@ pub enum CraneliftTrap {
     User(TrapCode),
     #[error("user debug")]
     Debug,
-    #[error("resumable")]
-    Resumable,
 }
 
 /// Compare two values using the given integer condition `code`.
diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs
index a4ed9a0c4..bb44575bd 100644
--- a/crates/cranelift/src/compiler.rs
+++ b/crates/cranelift/src/compiler.rs
@@ -193,9 +193,7 @@ impl wasmtime_environ::Compiler for Compiler {
             .create_global_value(ir::GlobalValueData::VMContext);
         let interrupts_ptr = context.func.create_global_value(ir::GlobalValueData::Load {
             base: vmctx,
-            offset: i32::try_from(func_env.offsets.vmctx_runtime_limits())
-                .unwrap()
-                .into(),
+            offset: i32::from(func_env.offsets.ptr.vmctx_runtime_limits()).into(),
             global_type: isa.pointer_type(),
             flags: MemFlags::trusted().with_readonly(),
         });
@@ -282,12 +280,12 @@ impl wasmtime_environ::Compiler for Compiler {
         // what we are assuming with our offsets below.
         debug_assert_vmctx_kind(isa, &mut builder, vmctx, wasmtime_environ::VMCONTEXT_MAGIC);
         let offsets = VMOffsets::new(isa.pointer_bytes(), &translation.module);
-        let vm_runtime_limits_offset = offsets.vmctx_runtime_limits();
+        let vm_runtime_limits_offset = offsets.ptr.vmctx_runtime_limits();
         save_last_wasm_entry_sp(
             &mut builder,
             pointer_type,
             &offsets.ptr,
-            vm_runtime_limits_offset,
+            vm_runtime_limits_offset.into(),
             vmctx,
         );
 
diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs
index 8adf82454..0dbffa4b4 100644
--- a/crates/cranelift/src/func_environ.rs
+++ b/crates/cranelift/src/func_environ.rs
@@ -287,7 +287,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
         let pointer_type = self.pointer_type();
         let vmctx = self.vmctx(builder.func);
         let base = builder.ins().global_value(pointer_type, vmctx);
-        let offset = i32::try_from(self.offsets.vmctx_runtime_limits()).unwrap();
+        let offset = i32::from(self.offsets.ptr.vmctx_runtime_limits());
         debug_assert!(self.vmruntime_limits_ptr.is_reserved_value());
         self.vmruntime_limits_ptr =
             builder
@@ -580,7 +580,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
         let vmctx = self.vmctx(builder.func);
         let pointer_type = self.pointer_type();
         let base = builder.ins().global_value(pointer_type, vmctx);
-        let offset = i32::try_from(self.offsets.vmctx_epoch_ptr()).unwrap();
+        let offset = i32::try_from(self.offsets.ptr.vmctx_epoch_ptr()).unwrap();
         let epoch_ptr = builder
             .ins()
             .load(pointer_type, ir::MemFlags::trusted(), base, offset);
@@ -1518,7 +1518,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
             pointer_type,
             mem_flags,
             base,
-            i32::try_from(self.env.offsets.vmctx_type_ids_array()).unwrap(),
+            i32::from(self.env.offsets.ptr.vmctx_type_ids_array()),
         );
         let sig_index = self.env.module.types[ty_index];
         let offset =
diff --git a/crates/cranelift/src/gc/enabled.rs b/crates/cranelift/src/gc/enabled.rs
index 00aefbb1e..e610e57a2 100644
--- a/crates/cranelift/src/gc/enabled.rs
+++ b/crates/cranelift/src/gc/enabled.rs
@@ -5,7 +5,7 @@ use cranelift_frontend::FunctionBuilder;
 use cranelift_wasm::{
     TargetEnvironment, WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult, WasmValType,
 };
-use wasmtime_environ::{I31_DISCRIMINANT, NON_NULL_NON_I31_MASK};
+use wasmtime_environ::{PtrSize, I31_DISCRIMINANT, NON_NULL_NON_I31_MASK};
 
 /// Get the default GC compiler.
 pub fn gc_compiler(_func_env: &FuncEnvironment<'_>) -> Box<dyn GcCompiler> {
@@ -97,11 +97,11 @@ impl FuncEnvironment<'_> {
         let vmctx = self.vmctx(builder.func);
         let vmctx = builder.ins().global_value(ptr_ty, vmctx);
 
-        let base_offset = self.offsets.vmctx_gc_heap_base();
-        let base_offset = i32::try_from(base_offset).unwrap();
+        let base_offset = self.offsets.ptr.vmctx_gc_heap_base();
+        let base_offset = i32::from(base_offset);
 
-        let bound_offset = self.offsets.vmctx_gc_heap_bound();
-        let bound_offset = i32::try_from(bound_offset).unwrap();
+        let bound_offset = self.offsets.ptr.vmctx_gc_heap_bound();
+        let bound_offset = i32::from(bound_offset);
 
         let base = builder.ins().load(ptr_ty, flags, vmctx, base_offset);
         let bound = builder.ins().load(ptr_ty, flags, vmctx, bound_offset);
@@ -289,7 +289,7 @@ impl DrcCompiler {
             ptr_ty,
             ir::MemFlags::trusted(),
             vmctx,
-            i32::try_from(func_env.offsets.vmctx_gc_heap_data()).unwrap(),
+            i32::from(func_env.offsets.ptr.vmctx_gc_heap_data()),
         );
         let next = builder.ins().load(
             ptr_ty,
diff --git a/crates/environ/src/vmoffsets.rs b/crates/environ/src/vmoffsets.rs
index 569e3e5ff..d913f2d62 100644
--- a/crates/environ/src/vmoffsets.rs
+++ b/crates/environ/src/vmoffsets.rs
@@ -7,8 +7,9 @@
 //      magic: u32,
 //      _padding: u32, // (On 64-bit systems)
 //      runtime_limits: *const VMRuntimeLimits,
-//      builtins: *mut VMBuiltinFunctionsArray,
+//      builtin_functions: *mut VMBuiltinFunctionsArray,
 //      callee: *mut VMFunctionBody,
+//      epoch_ptr: *mut AtomicU64,
 //      gc_heap_base: *mut u8,
 //      gc_heap_bound: *mut u8,
 //      gc_heap_data: *mut T, // Collector-specific pointer
@@ -77,16 +78,6 @@ pub struct VMOffsets<P> {
     pub num_call_indirect_caches: u32,
 
     // precalculated offsets of various member fields
-    magic: u32,
-    runtime_limits: u32,
-    builtin_functions: u32,
-    callee: u32,
-    epoch_ptr: u32,
-    gc_heap_base: u32,
-    gc_heap_bound: u32,
-    gc_heap_data: u32,
-    store: u32,
-    type_ids: u32,
     imported_functions: u32,
     imported_tables: u32,
     imported_memories: u32,
@@ -244,6 +235,81 @@ pub trait PtrSize {
     fn size_of_vmcall_indirect_cache(&self) -> u8 {
         2 * self.size()
     }
+
+    /// Return the offset to the `magic` value in this `VMContext`.
+    #[inline]
+    fn vmctx_magic(&self) -> u8 {
+        // This is required by the implementation of `VMContext::instance` and
+        // `VMContext::instance_mut`. If this value changes then those locations
+        // need to be updated.
+        0
+    }
+
+    /// Return the offset to the `VMRuntimeLimits` structure
+    #[inline]
+    fn vmctx_runtime_limits(&self) -> u8 {
+        self.vmctx_magic() + self.size()
+    }
+
+    /// Return the offset to the `VMBuiltinFunctionsArray` structure
+    #[inline]
+    fn vmctx_builtin_functions(&self) -> u8 {
+        self.vmctx_runtime_limits() + self.size()
+    }
+
+    /// Return the offset to the `callee` member in this `VMContext`.
+    #[inline]
+    fn vmctx_callee(&self) -> u8 {
+        self.vmctx_builtin_functions() + self.size()
+    }
+
+    /// Return the offset to the `*const AtomicU64` epoch-counter
+    /// pointer.
+    #[inline]
+    fn vmctx_epoch_ptr(&self) -> u8 {
+        self.vmctx_callee() + self.size()
+    }
+
+    /// Return the offset to the GC heap base in this `VMContext`.
+    #[inline]
+    fn vmctx_gc_heap_base(&self) -> u8 {
+        self.vmctx_epoch_ptr() + self.size()
+    }
+
+    /// Return the offset to the GC heap bound in this `VMContext`.
+    #[inline]
+    fn vmctx_gc_heap_bound(&self) -> u8 {
+        self.vmctx_gc_heap_base() + self.size()
+    }
+
+    /// Return the offset to the `*mut T` collector-specific data.
+    ///
+    /// This is a pointer that different collectors can use however they see
+    /// fit.
+    #[inline]
+    fn vmctx_gc_heap_data(&self) -> u8 {
+        self.vmctx_gc_heap_bound() + self.size()
+    }
+
+    /// The offset of the `*const dyn Store` member.
+    #[inline]
+    fn vmctx_store(&self) -> u8 {
+        self.vmctx_gc_heap_data() + self.size()
+    }
+
+    /// The offset of the `type_ids` array pointer.
+    #[inline]
+    fn vmctx_type_ids_array(&self) -> u8 {
+        self.vmctx_store() + 2 * self.size()
+    }
+
+    /// The end of statically known offsets in `VMContext`.
+    ///
+    /// Data after this is dynamically sized.
+    #[inline]
+    fn vmctx_dynamic_data_start(&self) -> u8 {
+        self.vmctx_type_ids_array() + self.size()
+    }
 }
 
 /// Type representing the size of a pointer for the current compilation host
@@ -366,8 +432,11 @@ impl<P: PtrSize> VMOffsets<P> {
                     let $name = last - $name;
                     last = tmp;
                 )*
-                assert_eq!(last, 0);
-                IntoIterator::into_iter([$(($desc, $name),)*])
+                assert_ne!(last, 0);
+                IntoIterator::into_iter([
+                    $(($desc, $name),)*
+                    ("static vmctx data", last),
+                ])
             }};
         }
 
@@ -382,16 +451,6 @@ impl<P: PtrSize> VMOffsets<P> {
             imported_memories: "imported memories",
             imported_tables: "imported tables",
             imported_functions: "imported functions",
-            type_ids: "module types",
-            store: "jit store state",
-            gc_heap_data: "GC implementation-specific data",
-            gc_heap_bound: "GC heap bound",
-            gc_heap_base: "GC heap base",
-            epoch_ptr: "jit current epoch state",
-            callee: "callee function pointer",
-            builtin_functions: "jit builtin functions state",
-            runtime_limits: "jit runtime limits state",
-            magic: "magic value",
         }
     }
 }
@@ -410,16 +469,6 @@ impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
             num_defined_globals: fields.num_defined_globals,
             num_escaped_funcs: fields.num_escaped_funcs,
             num_call_indirect_caches: fields.num_call_indirect_caches,
-            magic: 0,
-            runtime_limits: 0,
-            builtin_functions: 0,
-            callee: 0,
-            epoch_ptr: 0,
-            gc_heap_base: 0,
-            gc_heap_bound: 0,
-            gc_heap_data: 0,
-            store: 0,
-            type_ids: 0,
             imported_functions: 0,
             imported_tables: 0,
             imported_memories: 0,
@@ -447,7 +496,7 @@ impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
             count.checked_mul(u32::from(size)).unwrap()
         }
 
-        let mut next_field_offset = 0;
+        let mut next_field_offset = u32::from(ret.ptr.vmctx_dynamic_data_start());
 
         macro_rules! fields {
             (size($field:ident) = $size:expr, $($rest:tt)*) => {
@@ -463,17 +512,6 @@ impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
         }
 
         fields! {
-            size(magic) = 4u32,
-            align(u32::from(ret.ptr.size())),
-            size(runtime_limits) = ret.ptr.size(),
-            size(builtin_functions) = ret.ptr.size(),
-            size(callee) = ret.ptr.size(),
-            size(epoch_ptr) = ret.ptr.size(),
-            size(gc_heap_base) = ret.ptr.size(),
-            size(gc_heap_bound) = ret.ptr.size(),
-            size(gc_heap_data) = ret.ptr.size(),
-            size(store) = ret.ptr.size() * 2,
-            size(type_ids) = ret.ptr.size(),
             size(imported_functions)
                 = cmul(ret.num_imported_functions, ret.size_of_vmfunction_import()),
             size(imported_tables)
@@ -503,11 +541,6 @@ impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
 
         ret.size = next_field_offset;
 
-        // This is required by the implementation of `VMContext::instance` and
-        // `VMContext::instance_mut`. If this value changes then those locations
-        // need to be updated.
-        assert_eq!(ret.magic, 0);
-
         return ret;
     }
 }
@@ -640,63 +673,6 @@ impl<P: PtrSize> VMOffsets<P> {
 
 /// Offsets for `VMContext`.
 impl<P: PtrSize> VMOffsets<P> {
-    /// Return the offset to the `magic` value in this `VMContext`.
-    #[inline]
-    pub fn vmctx_magic(&self) -> u32 {
-        self.magic
-    }
-
-    /// Return the offset to the `VMRuntimeLimits` structure
-    #[inline]
-    pub fn vmctx_runtime_limits(&self) -> u32 {
-        self.runtime_limits
-    }
-
-    /// Return the offset to the `callee` member in this `VMContext`.
-    pub fn vmctx_callee(&self) -> u32 {
-        self.callee
-    }
-
-    /// Return the offset to the `*const AtomicU64` epoch-counter
-    /// pointer.
-    #[inline]
-    pub fn vmctx_epoch_ptr(&self) -> u32 {
-        self.epoch_ptr
-    }
-
-    /// Return the offset to the GC heap base in this `VMContext`.
-    #[inline]
-    pub fn vmctx_gc_heap_base(&self) -> u32 {
-        self.gc_heap_base
-    }
-
-    /// Return the offset to the GC heap bound in this `VMContext`.
-    #[inline]
-    pub fn vmctx_gc_heap_bound(&self) -> u32 {
-        self.gc_heap_bound
-    }
-
-    /// Return the offset to the `*mut T` collector-specific data.
-    ///
-    /// This is a pointer that different collectors can use however they see
-    /// fit.
-    #[inline]
-    pub fn vmctx_gc_heap_data(&self) -> u32 {
-        self.gc_heap_data
-    }
-
-    /// The offset of the `*const dyn Store` member.
-    #[inline]
-    pub fn vmctx_store(&self) -> u32 {
-        self.store
-    }
-
-    /// The offset of the `type_ids` array pointer.
-    #[inline]
-    pub fn vmctx_type_ids_array(&self) -> u32 {
-        self.type_ids
-    }
-
     /// The offset of the `tables` array.
     #[inline]
     pub fn vmctx_imported_functions_begin(&self) -> u32 {
@@ -751,12 +727,6 @@ impl<P: PtrSize> VMOffsets<P> {
         self.defined_func_refs
     }
 
-    /// The offset of the builtin functions array.
-    #[inline]
-    pub fn vmctx_builtin_functions(&self) -> u32 {
-        self.builtin_functions
-    }
-
     /// The offset of the `call_indirect_caches` array.
     #[inline]
     pub fn vmctx_call_indirec_caches_begin(&self) -> u32 {
diff --git a/crates/wasi-preview1-component-adapter/Cargo.toml b/crates/wasi-preview1-component-adapter/Cargo.toml
index d8b3959ad..583a87989 100644
--- a/crates/wasi-preview1-component-adapter/Cargo.toml
+++ b/crates/wasi-preview1-component-adapter/Cargo.toml
@@ -22,6 +22,7 @@ object = { workspace = true, default-features = false, features = ["archive", "s
 test = false
 crate-type = ["cdylib"]
 name = "wasi_snapshot_preview1"
+doc = false
 
 [features]
 default = ["reactor"]
diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml
index cb21b24e6..7a8aa7766 100644
--- a/crates/wasmtime/Cargo.toml
+++ b/crates/wasmtime/Cargo.toml
@@ -125,7 +125,6 @@ default = [
   'component-model',
   'threads',
   'std',
-  'call-hook',
 ]
 
 # An on-by-default feature enabling runtime compilation of WebAssembly modules
@@ -263,6 +262,5 @@ std = [
 
 # Enables support for the `Store::call_hook` API which enables injecting custom
 # logic around all entries/exits from WebAssembly. This has a slight performance
-# cost for all host functions so is provided as a compile-time feature if
-# embedders would like to disable it.
+# cost for all host functions.
 call-hook = []
diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs
index 749447bc8..baed60ec0 100644
--- a/crates/wasmtime/src/lib.rs
+++ b/crates/wasmtime/src/lib.rs
@@ -254,7 +254,7 @@
 //! * `threads` - Enabled by default, this enables compile-time support for the
 //!   WebAssembly `threads` proposal, notably shared memories.
 //!
-//! * `call-hook` - Enabled by default, this enables support for the
+//! * `call-hook` - Disabled by default, this enables support for the
 //!   [`Store::call_hook`] API. This incurs a small overhead on all
 //!   entries/exits from WebAssembly and may want to be disabled by some
 //!   embedders.
diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs
index 2beb9b16d..e4e35ebb6 100644
--- a/crates/wasmtime/src/runtime/func.rs
+++ b/crates/wasmtime/src/runtime/func.rs
@@ -1704,6 +1704,8 @@ pub unsafe trait WasmRet {
 
     #[doc(hidden)]
     fn func_type(engine: &Engine, params: impl Iterator<Item = ValType>) -> FuncType;
+    #[doc(hidden)]
+    fn may_gc() -> bool;
 
     // Utilities used to convert an instance of this type to a `Result`
     // explicitly, used when wrapping async functions which always bottom-out
@@ -1735,6 +1737,10 @@ where
         <Self as WasmTy>::store(self, store, ptr.get_unchecked_mut(0))
     }
 
+    fn may_gc() -> bool {
+        T::may_gc()
+    }
+
     fn func_type(engine: &Engine, params: impl Iterator<Item = ValType>) -> FuncType {
         FuncType::new(engine, params, Some(<Self as WasmTy>::valtype()))
     }
@@ -1769,6 +1775,10 @@ where
         self.and_then(|val| val.store(store, ptr))
     }
 
+    fn may_gc() -> bool {
+        T::may_gc()
+    }
+
     fn func_type(engine: &Engine, params: impl Iterator<Item = ValType>) -> FuncType {
         T::func_type(engine, params)
     }
@@ -1814,6 +1824,11 @@ macro_rules! impl_wasm_host_results {
                 Ok(())
             }
 
+            #[doc(hidden)]
+            fn may_gc() -> bool {
+                $( $t::may_gc() || )* false
+            }
+
             fn func_type(engine: &Engine, params: impl Iterator<Item = ValType>) -> FuncType {
                 FuncType::new(
                     engine,
@@ -1937,6 +1952,9 @@ pub unsafe trait WasmTyList {
     // valid for this given type.
     #[doc(hidden)]
     unsafe fn load(store: &mut AutoAssertNoGc<'_>, values: &mut [MaybeUninit<ValRaw>]) -> Self;
+
+    #[doc(hidden)]
+    fn may_gc() -> bool;
 }
 
 macro_rules! impl_wasm_ty_list {
@@ -1959,6 +1977,10 @@ macro_rules! impl_wasm_ty_list {
                     $args::load(_store, ptr)
                 },)*)
             }
+
+            fn may_gc() -> bool {
+                $( $args::may_gc() || )* false
+            }
         }
     });
 }
@@ -2220,7 +2242,11 @@ impl HostContext {
                     break 'ret R::fallible_from_error(trap);
                 }
 
-                let mut store = AutoAssertNoGc::new(caller.store.0);
+                let mut store = if P::may_gc() {
+                    AutoAssertNoGc::new(caller.store.0)
+                } else {
+                    unsafe { AutoAssertNoGc::disabled(caller.store.0) }
+                };
                 let params = P::load(&mut store, args);
                 let _ = &mut store;
                 drop(store);
@@ -2235,7 +2261,11 @@ impl HostContext {
             if !ret.compatible_with_store(caller.store.0) {
                 bail!("host function attempted to return cross-`Store` value to Wasm")
             } else {
-                let mut store = AutoAssertNoGc::new(&mut **caller.store.0);
+                let mut store = if R::may_gc() {
+                    AutoAssertNoGc::new(caller.store.0)
+                } else {
+                    unsafe { AutoAssertNoGc::disabled(caller.store.0) }
+                };
                 let ret = ret.store(&mut store, args)?;
                 Ok(ret)
             }
diff --git a/crates/wasmtime/src/runtime/func/typed.rs b/crates/wasmtime/src/runtime/func/typed.rs
index f30b9e7a8..f021909ae 100644
--- a/crates/wasmtime/src/runtime/func/typed.rs
+++ b/crates/wasmtime/src/runtime/func/typed.rs
@@ -315,6 +315,14 @@ pub unsafe trait WasmTy: Send {
     #[doc(hidden)]
     fn valtype() -> ValType;
 
+    #[doc(hidden)]
+    fn may_gc() -> bool {
+        match Self::valtype() {
+            ValType::Ref(_) => true,
+            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => false,
+        }
+    }
+
     // Dynamic checks that this value is being used with the correct store
     // context.
     #[doc(hidden)]
diff --git a/crates/wasmtime/src/runtime/gc/enabled/rooting.rs b/crates/wasmtime/src/runtime/gc/enabled/rooting.rs
index 9b465787e..74fe5be87 100644
--- a/crates/wasmtime/src/runtime/gc/enabled/rooting.rs
+++ b/crates/wasmtime/src/runtime/gc/enabled/rooting.rs
@@ -407,9 +407,7 @@ impl RootSet {
     /// Calls to `{enter,exit}_lifo_scope` must happen in a strict LIFO order.
     #[inline]
     pub(crate) fn enter_lifo_scope(&self) -> usize {
-        let len = self.lifo_roots.len();
-        log::debug!("Entering GC root set LIFO scope: {len}");
-        len
+        self.lifo_roots.len()
     }
 
     /// Exit a LIFO rooting scope.
@@ -420,7 +418,6 @@ impl RootSet {
     /// Calls to `{enter,exit}_lifo_scope` must happen in a strict LIFO order.
     #[inline]
     pub(crate) fn exit_lifo_scope(&mut self, gc_store: &mut GcStore, scope: usize) {
-        log::debug!("Exiting GC root set LIFO scope: {scope}");
         debug_assert!(self.lifo_roots.len() >= scope);
 
         // If we actually have roots to unroot, call an out-of-line slow path.
diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs
index f2e2bf116..16eb424d2 100644
--- a/crates/wasmtime/src/runtime/store.rs
+++ b/crates/wasmtime/src/runtime/store.rs
@@ -420,6 +420,29 @@ impl<'a> AutoAssertNoGc<'a> {
 
         AutoAssertNoGc { store, entered }
     }
+
+    /// Creates an `AutoAssertNoGc` value which is forcibly "not entered" and
+    /// disables checks for no GC happening for the duration of this value.
+    ///
+    /// This is used when it is statically otherwise known that a GC doesn't
+    /// happen for the various types involved.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is `unsafe` as it does not provide the same safety
+    /// guarantees as `AutoAssertNoGc::new`. It must be guaranteed by the
+    /// caller that a GC doesn't happen.
+    #[inline]
+    pub unsafe fn disabled(store: &'a mut StoreOpaque) -> Self {
+        if cfg!(debug_assertions) {
+            AutoAssertNoGc::new(store)
+        } else {
+            AutoAssertNoGc {
+                store,
+                entered: false,
+            }
+        }
+    }
 }
 
 impl core::ops::Deref for AutoAssertNoGc<'_> {
diff --git a/crates/wasmtime/src/runtime/vm/instance.rs b/crates/wasmtime/src/runtime/vm/instance.rs
index 80fc138e4..fe3fbe6a2 100644
--- a/crates/wasmtime/src/runtime/vm/instance.rs
+++ b/crates/wasmtime/src/runtime/vm/instance.rs
@@ -27,9 +27,9 @@ use sptr::Strict;
 use wasmtime_environ::{
     packed_option::ReservedValue, DataIndex, DefinedGlobalIndex, DefinedMemoryIndex,
     DefinedTableIndex, ElemIndex, EntityIndex, EntityRef, EntitySet, FuncIndex, GlobalIndex,
-    HostPtr, MemoryIndex, MemoryPlan, Module, ModuleInternedTypeIndex, PrimaryMap, TableIndex,
-    TableInitialValue, TableSegmentElements, Trap, VMOffsets, VMSharedTypeIndex, WasmHeapTopType,
-    VMCONTEXT_MAGIC,
+    HostPtr, MemoryIndex, MemoryPlan, Module, ModuleInternedTypeIndex, PrimaryMap, PtrSize,
+    TableIndex, TableInitialValue, TableSegmentElements, Trap, VMOffsets, VMSharedTypeIndex,
+    WasmHeapTopType, VMCONTEXT_MAGIC,
 };
 #[cfg(feature = "wmemcheck")]
 use wasmtime_wmemcheck::Wmemcheck;
@@ -246,16 +246,16 @@ impl Instance {
     ///
     /// This method is unsafe because the `offset` must be within bounds of the
     /// `VMContext` object trailing this instance.
-    unsafe fn vmctx_plus_offset<T>(&self, offset: u32) -> *const T {
+    unsafe fn vmctx_plus_offset<T>(&self, offset: impl Into<u32>) -> *const T {
         self.vmctx()
-            .byte_add(usize::try_from(offset).unwrap())
+            .byte_add(usize::try_from(offset.into()).unwrap())
             .cast()
     }
 
     /// Dual of `vmctx_plus_offset`, but for mutability.
-    unsafe fn vmctx_plus_offset_mut<T>(&mut self, offset: u32) -> *mut T {
+    unsafe fn vmctx_plus_offset_mut<T>(&mut self, offset: impl Into<u32>) -> *mut T {
         self.vmctx()
-            .byte_add(usize::try_from(offset).unwrap())
+            .byte_add(usize::try_from(offset.into()).unwrap())
             .cast()
     }
 
@@ -420,27 +420,27 @@ impl Instance {
     /// Return a pointer to the interrupts structure
     #[inline]
     pub fn runtime_limits(&mut self) -> *mut *const VMRuntimeLimits {
-        unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_runtime_limits()) }
+        unsafe { self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_runtime_limits()) }
     }
 
     /// Return a pointer to the global epoch counter used by this instance.
     pub fn epoch_ptr(&mut self) -> *mut *const AtomicU64 {
-        unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_epoch_ptr()) }
+        unsafe { self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_epoch_ptr()) }
     }
 
     /// Return a pointer to the GC heap base pointer.
     pub fn gc_heap_base(&mut self) -> *mut *mut u8 {
-        unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_gc_heap_base()) }
+        unsafe { self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_gc_heap_base()) }
     }
 
     /// Return a pointer to the GC heap bound.
     pub fn gc_heap_bound(&mut self) -> *mut usize {
-        unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_gc_heap_bound()) }
+        unsafe { self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_gc_heap_bound()) }
     }
 
     /// Return a pointer to the collector-specific heap data.
     pub fn gc_heap_data(&mut self) -> *mut *mut u8 {
-        unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_gc_heap_data()) }
+        unsafe { self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_gc_heap_data()) }
     }
 
     /// Gets a pointer to this instance's `Store` which was originally
@@ -456,14 +456,14 @@ impl Instance {
     #[inline]
     pub fn store(&self) -> *mut dyn Store {
         let ptr =
-            unsafe { *self.vmctx_plus_offset::<*mut dyn Store>(self.offsets().vmctx_store()) };
+            unsafe { *self.vmctx_plus_offset::<*mut dyn Store>(self.offsets().ptr.vmctx_store()) };
         debug_assert!(!ptr.is_null());
         ptr
     }
 
     pub(crate) unsafe fn set_store(&mut self, store: Option<*mut dyn Store>) {
         if let Some(store) = store {
-            *self.vmctx_plus_offset_mut(self.offsets().vmctx_store()) = store;
+            *self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_store()) = store;
             *self.runtime_limits() = (*store).vmruntime_limits();
             *self.epoch_ptr() = (*store).epoch_ptr();
             self.set_gc_heap((*store).maybe_gc_store());
@@ -472,7 +472,7 @@ impl Instance {
                 mem::size_of::<*mut dyn Store>(),
                 mem::size_of::<[*mut (); 2]>()
             );
-            *self.vmctx_plus_offset_mut::<[*mut (); 2]>(self.offsets().vmctx_store()) =
+            *self.vmctx_plus_offset_mut::<[*mut (); 2]>(self.offsets().ptr.vmctx_store()) =
                 [ptr::null_mut(), ptr::null_mut()];
             *self.runtime_limits() = ptr::null_mut();
             *self.epoch_ptr() = ptr::null_mut();
@@ -493,7 +493,7 @@ impl Instance {
     }
 
     pub(crate) unsafe fn set_callee(&mut self, callee: Option<NonNull<VMFunctionBody>>) {
-        *self.vmctx_plus_offset_mut(self.offsets().vmctx_callee()) =
+        *self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_callee()) =
             callee.map_or(ptr::null_mut(), |c| c.as_ptr());
     }
 
@@ -717,7 +717,7 @@ impl Instance {
     ) {
         let type_index = unsafe {
             let base: *const VMSharedTypeIndex =
-                *self.vmctx_plus_offset_mut(self.offsets().vmctx_type_ids_array());
+                *self.vmctx_plus_offset_mut(self.offsets().ptr.vmctx_type_ids_array());
             *base.add(sig.index())
         };
 
@@ -1180,16 +1180,16 @@ impl Instance {
     ) {
         assert!(ptr::eq(module, self.module().as_ref()));
 
-        *self.vmctx_plus_offset_mut(offsets.vmctx_magic()) = VMCONTEXT_MAGIC;
+        *self.vmctx_plus_offset_mut(offsets.ptr.vmctx_magic()) = VMCONTEXT_MAGIC;
         self.set_callee(None);
         self.set_store(store.as_raw());
 
         // Initialize shared types
         let types = self.runtime_info.type_ids();
-        *self.vmctx_plus_offset_mut(offsets.vmctx_type_ids_array()) = types.as_ptr();
+        *self.vmctx_plus_offset_mut(offsets.ptr.vmctx_type_ids_array()) = types.as_ptr();
 
         // Initialize the built-in functions
-        *self.vmctx_plus_offset_mut(offsets.vmctx_builtin_functions()) =
+        *self.vmctx_plus_offset_mut(offsets.ptr.vmctx_builtin_functions()) =
             &VMBuiltinFunctionsArray::INIT;
 
         // Initialize the imports
diff --git a/crates/wasmtime/src/runtime/vm/vmcontext.rs b/crates/wasmtime/src/runtime/vm/vmcontext.rs
index 6530399ae..d9da984eb 100644
--- a/crates/wasmtime/src/runtime/vm/vmcontext.rs
+++ b/crates/wasmtime/src/runtime/vm/vmcontext.rs
@@ -840,16 +840,6 @@ mod test_vmruntime_limits {
     use std::mem::size_of;
     use wasmtime_environ::{Module, PtrSize, VMOffsets};
 
-    #[test]
-    fn vmctx_runtime_limits_offset() {
-        let module = Module::new();
-        let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
-        assert_eq!(
-            offsets.vmctx_runtime_limits(),
-            u32::from(offsets.ptr.vmcontext_runtime_limits())
-        );
-    }
-
     #[test]
     fn field_offsets() {
         let module = Module::new();
diff --git a/fuzz/fuzz_targets/cranelift-fuzzgen.rs b/fuzz/fuzz_targets/cranelift-fuzzgen.rs
index c3c1b19d7..b496912d8 100644
--- a/fuzz/fuzz_targets/cranelift-fuzzgen.rs
+++ b/fuzz/fuzz_targets/cranelift-fuzzgen.rs
@@ -107,7 +107,6 @@ impl Default for Statistics {
         // Pre-Register all trap codes since we can't modify this hashmap atomically.
         let mut run_result_trap = HashMap::new();
         run_result_trap.insert(CraneliftTrap::Debug, AtomicU64::new(0));
-        run_result_trap.insert(CraneliftTrap::Resumable, AtomicU64::new(0));
         for trapcode in TrapCode::non_user_traps() {
             run_result_trap.insert(CraneliftTrap::User(*trapcode), AtomicU64::new(0));
         }
diff --git a/winch/codegen/src/codegen/mod.rs b/winch/codegen/src/codegen/mod.rs
index 07d60ed69..4752bdddc 100644
--- a/winch/codegen/src/codegen/mod.rs
+++ b/winch/codegen/src/codegen/mod.rs
@@ -328,13 +328,13 @@ where
             .as_u32()
             .checked_mul(sig_index_bytes.into())
             .unwrap();
-        let signatures_base_offset = self.env.vmoffsets.vmctx_type_ids_array();
+        let signatures_base_offset = self.env.vmoffsets.ptr.vmctx_type_ids_array();
         let scratch = <M::ABI as ABI>::scratch_reg();
         let funcref_sig_offset = self.env.vmoffsets.ptr.vm_func_ref_type_index();
 
         // Load the signatures address into the scratch register.
         self.masm.load(
-            self.masm.address_at_vmctx(signatures_base_offset),
+            self.masm.address_at_vmctx(signatures_base_offset.into()),
             scratch,
             ptr_size,
         );


Test patch:
diff --git a/cranelift/filetests/filetests/isa/s390x/traps.clif b/cranelift/filetests/filetests/isa/s390x/traps.clif
index f231f0851..54a071823 100644
--- a/cranelift/filetests/filetests/isa/s390x/traps.clif
+++ b/cranelift/filetests/filetests/isa/s390x/traps.clif
@@ -2,7 +2,7 @@ test compile precise-output
 target s390x
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; TRAP/RESUMABLE_TRAP
+;; TRAP
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 function %trap() {
@@ -18,19 +18,6 @@ block0:
 ; block0: ; offset 0x0
 ;   .byte 0x00, 0x00 ; trap: user0
 
-function %resumable_trap() {
-block0:
-  trap user0
-}
-
-; VCode:
-; block0:
-;   .word 0x0000 # trap=user0
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   .byte 0x00, 0x00 ; trap: user0
-
 function %trapz(i64) {
 block0(v0: i64):
   v1 = iconst.i64 42
@@ -83,32 +70,6 @@ block0(v0: i64):
 ; block2: ; offset 0xe
 ;   .byte 0x00, 0x00 ; trap: user0
 
-function %resumable_trapnz(i64) {
-block0(v0: i64):
-  v1 = iconst.i64 42
-  v2 = icmp eq v0, v1
-  trapnz v2, user0
-  return
-}
-
-; VCode:
-; block0:
-;   clgfi %r2, 42
-;   jge label2 ; jg label1
-; block1:
-;   br %r14
-; block2:
-;   .word 0x0000 # trap=user0
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   clgfi %r2, 0x2a
-;   jge 0xe
-; block1: ; offset 0xc
-;   br %r14
-; block2: ; offset 0xe
-;   .byte 0x00, 0x00 ; trap: user0
-
 function %h() {
 block0:
   debugtrap
@@ -124,4 +85,3 @@ block0:
 ; block0: ; offset 0x0
 ;   .byte 0x00, 0x01
 ;   br %r14
-
diff --git a/tests/all/pooling_allocator.rs b/tests/all/pooling_allocator.rs
index e6f51e5ac..d3d4424d7 100644
--- a/tests/all/pooling_allocator.rs
+++ b/tests/all/pooling_allocator.rs
@@ -648,6 +648,7 @@ fn instance_too_large() -> Result<()> {
 configured maximum of 16 bytes; breakdown of allocation requirement:
 
  * 72.73% - 256 bytes - instance state management
+ * 25.00% - 88 bytes - static vmctx data
 "
     } else {
         "\
@@ -655,7 +656,7 @@ instance allocation for this module requires 256 bytes which exceeds the \
 configured maximum of 16 bytes; breakdown of allocation requirement:
 
  * 62.50% - 160 bytes - instance state management
- * 6.25% - 16 bytes - jit store state
+ * 34.38% - 88 bytes - static vmctx data
 "
     };
     match Module::new(&engine, "(module)") {
diff --git a/tests/spec_testsuite b/tests/spec_testsuite
index 16a839d56..e05365077 160000
--- a/tests/spec_testsuite
+++ b/tests/spec_testsuite
@@ -1,1 +1,1 @@
-Subproject commit 16a839d5601c283541a84572b47637f035b51437
+Subproject commit e05365077e13a1d86ffe77acfb1a835b7aa78422
diff --git a/tests/wast.rs b/tests/wast.rs
index 8e5b38c85..076a6ccb3 100644
--- a/tests/wast.rs
+++ b/tests/wast.rs
@@ -78,6 +78,26 @@ fn ignore(test: &Path, strategy: Strategy) -> bool {
         if part == "extended-const" {
             return true;
         }
+        // Wasmtime doesn't implement the table64 extension yet.
+        if part == "memory64" {
+            if [
+                "call_indirect.wast",
+                "table_copy.wast",
+                "table_get.wast",
+                "table_set.wast",
+                "table_fill.wast",
+                "table.wast",
+                "table_init.wast",
+                "table_copy_mixed.wast",
+                "table_grow.wast",
+                "table_size.wast",
+            ]
+            .iter()
+            .any(|i| test.ends_with(i))
+            {
+                return true;
+            }
+        }
 
         // TODO(#6530): These tests require tail calls, but s390x doesn't
         // support them yet.
@@ -175,6 +195,7 @@ fn ignore(test: &Path, strategy: Strategy) -> bool {
                 "type-subtyping.wast",
                 "unreached-invalid.wast",
                 "unreached_valid.wast",
+                "i31.wast",
             ]
             .iter()
             .any(|i| test.ends_with(i));