Repository: bytecodealliance/wasmtime
Pull request #8506 (2024-04-29 20:20:37)

cranelift: Compress vcode range-lists
These lists of ranges always cover contiguous ranges of an index space, meaning the start of one range is the same as the end of the previous range, so we can cut storage in half by only storing one endpoint of each range.

This in turn means we don't have to keep track of the other endpoint while building these lists, reducing the state we need to keep while building vcode and simplifying the various build steps.


Patch:
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 0c91d826b..bccfbd59c 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -76,8 +76,12 @@
   - "docs/**"
 
 "wasmtime:ref-types":
-  - "crates/wasmtime/src/ref.rs"
-  - "crates/runtime/src/externref.rs"
+  - "crates/cranelift/src/gc.rs"
+  - "crates/cranelift/src/gc/**"
+  - "crates/wasmtime/src/runtime/gc.rs"
+  - "crates/wasmtime/src/runtime/gc/**"
+  - "crates/wasmtime/src/runtime/vm/gc.rs"
+  - "crates/wasmtime/src/runtime/vm/gc/**"
 
 "winch":
   - "winch/**"
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index f2b5a0c93..8280db0c5 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -376,9 +376,9 @@ jobs:
       env:
         CARGO_BUILD_TARGET: x86_64-unknown-none
 
-    # Check that wasmtime-runtime compiles with panic=abort since there's some
-    # #[cfg] for specifically panic=abort there.
-    - run: cargo check -p wasmtime-runtime
+    # Check that wasmtime compiles with panic=abort since there's some `#[cfg]`
+    # for specifically panic=abort there.
+    - run: cargo check -p wasmtime
       env:
         RUSTFLAGS: -Cpanic=abort
 
@@ -824,7 +824,6 @@ jobs:
         cargo miri nextest run -j4 --no-fail-fast \
           -p wasmtime \
           -p wasmtime-cli \
-          -p wasmtime-runtime \
           -p wasmtime-environ
       env:
         MIRIFLAGS: -Zmiri-strict-provenance
diff --git a/Cargo.lock b/Cargo.lock
index 8274bbb8c..c6e7dafea 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3397,6 +3397,7 @@ dependencies = [
  "anyhow",
  "async-trait",
  "bumpalo",
+ "cc",
  "cfg-if",
  "encoding_rs",
  "fxprof-processed-profile",
@@ -3405,10 +3406,16 @@ dependencies = [
  "ittapi",
  "libc",
  "log",
+ "mach2",
+ "memfd",
+ "memoffset",
  "object 0.33.0",
  "once_cell",
  "paste",
  "postcard",
+ "proptest",
+ "psm",
+ "rand",
  "rayon",
  "rustix",
  "semver",
@@ -3416,11 +3423,13 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "smallvec",
+ "sptr",
  "target-lexicon",
  "tempfile",
  "wasi-common",
  "wasm-encoder 0.206.0",
  "wasmparser 0.206.0",
+ "wasmtime-asm-macros",
  "wasmtime-cache",
  "wasmtime-component-macro",
  "wasmtime-component-util",
@@ -3429,9 +3438,10 @@ dependencies = [
  "wasmtime-fiber",
  "wasmtime-jit-debug",
  "wasmtime-jit-icache-coherence",
- "wasmtime-runtime",
  "wasmtime-slab",
+ "wasmtime-versioned-export-macros",
  "wasmtime-winch",
+ "wasmtime-wmemcheck",
  "wat",
  "windows-sys 0.52.0",
 ]
@@ -3568,7 +3578,6 @@ dependencies = [
  "wasmtime-cranelift",
  "wasmtime-environ",
  "wasmtime-explorer",
- "wasmtime-runtime",
  "wasmtime-wasi",
  "wasmtime-wasi-http",
  "wasmtime-wasi-nn",
@@ -3782,39 +3791,6 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
-[[package]]
-name = "wasmtime-runtime"
-version = "21.0.0"
-dependencies = [
- "anyhow",
- "cc",
- "cfg-if",
- "encoding_rs",
- "indexmap 2.0.0",
- "libc",
- "log",
- "mach2",
- "memfd",
- "memoffset",
- "once_cell",
- "paste",
- "proptest",
- "psm",
- "rand",
- "rustix",
- "smallvec",
- "sptr",
- "wasm-encoder 0.206.0",
- "wasmtime-asm-macros",
- "wasmtime-environ",
- "wasmtime-fiber",
- "wasmtime-jit-debug",
- "wasmtime-slab",
- "wasmtime-versioned-export-macros",
- "wasmtime-wmemcheck",
- "windows-sys 0.52.0",
-]
-
 [[package]]
 name = "wasmtime-slab"
 version = "21.0.0"
diff --git a/Cargo.toml b/Cargo.toml
index 075f300ea..5b2be064e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -37,7 +37,6 @@ wasmtime-wasi = { workspace = true, default-features = true, optional = true }
 wasmtime-wasi-nn = { workspace = true, optional = true }
 wasmtime-wasi-threads = { workspace = true, optional = true }
 wasmtime-wasi-http = { workspace = true, optional = true }
-wasmtime-runtime = { workspace = true, optional = true }
 clap = { workspace = true }
 anyhow = { workspace = true, features = ['std'] }
 target-lexicon = { workspace = true }
@@ -70,7 +69,6 @@ env_logger = { workspace = true }
 log = { workspace = true }
 filecheck = { workspace = true }
 tempfile = { workspace = true }
-wasmtime-runtime = { workspace = true }
 tokio = { workspace = true, features = ["rt", "time", "macros", "rt-multi-thread"] }
 wast = { workspace = true }
 criterion = { workspace = true }
@@ -170,7 +168,6 @@ wasmtime-explorer = { path = "crates/explorer", version = "=21.0.0" }
 wasmtime-fiber = { path = "crates/fiber", version = "=21.0.0" }
 wasmtime-types = { path = "crates/types", version = "21.0.0" }
 wasmtime-jit-debug = { path = "crates/jit-debug", version = "=21.0.0" }
-wasmtime-runtime = { path = "crates/runtime", version = "=21.0.0" }
 wasmtime-wast = { path = "crates/wast", version = "=21.0.0" }
 wasmtime-wasi = { path = "crates/wasi", version = "21.0.0", default-features = false }
 wasmtime-wasi-http = { path = "crates/wasi-http", version = "=21.0.0", default-features = false }
@@ -246,6 +243,7 @@ wit-component = "0.206.0"
 
 # Non-Bytecode Alliance maintained dependencies:
 # --------------------------
+cc = "1.0"
 object = { version = "0.33", default-features = false, features = ['read_core', 'elf', 'std'] }
 gimli = { version = "0.28.0", default-features = false, features = ['read', 'std'] }
 anyhow = { version = "1.0.22", default-features = false }
@@ -264,6 +262,13 @@ async-trait = "0.1.71"
 heck = "0.4"
 similar = "2.1.0"
 toml = "0.8.10"
+mach2 = "0.4.1"
+memfd = "0.6.2"
+memoffset = "0.9.0"
+psm = "0.1.11"
+proptest = "1.0.0"
+rand = { version = "0.8.3", features = ["small_rng"] }
+sptr = "0.3.2"
 # serde and serde_derive must have the same version
 serde = "1.0.188"
 serde_derive = "1.0.188"
@@ -395,7 +400,7 @@ explore = ["dep:wasmtime-explorer"]
 wast = ["dep:wasmtime-wast"]
 config = ["cache"]
 compile = ["cranelift"]
-run = ["dep:wasmtime-wasi", "wasmtime/runtime", "wasmtime-runtime", "dep:listenfd", "dep:wasi-common"]
+run = ["dep:wasmtime-wasi", "wasmtime/runtime", "dep:listenfd", "dep:wasi-common"]
 
 [[test]]
 name = "host_segfault"
diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs
index ceb0d2962..5c1e84a09 100644
--- a/cranelift/codegen/src/isa/x64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/x64/inst/mod.rs
@@ -1179,11 +1179,11 @@ impl PrettyPrint for Inst {
                 dst,
                 ..
             } => {
-                let dst = pretty_print_reg(dst.to_reg().to_reg(), 8, allocs);
                 let src1 = pretty_print_reg(src1.to_reg(), 8, allocs);
                 let src2 = src2.pretty_print(8, allocs);
+                let dst = pretty_print_reg(dst.to_reg().to_reg(), 8, allocs);
                 let op = ljustify(op.to_string());
-                format!("{op} {src1}, {src2}, {dst}")
+                format!("{op} {src2}, {src1}, {dst}")
             }
 
             Inst::XmmRmREvex3 {
@@ -1199,7 +1199,7 @@ impl PrettyPrint for Inst {
                 let src3 = src3.pretty_print(8, allocs);
                 let dst = pretty_print_reg(dst.to_reg().to_reg(), 8, allocs);
                 let op = ljustify(op.to_string());
-                format!("{op} {src1}, {src2}, {src3}, {dst}")
+                format!("{op} {src3}, {src2}, {src1}, {dst}")
             }
 
             Inst::XmmMinMaxSeq {
diff --git a/cranelift/codegen/src/lib.rs b/cranelift/codegen/src/lib.rs
index 6e66d31d5..2b24ab579 100644
--- a/cranelift/codegen/src/lib.rs
+++ b/cranelift/codegen/src/lib.rs
@@ -76,6 +76,7 @@ mod iterators;
 mod legalizer;
 mod nan_canonicalization;
 mod opts;
+mod ranges;
 mod remove_constant_phis;
 mod result;
 mod scoped_hash_map;
diff --git a/cranelift/codegen/src/machinst/reg.rs b/cranelift/codegen/src/machinst/reg.rs
index 5ea6efc37..c4e90bc0e 100644
--- a/cranelift/codegen/src/machinst/reg.rs
+++ b/cranelift/codegen/src/machinst/reg.rs
@@ -288,7 +288,6 @@ pub type RegClass = regalloc2::RegClass;
 #[derive(Debug)]
 pub struct OperandCollector<'a, F: Fn(VReg) -> VReg> {
     operands: &'a mut Vec<Operand>,
-    operands_start: usize,
     clobbers: PRegSet,
 
     /// The subset of physical registers that are allocatable.
@@ -300,10 +299,8 @@ pub struct OperandCollector<'a, F: Fn(VReg) -> VReg> {
 impl<'a, F: Fn(VReg) -> VReg> OperandCollector<'a, F> {
     /// Start gathering operands into one flattened operand array.
     pub fn new(operands: &'a mut Vec<Operand>, allocatable: PRegSet, renamer: F) -> Self {
-        let operands_start = operands.len();
         Self {
             operands,
-            operands_start,
             clobbers: PRegSet::default(),
             allocatable,
             renamer,
@@ -313,10 +310,9 @@ impl<'a, F: Fn(VReg) -> VReg> OperandCollector<'a, F> {
     /// Finish the operand collection and return the tuple giving the
     /// range of indices in the flattened operand array, and the
     /// clobber set.
-    pub fn finish(self) -> ((u32, u32), PRegSet) {
-        let start = self.operands_start as u32;
-        let end = self.operands.len() as u32;
-        ((start, end), self.clobbers)
+    pub fn finish(self) -> (usize, PRegSet) {
+        let end = self.operands.len();
+        (end, self.clobbers)
     }
 }
 
diff --git a/cranelift/codegen/src/machinst/vcode.rs b/cranelift/codegen/src/machinst/vcode.rs
index f526958f6..5acb35240 100644
--- a/cranelift/codegen/src/machinst/vcode.rs
+++ b/cranelift/codegen/src/machinst/vcode.rs
@@ -20,6 +20,7 @@
 use crate::ir::pcc::*;
 use crate::ir::{self, types, Constant, ConstantData, ValueLabel};
 use crate::machinst::*;
+use crate::ranges::Ranges;
 use crate::timing;
 use crate::trace;
 use crate::CodegenError;
@@ -75,7 +76,7 @@ pub struct VCode<I: VCodeInst> {
     /// Operand index ranges: for each instruction in `insts`, there
     /// is a tuple here providing the range in `operands` for that
     /// instruction's operands.
-    operand_ranges: Vec<(u32, u32)>,
+    operand_ranges: Ranges,
 
     /// Clobbers: a sparse map from instruction indices to clobber masks.
     clobbers: FxHashMap<InsnIndex, PRegSet>,
@@ -88,10 +89,10 @@ pub struct VCode<I: VCodeInst> {
     entry: BlockIndex,
 
     /// Block instruction indices.
-    block_ranges: Vec<(InsnIndex, InsnIndex)>,
+    block_ranges: Ranges,
 
     /// Block successors: index range in the `block_succs` list.
-    block_succ_range: Vec<(u32, u32)>,
+    block_succ_range: Ranges,
 
     /// Block successor lists, concatenated into one vec. The
     /// `block_succ_range` list of tuples above gives (start, end)
@@ -100,7 +101,7 @@ pub struct VCode<I: VCodeInst> {
     block_succs: Vec<regalloc2::Block>,
 
     /// Block predecessors: index range in the `block_preds` list.
-    block_pred_range: Vec<(u32, u32)>,
+    block_pred_range: Ranges,
 
     /// Block predecessor lists, concatenated into one vec. The
     /// `block_pred_range` list of tuples above gives (start, end)
@@ -109,7 +110,7 @@ pub struct VCode<I: VCodeInst> {
     block_preds: Vec<regalloc2::Block>,
 
     /// Block parameters: index range in `block_params` below.
-    block_params_range: Vec<(u32, u32)>,
+    block_params_range: Ranges,
 
     /// Block parameter lists, concatenated into one vec. The
     /// `block_params_range` list of tuples above gives (start, end)
@@ -133,11 +134,11 @@ pub struct VCode<I: VCodeInst> {
     /// for each block are concatenated.
     ///
     /// Indexed by the indices in `branch_block_arg_succ_range`.
-    branch_block_arg_range: Vec<(u32, u32)>,
+    branch_block_arg_range: Ranges,
 
     /// For a given block, indices in `branch_block_arg_range`
     /// corresponding to all of its successors.
-    branch_block_arg_succ_range: Vec<(u32, u32)>,
+    branch_block_arg_succ_range: Ranges,
 
     /// Block-order information.
     block_order: BlockLoweringOrder,
@@ -226,20 +227,6 @@ pub struct VCodeBuilder<I: VCodeInst> {
     /// In what direction is the build occuring?
     direction: VCodeBuildDirection,
 
-    /// Index of the last block-start in the vcode.
-    block_start: usize,
-
-    /// Start of succs for the current block in the concatenated succs list.
-    succ_start: usize,
-
-    /// Start of blockparams for the current block in the concatenated
-    /// blockparams list.
-    block_params_start: usize,
-
-    /// Start of successor blockparam arg list entries in
-    /// the concatenated branch_block_arg_range list.
-    branch_block_arg_succ_start: usize,
-
     /// Debug-value label in-progress map, keyed by label. For each
     /// label, we keep disjoint ranges mapping to vregs. We'll flatten
     /// this into (vreg, range, label) tuples when done.
@@ -270,10 +257,6 @@ impl<I: VCodeInst> VCodeBuilder<I> {
         VCodeBuilder {
             vcode,
             direction,
-            block_start: 0,
-            succ_start: 0,
-            block_params_start: 0,
-            branch_block_arg_succ_start: 0,
             debug_info: FxHashMap::default(),
         }
     }
@@ -313,32 +296,20 @@ impl<I: VCodeInst> VCodeBuilder<I> {
     /// End the current basic block. Must be called after emitting vcode insts
     /// for IR insts and prior to ending the function (building the VCode).
     pub fn end_bb(&mut self) {
-        let start_idx = self.block_start;
         let end_idx = self.vcode.insts.len();
-        self.block_start = end_idx;
         // Add the instruction index range to the list of blocks.
-        self.vcode
-            .block_ranges
-            .push((InsnIndex::new(start_idx), InsnIndex::new(end_idx)));
+        self.vcode.block_ranges.push_end(end_idx);
         // End the successors list.
         let succ_end = self.vcode.block_succs.len();
-        self.vcode
-            .block_succ_range
-            .push((self.succ_start as u32, succ_end as u32));
-        self.succ_start = succ_end;
+        self.vcode.block_succ_range.push_end(succ_end);
         // End the blockparams list.
         let block_params_end = self.vcode.block_params.len();
-        self.vcode
-            .block_params_range
-            .push((self.block_params_start as u32, block_params_end as u32));
-        self.block_params_start = block_params_end;
+        self.vcode.block_params_range.push_end(block_params_end);
         // End the branch blockparam args list.
         let branch_block_arg_succ_end = self.vcode.branch_block_arg_range.len();
-        self.vcode.branch_block_arg_succ_range.push((
-            self.branch_block_arg_succ_start as u32,
-            branch_block_arg_succ_end as u32,
-        ));
-        self.branch_block_arg_succ_start = branch_block_arg_succ_end;
+        self.vcode
+            .branch_block_arg_succ_range
+            .push_end(branch_block_arg_succ_end);
     }
 
     pub fn add_block_param(&mut self, param: VirtualReg) {
@@ -346,14 +317,11 @@ impl<I: VCodeInst> VCodeBuilder<I> {
     }
 
     fn add_branch_args_for_succ(&mut self, args: &[Reg]) {
-        let start = self.vcode.branch_block_args.len();
         self.vcode
             .branch_block_args
             .extend(args.iter().map(|&arg| VReg::from(arg)));
         let end = self.vcode.branch_block_args.len();
-        self.vcode
-            .branch_block_arg_range
-            .push((start as u32, end as u32));
+        self.vcode.branch_block_arg_range.push_end(end);
     }
 
     /// Push an instruction for the current BB and current IR inst
@@ -407,20 +375,20 @@ impl<I: VCodeInst> VCodeBuilder<I> {
             let start = end;
             end += *count;
             *count = start;
-            self.vcode.block_pred_range.push((start, end));
+            self.vcode.block_pred_range.push_end(end as usize);
         }
         let end = end as usize;
         debug_assert_eq!(end, self.vcode.block_succs.len());
 
         // Walk over the successors again, this time grouped by
         // predecessor, and push the predecessor at the current
-        // starting position of each of its successors. Visiting
-        // predecessor groups in ascending order means we build each
-        // group of predecessors in sorted order too.
+        // starting position of each of its successors. We build
+        // each group of predecessors in whatever order Ranges::iter
+        // returns them; regalloc2 doesn't care.
         self.vcode.block_preds.resize(end, BlockIndex::invalid());
-        for (pred, &(start, end)) in self.vcode.block_succ_range.iter().enumerate() {
+        for (pred, range) in self.vcode.block_succ_range.iter() {
             let pred = BlockIndex::new(pred);
-            for succ in &self.vcode.block_succs[start as usize..end as usize] {
+            for succ in &self.vcode.block_succs[range] {
                 let pos = &mut starts[succ.index()];
                 self.vcode.block_preds[*pos as usize] = pred;
                 *pos += 1;
@@ -439,21 +407,22 @@ impl<I: VCodeInst> VCodeBuilder<I> {
         }
 
         // Reverse the per-block and per-inst sequences.
-        self.vcode.block_ranges.reverse();
+        self.vcode.block_ranges.reverse_index();
+        self.vcode.block_ranges.reverse_target(n_insts);
         // block_params_range is indexed by block (and blocks were
         // traversed in reverse) so we reverse it; but block-param
         // sequences in the concatenated vec can remain in reverse
         // order (it is effectively an arena of arbitrarily-placed
         // referenced sequences).
-        self.vcode.block_params_range.reverse();
+        self.vcode.block_params_range.reverse_index();
         // Likewise, we reverse block_succ_range, but the block_succ
         // concatenated array can remain as-is.
-        self.vcode.block_succ_range.reverse();
+        self.vcode.block_succ_range.reverse_index();
         self.vcode.insts.reverse();
         self.vcode.srclocs.reverse();
         // Likewise, branch_block_arg_succ_range is indexed by block
         // so must be reversed.
-        self.vcode.branch_block_arg_succ_range.reverse();
+        self.vcode.branch_block_arg_succ_range.reverse_index();
 
         // To translate an instruction index *endpoint* in reversed
         // order to forward order, compute `n_insts - i`.
@@ -467,12 +436,6 @@ impl<I: VCodeInst> VCodeBuilder<I> {
         // (exclusive) end of 10.
         let translate = |inst: InsnIndex| InsnIndex::new(n_insts - inst.index());
 
-        // Edit the block-range instruction indices.
-        for tuple in &mut self.vcode.block_ranges {
-            let (start, end) = *tuple;
-            *tuple = (translate(end), translate(start)); // Note reversed order.
-        }
-
         // Generate debug-value labels based on per-label maps.
         for (label, tuples) in &self.debug_info {
             for &(start, end, vreg) in tuples {
@@ -512,7 +475,7 @@ impl<I: VCodeInst> VCodeBuilder<I> {
                 });
             insn.get_operands(&mut op_collector);
             let (ops, clobbers) = op_collector.finish();
-            self.vcode.operand_ranges.push(ops);
+            self.vcode.operand_ranges.push_end(ops);
 
             if clobbers != PRegSet::default() {
                 self.vcode.clobbers.insert(InsnIndex::new(i), clobbers);
@@ -626,20 +589,20 @@ impl<I: VCodeInst> VCode<I> {
             vreg_types: vec![],
             insts: Vec::with_capacity(10 * n_blocks),
             operands: Vec::with_capacity(30 * n_blocks),
-            operand_ranges: Vec::with_capacity(10 * n_blocks),
+            operand_ranges: Ranges::with_capacity(10 * n_blocks),
             clobbers: FxHashMap::default(),
             srclocs: Vec::with_capacity(10 * n_blocks),
             entry: BlockIndex::new(0),
-            block_ranges: Vec::with_capacity(n_blocks),
-            block_succ_range: Vec::with_capacity(n_blocks),
+            block_ranges: Ranges::with_capacity(n_blocks),
+            block_succ_range: Ranges::with_capacity(n_blocks),
             block_succs: Vec::with_capacity(n_blocks),
-            block_pred_range: Vec::new(),
+            block_pred_range: Ranges::default(),
             block_preds: Vec::new(),
-            block_params_range: Vec::with_capacity(n_blocks),
+            block_params_range: Ranges::with_capacity(n_blocks),
             block_params: Vec::with_capacity(5 * n_blocks),
             branch_block_args: Vec::with_capacity(10 * n_blocks),
-            branch_block_arg_range: Vec::with_capacity(2 * n_blocks),
-            branch_block_arg_succ_range: Vec::with_capacity(n_blocks),
+            branch_block_arg_range: Ranges::with_capacity(2 * n_blocks),
+            branch_block_arg_succ_range: Ranges::with_capacity(n_blocks),
             block_order,
             abi,
             emit_info,
@@ -676,7 +639,7 @@ impl<I: VCodeInst> VCode<I> {
             }
         }
 
-        for (i, (start, end)) in self.operand_ranges.iter().enumerate() {
+        for (i, range) in self.operand_ranges.iter() {
             // Skip this instruction if not "included in clobbers" as
             // per the MachInst. (Some backends use this to implement
             // ABI specifics; e.g., excluding calls of the same ABI as
@@ -687,10 +650,8 @@ impl<I: VCodeInst> VCode<I> {
                 continue;
             }
 
-            let start = *start as usize;
-            let end = *end as usize;
-            let operands = &self.operands[start..end];
-            let allocs = &regalloc.allocs[start..end];
+            let operands = &self.operands[range.clone()];
+            let allocs = &regalloc.allocs[range];
             for (operand, alloc) in operands.iter().zip(allocs.iter()) {
                 if operand.kind() == OperandKind::Def {
                     if let Some(preg) = alloc.as_reg() {
@@ -787,7 +748,7 @@ impl<I: VCodeInst> VCode<I> {
         let mut ra_edits_per_block: SmallVec<[u32; 64]> = smallvec![];
         let mut edit_idx = 0;
         for block in 0..self.num_blocks() {
-            let end_inst = self.block_ranges[block].1;
+            let end_inst = InsnIndex::new(self.block_ranges.get(block).end);
             let start_edit_idx = edit_idx;
             while edit_idx < regalloc.edits.len() && regalloc.edits[edit_idx].0.inst() < end_inst {
                 edit_idx += 1;
@@ -1004,9 +965,8 @@ impl<I: VCodeInst> VCode<I> {
             // `MachBuffer` to determine if an island is necessary.
             let worst_case_next_bb = if block_order_idx < final_order.len() - 1 {
                 let next_block = final_order[block_order_idx + 1];
-                let next_block_range = self.block_ranges[next_block.index()];
-                let next_block_size =
-                    (next_block_range.1.index() - next_block_range.0.index()) as u32;
+                let next_block_range = self.block_ranges.get(next_block.index());
+                let next_block_size = next_block_range.len() as u32;
                 let next_block_ra_insertions = ra_edits_per_block[next_block.index()];
                 I::worst_case_size() * (next_block_size + next_block_ra_insertions)
             } else {
@@ -1270,18 +1230,18 @@ impl<I: VCodeInst> RegallocFunction for VCode<I> {
     }
 
     fn block_insns(&self, block: BlockIndex) -> InstRange {
-        let (start, end) = self.block_ranges[block.index()];
-        InstRange::forward(start, end)
+        let range = self.block_ranges.get(block.index());
+        InstRange::forward(InsnIndex::new(range.start), InsnIndex::new(range.end))
     }
 
     fn block_succs(&self, block: BlockIndex) -> &[BlockIndex] {
-        let (start, end) = self.block_succ_range[block.index()];
-        &self.block_succs[start as usize..end as usize]
+        let range = self.block_succ_range.get(block.index());
+        &self.block_succs[range]
     }
 
     fn block_preds(&self, block: BlockIndex) -> &[BlockIndex] {
-        let (start, end) = self.block_pred_range[block.index()];
-        &self.block_preds[start as usize..end as usize]
+        let range = self.block_pred_range.get(block.index());
+        &self.block_preds[range]
     }
 
     fn block_params(&self, block: BlockIndex) -> &[VReg] {
@@ -1291,16 +1251,15 @@ impl<I: VCodeInst> RegallocFunction for VCode<I> {
             return &[];
         }
 
-        let (start, end) = self.block_params_range[block.index()];
-        &self.block_params[start as usize..end as usize]
+        let range = self.block_params_range.get(block.index());
+        &self.block_params[range]
     }
 
     fn branch_blockparams(&self, block: BlockIndex, _insn: InsnIndex, succ_idx: usize) -> &[VReg] {
-        let (succ_range_start, succ_range_end) = self.branch_block_arg_succ_range[block.index()];
-        let succ_ranges =
-            &self.branch_block_arg_range[succ_range_start as usize..succ_range_end as usize];
-        let (branch_block_args_start, branch_block_args_end) = succ_ranges[succ_idx];
-        &self.branch_block_args[branch_block_args_start as usize..branch_block_args_end as usize]
+        let succ_range = self.branch_block_arg_succ_range.get(block.index());
+        debug_assert!(succ_idx < succ_range.len());
+        let branch_block_args = self.branch_block_arg_range.get(succ_range.start + succ_idx);
+        &self.branch_block_args[branch_block_args]
     }
 
     fn is_ret(&self, insn: InsnIndex) -> bool {
@@ -1324,8 +1283,8 @@ impl<I: VCodeInst> RegallocFunction for VCode<I> {
     }
 
     fn inst_operands(&self, insn: InsnIndex) -> &[Operand] {
-        let (start, end) = self.operand_ranges[insn.index()];
-        &self.operands[start as usize..end as usize]
+        let range = self.operand_ranges.get(insn.index());
+        &self.operands[range]
     }
 
     fn inst_clobbers(&self, insn: InsnIndex) -> PRegSet {
@@ -1393,8 +1352,7 @@ impl<I: VCodeInst> fmt::Debug for VCode<I> {
             for succ in self.block_succs(block) {
                 writeln!(f, "    (successor: Block {})", succ.index())?;
             }
-            let (start, end) = self.block_ranges[block.index()];
-            for inst in start.index()..end.index() {
+            for inst in self.block_ranges.get(block.index()) {
                 writeln!(
                     f,
                     "  Inst {}: {}",
diff --git a/cranelift/codegen/src/opts/icmp.isle b/cranelift/codegen/src/opts/icmp.isle
index f7d20fa3d..024e6668f 100644
--- a/cranelift/codegen/src/opts/icmp.isle
+++ b/cranelift/codegen/src/opts/icmp.isle
@@ -14,16 +14,34 @@
 (rule (simplify (sle (ty_int ty) x x)) (subsume (iconst_u ty 1)))
 
 ;; Optimize icmp-of-icmp.
+;; ne(icmp(ty, cc, x, y), 0) == icmp(ty, cc, x, y)
+;; e.g. neq(ugt(x, y), 0) == ugt(x, y) 
 (rule (simplify (ne ty
                       (uextend_maybe _ inner @ (icmp ty _ _ _))
                       (iconst_u _ 0)))
       (subsume inner))
 
+;; eq(icmp(ty, cc, x, y), 0) == icmp(ty, cc_complement, x, y)
+;; e.g. eq(ugt(x, y), 0) == ule(x, y) 
 (rule (simplify (eq ty
                       (uextend_maybe _ (icmp ty cc x y))
                       (iconst_u _ 0)))
       (subsume (icmp ty (intcc_complement cc) x y)))
 
+;; ne(icmp(ty, cc, x, y), 1) == icmp(ty, cc_complement, x, y)
+;; e.g. ne(ugt(x, y), 1) == ule(x, y)
+(rule (simplify (ne ty
+                      (uextend_maybe _ (icmp ty cc x y))
+                      (iconst_u _ 1)))
+      (subsume (icmp ty (intcc_complement cc) x y)))
+
+;; eq(icmp(ty, cc, x, y), 1) == icmp(ty, cc, x, y)
+;; e.g. eq(ugt(x, y), 1) == ugt(x, y)
+(rule (simplify (eq ty
+                      (uextend_maybe _ inner @ (icmp _ _ _ _))
+                      (iconst_u _ 1)))
+      (subsume inner))
+
 ;; Optimize select-of-uextend-of-icmp to select-of-icmp, because
 ;; select can take an I8 condition too.
 (rule (simplify
diff --git a/cranelift/codegen/src/ranges.rs b/cranelift/codegen/src/ranges.rs
new file mode 100644
index 000000000..419dee83c
--- /dev/null
+++ b/cranelift/codegen/src/ranges.rs
@@ -0,0 +1,131 @@
+//! The [`Ranges`] type stores a list of contiguous index ranges that
+//! span some other list's full length.
+
+use alloc::vec::Vec;
+use core::ops::Range;
+
+/// A list of contiguous index ranges.
+#[derive(Default)]
+pub struct Ranges {
+    ranges: Vec<u32>,
+    reverse: bool,
+}
+
+impl Ranges {
+    /// Constructs a new, empty, list of ranges with at least the
+    /// specified capacity.
+    pub fn with_capacity(capacity: usize) -> Self {
+        let mut new = Ranges::default();
+        new.reserve(capacity);
+        new
+    }
+
+    /// Add a new range which begins at the end of the previous range
+    /// and ends at the specified offset, exclusive.
+    pub fn push_end(&mut self, end: usize) {
+        debug_assert!(!self.reverse);
+        // To keep this implementation simple we explicitly store the
+        // starting index, which is always 0, so that all ranges are
+        // represented by adjacent pairs in the list. But we add it
+        // lazily so that an empty list doesn't have to allocate.
+        if self.ranges.is_empty() {
+            self.ranges.push(0);
+        }
+        self.ranges.push(u32::try_from(end).unwrap());
+    }
+
+    /// Number of ranges in this list.
+    pub fn len(&self) -> usize {
+        self.ranges.len().saturating_sub(1)
+    }
+
+    /// Reserves capacity for at least `additional` more ranges to be
+    /// added to this list.
+    pub fn reserve(&mut self, mut additional: usize) {
+        if additional > 0 && self.ranges.is_empty() {
+            additional = additional.saturating_add(1);
+        }
+        self.ranges.reserve(additional);
+    }
+
+    /// Get the range at the specified index.
+    pub fn get(&self, index: usize) -> Range<usize> {
+        let len = self.len();
+        assert!(index < len, "index {index} is too big for length {len}");
+        let index = self.map_index(index);
+        self.ranges[index] as usize..self.ranges[index + 1] as usize
+    }
+
+    /// Visit ranges in unspecified order, paired with the index each
+    /// range occurs at.
+    pub fn iter(
+        &self,
+    ) -> impl DoubleEndedIterator<Item = (usize, Range<usize>)> + ExactSizeIterator + '_ {
+        self.ranges
+            .windows(2)
+            .enumerate()
+            .map(|(index, range)| (self.map_index(index), range[0] as usize..range[1] as usize))
+    }
+
+    /// Reverse this list of ranges, so that the first range is at the
+    /// last index and the last range is at the first index.
+    ///
+    /// ```ignore
+    /// use cranelift_codegen::ranges::Ranges;
+    /// let mut ranges = Ranges::default();
+    /// ranges.push_end(4);
+    /// ranges.push_end(6);
+    /// ranges.reverse_index();
+    /// assert_eq!(ranges.get(0), 4..6);
+    /// assert_eq!(ranges.get(1), 0..4);
+    /// ```
+    pub fn reverse_index(&mut self) {
+        // We can't easily change the order of the endpoints in
+        // self.ranges: they need to be in ascending order or our
+        // compressed representation gets complicated. So instead we
+        // change our interpretation of indexes using map_index below,
+        // controlled by a simple flag. As a bonus, reversing the list
+        // is constant-time!
+        self.reverse = !self.reverse;
+    }
+
+    fn map_index(&self, index: usize) -> usize {
+        if self.reverse {
+            // These subtractions can't overflow because callers
+            // enforce that 0 <= index < self.len()
+            self.len() - 1 - index
+        } else {
+            index
+        }
+    }
+
+    /// Update these ranges to reflect that the list they refer to has
+    /// been reversed. Afterwards, the ranges will still be indexed
+    /// in the same order, but the first range will refer to the
+    /// same-length range at the end of the target list instead of at
+    /// the beginning, and subsequent ranges will proceed backwards
+    /// from there.
+    ///
+    /// ```ignore
+    /// use cranelift_codegen::ranges::Ranges;
+    /// let mut ranges = Ranges::default();
+    /// ranges.push_end(4);
+    /// ranges.push_end(6);
+    /// ranges.reverse_target(6);
+    /// assert_eq!(ranges.get(0), 2..6);
+    /// assert_eq!(ranges.get(1), 0..2);
+    /// ```
+    pub fn reverse_target(&mut self, target_len: usize) {
+        let target_len = u32::try_from(target_len).unwrap();
+        // The last endpoint added should be the same as the current
+        // length of the target list.
+        debug_assert_eq!(target_len, *self.ranges.last().unwrap_or(&0));
+        for end in self.ranges.iter_mut() {
+            *end = target_len - *end;
+        }
+        // Put the endpoints back in ascending order, but that means
+        // now our indexes are backwards.
+        self.ranges.reverse();
+        self.reverse_index();
+    }
+}
diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs
index a6c26c7f5..7d89ef5f8 100644
--- a/crates/cranelift/src/compiler.rs
+++ b/crates/cranelift/src/compiler.rs
@@ -965,8 +965,8 @@ impl Compiler {
         // Note that loads and stores are unconditionally done in the
         // little-endian format rather than the host's native-endianness,
         // despite this load/store being unrelated to execution in wasm itself.
-        // For more details on this see the `ValRaw` type in the
-        // `wasmtime-runtime` crate.
+        // For more details on this see the `ValRaw` type in
+        // `wasmtime::runtime::vm`.
         let flags = ir::MemFlags::new()
             .with_notrap()
             .with_endianness(ir::Endianness::Little);
@@ -1285,7 +1285,7 @@ fn save_last_wasm_exit_fp_and_pc(
         trampoline_fp,
         // The FP always points to the next older FP for all supported
         // targets. See assertion in
-        // `crates/runtime/src/traphandlers/backtrace.rs`.
+        // `crates/wasmtime/src/runtime/vm/traphandlers/backtrace.rs`.
         0,
     );
     builder.ins().store(
diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs
index bd50bc6d2..c44daa9f5 100644
--- a/crates/cranelift/src/lib.rs
+++ b/crates/cranelift/src/lib.rs
@@ -507,5 +507,5 @@ impl BuiltinFunctionSignatures {
 /// unboxed `i31`.
 ///
 /// Must be kept in sync with
-/// `wasmtime_runtime::gc::VMGcRef::I31_REF_DISCRIMINANT`.
+/// `crate::runtime::vm::gc::VMGcRef::I31_REF_DISCRIMINANT`.
 const I31_REF_DISCRIMINANT: u32 = 1;
diff --git a/crates/environ/src/compile/module_environ.rs b/crates/environ/src/compile/module_environ.rs
index 67f53bdde..7582f9c02 100644
--- a/crates/environ/src/compile/module_environ.rs
+++ b/crates/environ/src/compile/module_environ.rs
@@ -494,19 +494,8 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
                             offset_expr,
                         } => {
                             let table_index = TableIndex::from_u32(table_index.unwrap_or(0));
-                            let mut offset_expr_reader = offset_expr.get_binary_reader();
-                            let (base, offset) = match offset_expr_reader.read_operator()? {
-                                Operator::I32Const { value } => (None, value.unsigned()),
-                                Operator::GlobalGet { global_index } => {
-                                    (Some(GlobalIndex::from_u32(global_index)), 0)
-                                }
-                                ref s => {
-                                    bail!(WasmError::Unsupported(format!(
-                                        "unsupported init expr in element section: {:?}",
-                                        s
-                                    )));
-                                }
-                            };
+                            let (offset, escaped) = ConstExpr::from_wasmparser(offset_expr)?;
+                            debug_assert!(escaped.is_empty());
 
                             self.result
                                 .module
@@ -514,7 +503,6 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
                                 .segments
                                 .push(TableSegment {
                                     table_index,
-                                    base,
                                     offset,
                                     elements: elements.into(),
                                 });
@@ -1165,14 +1153,15 @@ impl ModuleTranslation<'_> {
             // If the base of this segment is dynamic, then we can't
             // include it in the statically-built array of initial
             // contents.
-            if segment.base.is_some() {
-                break;
-            }
+            let offset = match segment.offset.ops() {
+                &[ConstOp::I32Const(offset)] => offset.unsigned(),
+                _ => break,
+            };
 
             // Get the end of this segment. If out-of-bounds, or too
             // large for our dense table representation, then skip the
             // segment.
-            let top = match segment.offset.checked_add(segment.elements.len()) {
+            let top = match offset.checked_add(segment.elements.len()) {
                 Some(top) => top,
                 None => break,
             };
@@ -1228,7 +1217,7 @@ impl ModuleTranslation<'_> {
             if precomputed.len() < top as usize {
                 precomputed.resize(top as usize, FuncIndex::reserved_value());
             }
-            let dst = &mut precomputed[(segment.offset as usize)..(top as usize)];
+            let dst = &mut precomputed[offset as usize..top as usize];
             dst.copy_from_slice(&function_elements);
 
             // advance the iterator to see the next segment
diff --git a/crates/environ/src/module.rs b/crates/environ/src/module.rs
index b7fe41653..7d3bede30 100644
--- a/crates/environ/src/module.rs
+++ b/crates/environ/src/module.rs
@@ -427,10 +427,8 @@ pub enum TableInitialValue {
 pub struct TableSegment {
     /// The index of a table to initialize.
     pub table_index: TableIndex,
-    /// Optionally, a global variable giving a base index.
-    pub base: Option<GlobalIndex>,
-    /// The offset to add to the base.
-    pub offset: u32,
+    /// The base offset to start this segment at.
+    pub offset: ConstExpr,
     /// The values to write into the table elements.
     pub elements: TableSegmentElements,
 }
diff --git a/crates/environ/src/vmoffsets.rs b/crates/environ/src/vmoffsets.rs
index 88bc4c0e7..4678e56f0 100644
--- a/crates/environ/src/vmoffsets.rs
+++ b/crates/environ/src/vmoffsets.rs
@@ -1,5 +1,5 @@
-//! Offsets and sizes of various structs in wasmtime-runtime's vmcontext
-//! module.
+//! Offsets and sizes of various structs in `wasmtime::runtime::vm::*` that are
+//! accessed directly by compiled Wasm code.
 
 // Currently the `VMContext` allocation by field looks like this:
 //
diff --git a/crates/fuzzing/src/generators/config.rs b/crates/fuzzing/src/generators/config.rs
index 0f886e748..611ae3088 100644
--- a/crates/fuzzing/src/generators/config.rs
+++ b/crates/fuzzing/src/generators/config.rs
@@ -186,7 +186,7 @@ impl Config {
         self.wasmtime.codegen.configure(&mut cfg);
 
         // Determine whether we will actually enable PCC -- this is
-        // disabled if the module erquires memory64, which is not yet
+        // disabled if the module requires memory64, which is not yet
         // compatible (due to the need for dynamic checks).
         let pcc = cfg!(feature = "fuzz-pcc")
             && self.wasmtime.pcc
diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml
deleted file mode 100644
index 7d97e7a74..000000000
--- a/crates/runtime/Cargo.toml
+++ /dev/null
@@ -1,77 +0,0 @@
-[package]
-name = "wasmtime-runtime"
-version.workspace = true
-authors.workspace = true
-description = "Runtime library support for Wasmtime"
-documentation = "https://docs.rs/wasmtime-runtime"
-license = "Apache-2.0 WITH LLVM-exception"
-categories = ["wasm"]
-keywords = ["webassembly", "wasm"]
-repository = "https://github.com/bytecodealliance/wasmtime"
-edition.workspace = true
-
-[lints]
-workspace = true
-
-[dependencies]
-wasmtime-wmemcheck = { workspace = true, optional = true }
-wasmtime-asm-macros = { workspace = true }
-wasmtime-environ = { workspace = true }
-wasmtime-fiber = { workspace = true, optional = true }
-wasmtime-jit-debug = { workspace = true, features = ["gdb_jit_int"], optional = true }
-wasmtime-versioned-export-macros = { workspace = true }
-wasmtime-slab = { workspace = true }
-libc = { workspace = true }
-log = { workspace = true }
-memoffset = "0.9.0"
-indexmap = { workspace = true }
-cfg-if = { workspace = true }
-anyhow = { workspace = true }
-paste = "1.0.3"
-encoding_rs = { version = "0.8.31", optional = true }
-sptr = "0.3.2"
-wasm-encoder = { workspace = true, optional = true }
-smallvec = { workspace = true }
-
-[target.'cfg(target_os = "linux")'.dependencies]
-memfd = "0.6.2"
-
-[target.'cfg(target_os = "macos")'.dependencies]
-mach2 = "0.4.1"
-
-[target.'cfg(unix)'.dependencies]
-rustix = { workspace = true, features = ["mm"] }
-
-[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
-workspace = true
-features = [
-  "Win32_Foundation",
-  "Win32_System_Kernel",
-  "Win32_System_Memory",
-  "Win32_System_Diagnostics_Debug",
-  "Win32_System_SystemInformation",
-  "Win32_Storage_FileSystem",
-  "Win32_Security",
-]
-
-[target.'cfg(target_arch = "s390x")'.dependencies]
-psm = "0.1.11"
-
-[dev-dependencies]
-once_cell = { workspace = true }
-proptest = "1.0.0"
-rand = { version = "0.8.3", features = ['small_rng'] }
-
-[build-dependencies]
-cc = "1.0"
-wasmtime-versioned-export-macros = { workspace = true }
-
-[features]
-async = ["dep:wasmtime-fiber"]
-pooling-allocator = []
-component-model = ["wasmtime-environ/component-model", "dep:encoding_rs"]
-wmemcheck = ['dep:wasmtime-wmemcheck', 'wasmtime-environ/wmemcheck']
-debug-builtins = ['dep:wasmtime-jit-debug']
-gc = ["wasmtime-environ/gc"]
-coredump = ["dep:wasm-encoder"]
-threads = ["wasmtime-environ/threads"]
diff --git a/crates/runtime/LICENSE b/crates/runtime/LICENSE
deleted file mode 100644
index f9d81955f..000000000
--- a/crates/runtime/LICENSE
+++ /dev/null
@@ -1,220 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
---- LLVM Exceptions to the Apache 2.0 License ----
-
-As an exception, if, as a result of your compiling your source code, portions
-of this Software are embedded into an Object form of such source code, you
-may redistribute such embedded portions in such Object form without complying
-with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
-
-In addition, if you combine or link compiled forms of this Software with
-software that is licensed under the GPLv2 ("Combined Software") and if a
-court of competent jurisdiction determines that the patent provision (Section
-3), the indemnity provision (Section 9) or other Section of the License
-conflicts with the conditions of the GPLv2, you may retroactively and
-prospectively choose to deem waived or otherwise exclude such Section(s) of
-the License, but only in their entirety and only with respect to the Combined
-Software.
-
diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml
index 1916ec8c4..770549622 100644
--- a/crates/wasmtime/Cargo.toml
+++ b/crates/wasmtime/Cargo.toml
@@ -20,11 +20,9 @@ workspace = true
 features = ["component-model"]
 
 [dependencies]
-wasmtime-runtime = { workspace = true, optional = true }
+wasmtime-asm-macros = { workspace = true, optional = true }
 wasmtime-environ = { workspace = true }
-wasmtime-jit-debug = { workspace = true, features = [
-  "perf_jitdump",
-], optional = true }
+wasmtime-jit-debug = { workspace = true, features = ["gdb_jit_int", "perf_jitdump"], optional = true }
 wasmtime-jit-icache-coherence = { workspace = true, optional = true }
 wasmtime-cache = { workspace = true, optional = true }
 wasmtime-fiber = { workspace = true, optional = true }
@@ -33,6 +31,8 @@ wasmtime-winch = { workspace = true, optional = true }
 wasmtime-component-macro = { workspace = true, optional = true }
 wasmtime-component-util = { workspace = true, optional = true }
 wasmtime-slab = { workspace = true, optional = true }
+wasmtime-versioned-export-macros = { workspace = true }
+wasmtime-wmemcheck = { workspace = true, optional = true }
 target-lexicon = { workspace = true }
 wasmparser = { workspace = true }
 wasm-encoder = { workspace = true, optional = true }
@@ -44,6 +44,7 @@ wat = { workspace = true, optional = true }
 serde = { workspace = true }
 serde_derive = { workspace = true }
 serde_json = { workspace = true }
+sptr = { workspace = true }
 postcard = { workspace = true }
 indexmap = { workspace = true }
 paste = "1.0.3"
@@ -60,21 +61,46 @@ gimli = { workspace = true }
 addr2line = { version = "0.21.0", default-features = false, optional = true }
 semver = { version = "1.0.17", optional = true }
 smallvec = { workspace = true, optional = true }
+memoffset = { workspace = true, optional = true }
 
 [target.'cfg(target_os = "windows")'.dependencies.windows-sys]
 workspace = true
-features = ["Win32_System_Diagnostics_Debug"]
+optional = true
+features = [
+  "Win32_Foundation",
+  "Win32_System_Kernel",
+  "Win32_System_Memory",
+  "Win32_System_Diagnostics_Debug",
+  "Win32_System_SystemInformation",
+  "Win32_Storage_FileSystem",
+  "Win32_Security",
+]
 
 [target.'cfg(all(target_arch = "x86_64", not(target_os = "android")))'.dependencies]
 ittapi = { version = "0.4.0", optional = true }
 
 [target.'cfg(target_os = "linux")'.dependencies]
-rustix = { workspace = true, features = ['thread'] }
+memfd = { workspace = true, optional = true }
+
+[target.'cfg(target_os = "macos")'.dependencies]
+mach2 = { workspace = true, optional = true }
+
+[target.'cfg(unix)'.dependencies]
+rustix = { workspace = true, optional = true }
+
+[target.'cfg(target_arch = "s390x")'.dependencies]
+psm = { workspace = true, optional = true }
 
 [dev-dependencies]
-tempfile = "3.0"
+proptest = { workspace = true }
+rand = { workspace = true }
+tempfile = { workspace = true }
 wasi-common = { path = "../wasi-common", default-features = true }
 
+[build-dependencies]
+cc = { workspace = true, optional = true }
+wasmtime-versioned-export-macros = { workspace = true, optional = true }
+
 # =============================================================================
 #
 # Features for the Wasmtime crate.
@@ -122,6 +148,8 @@ profiling = [
   "dep:fxprof-processed-profile",
   "dep:wasmtime-jit-debug",
   "dep:ittapi",
+  "dep:rustix",
+  "rustix/thread"
 ]
 
 # Enables parallel compilation of WebAssembly code.
@@ -134,14 +162,13 @@ cache = ["dep:wasmtime-cache"]
 # `async fn` and calling functions asynchronously.
 async = [
   "dep:wasmtime-fiber",
-  "wasmtime-runtime/async",
   "dep:async-trait",
   "wasmtime-component-macro?/async",
   "runtime",
 ]
 
 # Enables support for the pooling instance allocation strategy
-pooling-allocator = ["runtime", "wasmtime-runtime/pooling-allocator"]
+pooling-allocator = ["runtime"]
 
 # Enables support for all architectures in Cranelift, allowing
 # cross-compilation using the `wasmtime` crate's API, notably the
@@ -155,32 +182,44 @@ component-model = [
   "wasmtime-environ/component-model",
   "wasmtime-cranelift?/component-model",
   "wasmtime-winch?/component-model",
-  "wasmtime-runtime?/component-model",
   "dep:wasmtime-component-macro",
   "dep:wasmtime-component-util",
   "dep:encoding_rs",
   "dep:semver",
 ]
 
-wmemcheck = ["wasmtime-runtime?/wmemcheck", "wasmtime-cranelift?/wmemcheck"]
+wmemcheck = [
+  "dep:wasmtime-wmemcheck",
+  "wasmtime-cranelift?/wmemcheck",
+  "wasmtime-environ/wmemcheck",
+]
 
 # Enables support for demangling WebAssembly function names at runtime in
 # errors such as backtraces.
 demangle = ["wasmtime-environ/demangle"]
 
 # Enable support for generating core dumps on traps.
-coredump = ["dep:wasm-encoder", "runtime", "wasmtime-runtime/coredump"]
+coredump = ["dep:wasm-encoder", "runtime"]
 
 # Export some symbols from the final binary to assist in debugging
 # Cranelift-generated code with native debuggers like GDB and LLDB.
-debug-builtins = ["wasmtime-runtime?/debug-builtins"]
+debug-builtins = ["dep:wasmtime-jit-debug"]
 
 # Enable support for executing compiled Wasm modules.
 runtime = [
-  "dep:wasmtime-runtime",
+  "dep:cc",
+  "dep:smallvec",
+  "dep:mach2",
+  "dep:memfd",
+  "dep:memoffset",
+  "dep:wasmtime-asm-macros",
   "dep:wasmtime-jit-icache-coherence",
   "dep:wasmtime-slab",
-  "dep:smallvec",
+  "dep:wasmtime-versioned-export-macros",
+  "dep:windows-sys",
+  "dep:psm",
+  "dep:rustix",
+  "rustix/mm"
 ]
 
 # Enable support for garbage collection-related things.
@@ -197,7 +236,7 @@ runtime = [
 #
 # When the `runtime` Cargo feature is enabled, this feature gates the ability to
 # load and run Wasm that uses those proposals.
-gc = ["wasmtime-environ/gc", "wasmtime-runtime?/gc", "wasmtime-cranelift?/gc"]
+gc = ["wasmtime-environ/gc", "wasmtime-cranelift?/gc"]
 
 # Enable runtime support for the WebAssembly threads proposal.
-threads = ["wasmtime-runtime?/threads", "wasmtime-cranelift?/threads"]
+threads = ["wasmtime-cranelift?/threads"]
diff --git a/crates/runtime/build.rs b/crates/wasmtime/build.rs
similarity index 57%
rename from crates/runtime/build.rs
rename to crates/wasmtime/build.rs
index a05ea87fa..4a38be574 100644
--- a/crates/runtime/build.rs
+++ b/crates/wasmtime/build.rs
@@ -1,11 +1,16 @@
-use std::env;
-use wasmtime_versioned_export_macros::versioned_suffix;
-
 fn main() {
     println!("cargo:rerun-if-changed=build.rs");
 
+    #[cfg(feature = "runtime")]
+    build_c_helpers();
+}
+
+#[cfg(feature = "runtime")]
+fn build_c_helpers() {
+    use wasmtime_versioned_export_macros::versioned_suffix;
+
     // NB: duplicating a workaround in the wasmtime-fiber build script.
-    match env::var("CARGO_CFG_SANITIZE") {
+    match std::env::var("CARGO_CFG_SANITIZE") {
         Ok(s) if s == "address" => {
             println!("cargo:rustc-cfg=asan");
         }
@@ -15,18 +20,18 @@ fn main() {
     // If this platform is neither unix nor windows then there's no default need
     // for a C helper library since `helpers.c` is tailored for just these
     // platforms currently.
-    if env::var("CARGO_CFG_UNIX").is_err() && env::var("CARGO_CFG_WINDOWS").is_err() {
+    if std::env::var("CARGO_CFG_UNIX").is_err() && std::env::var("CARGO_CFG_WINDOWS").is_err() {
         return;
     }
 
     let mut build = cc::Build::new();
     build.warnings(true);
-    let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
-    let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
+    let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
+    let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
     build.define(&format!("CFG_TARGET_OS_{}", os), None);
     build.define(&format!("CFG_TARGET_ARCH_{}", arch), None);
     build.define("VERSIONED_SUFFIX", Some(versioned_suffix!()));
-    println!("cargo:rerun-if-changed=src/helpers.c");
-    build.file("src/helpers.c");
+    println!("cargo:rerun-if-changed=src/runtime/vm/helpers.c");
+    build.file("src/runtime/vm/helpers.c");
     build.compile("wasmtime-helpers");
 }
diff --git a/crates/runtime/proptest-regressions/instance/allocator/pooling/memory_pool.txt b/crates/wasmtime/proptest-regressions/runtime/vm/instance/allocator/pooling/memory_pool.txt
similarity index 100%
rename from crates/runtime/proptest-regressions/instance/allocator/pooling/memory_pool.txt
rename to crates/wasmtime/proptest-regressions/runtime/vm/instance/allocator/pooling/memory_pool.txt
diff --git a/crates/wasmtime/src/compile/runtime.rs b/crates/wasmtime/src/compile/runtime.rs
index 0887cfb36..cd7d1c286 100644
--- a/crates/wasmtime/src/compile/runtime.rs
+++ b/crates/wasmtime/src/compile/runtime.rs
@@ -1,12 +1,12 @@
 use crate::compile::HashedEngineCompileEnv;
 #[cfg(feature = "component-model")]
 use crate::component::Component;
+use crate::runtime::vm::MmapVec;
 use crate::{CodeBuilder, CodeMemory, Engine, Module};
 use anyhow::{Context, Error, Result};
 use object::write::WritableBuffer;
 use std::sync::Arc;
 use wasmtime_environ::{FinishedObject, ObjectBuilder, ObjectKind};
-use wasmtime_runtime::MmapVec;
 
 impl<'a> CodeBuilder<'a> {
     fn compile_cached<T>(
diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs
index 0f55516df..84ae3cc12 100644
--- a/crates/wasmtime/src/config.rs
+++ b/crates/wasmtime/src/config.rs
@@ -17,23 +17,23 @@ use crate::memory::MemoryCreator;
 #[cfg(feature = "runtime")]
 use crate::profiling_agent::{self, ProfilingAgent};
 #[cfg(feature = "runtime")]
-use crate::trampoline::MemoryCreatorProxy;
-#[cfg(feature = "runtime")]
-use wasmtime_runtime::{
+use crate::runtime::vm::{
     GcRuntime, InstanceAllocator, OnDemandInstanceAllocator, RuntimeMemoryCreator,
 };
+#[cfg(feature = "runtime")]
+use crate::trampoline::MemoryCreatorProxy;
 
 #[cfg(feature = "async")]
 use crate::stack::{StackCreator, StackCreatorProxy};
 #[cfg(feature = "async")]
 use wasmtime_fiber::RuntimeFiberStackCreator;
 
-#[cfg(all(feature = "incremental-cache", feature = "cranelift"))]
-pub use wasmtime_environ::CacheStore;
 #[cfg(feature = "pooling-allocator")]
-use wasmtime_runtime::mpk;
+use crate::runtime::vm::mpk;
 #[cfg(feature = "pooling-allocator")]
-pub use wasmtime_runtime::MpkEnabled;
+pub use crate::runtime::vm::MpkEnabled;
+#[cfg(all(feature = "incremental-cache", feature = "cranelift"))]
+pub use wasmtime_environ::CacheStore;
 
 /// Represents the module instance allocation strategy to use.
 #[derive(Clone)]
@@ -1798,7 +1798,7 @@ impl Config {
             InstanceAllocationStrategy::Pooling(config) => {
                 let mut config = config.config;
                 config.stack_size = stack_size;
-                Ok(Box::new(wasmtime_runtime::PoolingInstanceAllocator::new(
+                Ok(Box::new(crate::runtime::vm::PoolingInstanceAllocator::new(
                     &config, tunables,
                 )?))
             }
@@ -1807,7 +1807,7 @@ impl Config {
 
     #[cfg(feature = "runtime")]
     pub(crate) fn build_gc_runtime(&self) -> Result<Arc<dyn GcRuntime>> {
-        Ok(Arc::new(wasmtime_runtime::default_gc_runtime()) as Arc<dyn GcRuntime>)
+        Ok(Arc::new(crate::runtime::vm::default_gc_runtime()) as Arc<dyn GcRuntime>)
     }
 
     #[cfg(feature = "runtime")]
@@ -1999,7 +1999,7 @@ fn round_up_to_pages(val: u64) -> u64 {
 
 #[cfg(feature = "runtime")]
 fn round_up_to_pages(val: u64) -> u64 {
-    let page_size = wasmtime_runtime::page_size() as u64;
+    let page_size = crate::runtime::vm::page_size() as u64;
     debug_assert!(page_size.is_power_of_two());
     val.checked_add(page_size - 1)
         .map(|val| val & !(page_size - 1))
@@ -2236,7 +2236,7 @@ pub enum WasmBacktraceDetails {
 #[cfg(feature = "pooling-allocator")]
 #[derive(Debug, Clone, Default)]
 pub struct PoolingAllocationConfig {
-    config: wasmtime_runtime::PoolingInstanceAllocatorConfig,
+    config: crate::runtime::vm::PoolingInstanceAllocatorConfig,
 }
 
 #[cfg(feature = "pooling-allocator")]
diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs
index 02b2f376a..47f8dd419 100644
--- a/crates/wasmtime/src/engine.rs
+++ b/crates/wasmtime/src/engine.rs
@@ -1,5 +1,7 @@
 #[cfg(feature = "runtime")]
 use crate::runtime::type_registry::TypeRegistry;
+#[cfg(feature = "runtime")]
+use crate::runtime::vm::GcRuntime;
 use crate::Config;
 use anyhow::{Context, Result};
 #[cfg(any(feature = "cranelift", feature = "winch"))]
@@ -12,8 +14,6 @@ use std::sync::Arc;
 use wasmparser::WasmFeatures;
 use wasmtime_environ::obj;
 use wasmtime_environ::{FlagValue, ObjectKind, Tunables};
-#[cfg(feature = "runtime")]
-use wasmtime_runtime::GcRuntime;
 
 mod serialization;
 
@@ -50,7 +50,7 @@ struct EngineInner {
     #[cfg(any(feature = "cranelift", feature = "winch"))]
     compiler: Box<dyn wasmtime_environ::Compiler>,
     #[cfg(feature = "runtime")]
-    allocator: Box<dyn wasmtime_runtime::InstanceAllocator + Send + Sync>,
+    allocator: Box<dyn crate::runtime::vm::InstanceAllocator + Send + Sync>,
     #[cfg(feature = "runtime")]
     gc_runtime: Arc<dyn GcRuntime>,
     #[cfg(feature = "runtime")]
@@ -60,7 +60,7 @@ struct EngineInner {
     #[cfg(feature = "runtime")]
     epoch: AtomicU64,
     #[cfg(feature = "runtime")]
-    unique_id_allocator: wasmtime_runtime::CompiledModuleIdAllocator,
+    unique_id_allocator: crate::runtime::vm::CompiledModuleIdAllocator,
 
     /// One-time check of whether the compiler's settings, if present, are
     /// compatible with the native host.
@@ -89,12 +89,16 @@ impl Engine {
     pub fn new(config: &Config) -> Result<Engine> {
         #[cfg(feature = "runtime")]
         {
-            // Ensure that wasmtime_runtime's signal handlers are configured. This
-            // is the per-program initialization required for handling traps, such
-            // as configuring signals, vectored exception handlers, etc.
-            wasmtime_runtime::init_traps(crate::module::get_wasm_trap, config.macos_use_mach_ports);
+            // Ensure that crate::runtime::vm's signal handlers are
+            // configured. This is the per-program initialization required for
+            // handling traps, such as configuring signals, vectored exception
+            // handlers, etc.
+            crate::runtime::vm::init_traps(
+                crate::module::get_wasm_trap,
+                config.macos_use_mach_ports,
+            );
             #[cfg(feature = "debug-builtins")]
-            wasmtime_runtime::debug_builtins::ensure_exported();
+            crate::runtime::vm::debug_builtins::ensure_exported();
         }
 
         let config = config.clone();
@@ -118,7 +122,7 @@ impl Engine {
                 #[cfg(feature = "runtime")]
                 epoch: AtomicU64::new(0),
                 #[cfg(feature = "runtime")]
-                unique_id_allocator: wasmtime_runtime::CompiledModuleIdAllocator::new(),
+                unique_id_allocator: crate::runtime::vm::CompiledModuleIdAllocator::new(),
                 compatible_with_native_host: OnceCell::new(),
                 config,
                 tunables,
@@ -591,10 +595,10 @@ impl Engine {
     /// latency of WebAssembly calls are extra-important, which is not
     /// necessarily true of all embeddings.
     pub fn tls_eager_initialize() {
-        wasmtime_runtime::tls_eager_initialize();
+        crate::runtime::vm::tls_eager_initialize();
     }
 
-    pub(crate) fn allocator(&self) -> &dyn wasmtime_runtime::InstanceAllocator {
+    pub(crate) fn allocator(&self) -> &dyn crate::runtime::vm::InstanceAllocator {
         self.inner.allocator.as_ref()
     }
 
@@ -652,7 +656,7 @@ impl Engine {
         self.inner.epoch.fetch_add(1, Ordering::Relaxed);
     }
 
-    pub(crate) fn unique_id_allocator(&self) -> &wasmtime_runtime::CompiledModuleIdAllocator {
+    pub(crate) fn unique_id_allocator(&self) -> &crate::runtime::vm::CompiledModuleIdAllocator {
         &self.inner.unique_id_allocator
     }
 
@@ -697,7 +701,7 @@ impl Engine {
         bytes: &[u8],
         expected: ObjectKind,
     ) -> Result<Arc<crate::CodeMemory>> {
-        self.load_code(wasmtime_runtime::MmapVec::from_slice(bytes)?, expected)
+        self.load_code(crate::runtime::vm::MmapVec::from_slice(bytes)?, expected)
     }
 
     /// Like `load_code_bytes`, but creates a mmap from a file on disk.
@@ -707,7 +711,7 @@ impl Engine {
         expected: ObjectKind,
     ) -> Result<Arc<crate::CodeMemory>> {
         self.load_code(
-            wasmtime_runtime::MmapVec::from_file(path).with_context(|| {
+            crate::runtime::vm::MmapVec::from_file(path).with_context(|| {
                 format!("failed to create file mapping for: {}", path.display())
             })?,
             expected,
@@ -716,7 +720,7 @@ impl Engine {
 
     pub(crate) fn load_code(
         &self,
-        mmap: wasmtime_runtime::MmapVec,
+        mmap: crate::runtime::vm::MmapVec,
         expected: ObjectKind,
     ) -> Result<Arc<crate::CodeMemory>> {
         serialization::check_compatible(self, &mmap, expected)?;
diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs
index 2c0e23be8..53771a359 100644
--- a/crates/wasmtime/src/lib.rs
+++ b/crates/wasmtime/src/lib.rs
@@ -301,3 +301,10 @@ fn _assertions_lib() {
     _assert_send_and_sync::<Engine>();
     _assert_send_and_sync::<Config>();
 }
+
+#[cfg(feature = "runtime")]
+#[doc(hidden)]
+pub mod _internal {
+    // Exported just for the CLI.
+    pub use crate::runtime::vm::MmapVec;
+}
diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs
index 69ed3c91b..af43f0b39 100644
--- a/crates/wasmtime/src/runtime.rs
+++ b/crates/wasmtime/src/runtime.rs
@@ -24,6 +24,7 @@ pub(crate) mod types;
 pub(crate) mod uninhabited;
 pub(crate) mod v128;
 pub(crate) mod values;
+pub(crate) mod vm;
 
 #[cfg(feature = "component-model")]
 pub mod component;
diff --git a/crates/wasmtime/src/runtime/code_memory.rs b/crates/wasmtime/src/runtime/code_memory.rs
index d09121935..4b5a1b2d6 100644
--- a/crates/wasmtime/src/runtime/code_memory.rs
+++ b/crates/wasmtime/src/runtime/code_memory.rs
@@ -1,5 +1,6 @@
 //! Memory management for executable code.
 
+use crate::runtime::vm::{libcalls, MmapVec, UnwindRegistration};
 use anyhow::{anyhow, bail, Context, Result};
 use object::read::{File, Object, ObjectSection};
 use object::ObjectSymbol;
@@ -7,7 +8,6 @@ use std::mem::ManuallyDrop;
 use std::ops::Range;
 use wasmtime_environ::obj;
 use wasmtime_jit_icache_coherence as icache_coherence;
-use wasmtime_runtime::{libcalls, MmapVec, UnwindRegistration};
 
 /// Management of executable memory within a `MmapVec`
 ///
diff --git a/crates/wasmtime/src/runtime/component/component.rs b/crates/wasmtime/src/runtime/component/component.rs
index 09908b6b4..3cb1cb967 100644
--- a/crates/wasmtime/src/runtime/component/component.rs
+++ b/crates/wasmtime/src/runtime/component/component.rs
@@ -1,5 +1,9 @@
 use crate::component::matching::InstanceType;
 use crate::component::types;
+use crate::runtime::vm::component::ComponentRuntimeInfo;
+use crate::runtime::vm::{
+    VMArrayCallFunction, VMFuncRef, VMFunctionBody, VMNativeCallFunction, VMWasmCallFunction,
+};
 use crate::{
     code::CodeObject, code_memory::CodeMemory, type_registry::TypeCollection, Engine, Module,
     ResourcesRequired,
@@ -15,12 +19,7 @@ use wasmtime_environ::component::{
     AllCallFunc, CompiledComponentInfo, ComponentArtifacts, ComponentTypes, GlobalInitializer,
     InstantiateModule, StaticModuleIndex, TrampolineIndex, TypeComponentIndex, VMComponentOffsets,
 };
-
 use wasmtime_environ::{FunctionLoc, HostPtr, ObjectKind, PrimaryMap};
-use wasmtime_runtime::component::ComponentRuntimeInfo;
-use wasmtime_runtime::{
-    VMArrayCallFunction, VMFuncRef, VMFunctionBody, VMNativeCallFunction, VMWasmCallFunction,
-};
 
 /// A compiled WebAssembly Component.
 ///
@@ -604,7 +603,7 @@ impl Component {
     /// compiled code resides at.
     ///
     /// For more information see
-    /// [`Module;:image_range`](crate::Module::image_range).
+    /// [`Module::image_range`](crate::Module::image_range).
     pub fn image_range(&self) -> Range<*const u8> {
         self.inner.code.code_memory().mmap().image_range()
     }
diff --git a/crates/wasmtime/src/runtime/component/func.rs b/crates/wasmtime/src/runtime/component/func.rs
index 2791da879..04300abe3 100644
--- a/crates/wasmtime/src/runtime/component/func.rs
+++ b/crates/wasmtime/src/runtime/component/func.rs
@@ -2,6 +2,8 @@ use crate::component::instance::{Instance, InstanceData};
 use crate::component::storage::storage_as_slice;
 use crate::component::types::Type;
 use crate::component::values::Val;
+use crate::runtime::vm::component::ResourceTables;
+use crate::runtime::vm::{Export, ExportFunction};
 use crate::store::{StoreOpaque, Stored};
 use crate::{AsContext, AsContextMut, StoreContextMut, ValRaw};
 use anyhow::{bail, Context, Result};
@@ -12,8 +14,6 @@ use wasmtime_environ::component::{
     CanonicalOptions, ComponentTypes, CoreDef, InterfaceType, RuntimeComponentInstanceIndex,
     TypeFuncIndex, TypeTuple, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
 };
-use wasmtime_runtime::component::ResourceTables;
-use wasmtime_runtime::{Export, ExportFunction};
 
 /// A helper macro to safely map `MaybeUninit<T>` to `MaybeUninit<U>` where `U`
 /// is a field projection within `T`.
diff --git a/crates/wasmtime/src/runtime/component/func/host.rs b/crates/wasmtime/src/runtime/component/func/host.rs
index a11477231..81e4d2fd5 100644
--- a/crates/wasmtime/src/runtime/component/func/host.rs
+++ b/crates/wasmtime/src/runtime/component/func/host.rs
@@ -2,6 +2,10 @@ use crate::component::func::{LiftContext, LowerContext, Options};
 use crate::component::matching::InstanceType;
 use crate::component::storage::slice_to_storage_mut;
 use crate::component::{ComponentNamedList, ComponentType, Lift, Lower, Val};
+use crate::runtime::vm::component::{
+    InstanceFlags, VMComponentContext, VMLowering, VMLoweringCallee,
+};
+use crate::runtime::vm::{VMFuncRef, VMMemoryDefinition, VMOpaqueContext};
 use crate::{AsContextMut, StoreContextMut, ValRaw};
 use anyhow::{bail, Context, Result};
 use std::any::Any;
@@ -12,10 +16,6 @@ use wasmtime_environ::component::{
     CanonicalAbiInfo, InterfaceType, StringEncoding, TypeFuncIndex, MAX_FLAT_PARAMS,
     MAX_FLAT_RESULTS,
 };
-use wasmtime_runtime::component::{
-    InstanceFlags, VMComponentContext, VMLowering, VMLoweringCallee,
-};
-use wasmtime_runtime::{VMFuncRef, VMMemoryDefinition, VMOpaqueContext};
 
 pub struct HostFunc {
     entrypoint: VMLoweringCallee,
@@ -290,7 +290,7 @@ fn validate_inbounds<T: ComponentType>(memory: &[u8], ptr: &ValRaw) -> Result<us
 }
 
 unsafe fn handle_result(func: impl FnOnce() -> Result<()>) {
-    match wasmtime_runtime::catch_unwind_and_longjmp(func) {
+    match crate::runtime::vm::catch_unwind_and_longjmp(func) {
         Ok(()) => {}
         Err(e) => crate::trap::raise(e),
     }
diff --git a/crates/wasmtime/src/runtime/component/func/options.rs b/crates/wasmtime/src/runtime/component/func/options.rs
index 5406a764e..20bc865f1 100644
--- a/crates/wasmtime/src/runtime/component/func/options.rs
+++ b/crates/wasmtime/src/runtime/component/func/options.rs
@@ -1,16 +1,16 @@
 use crate::component::matching::InstanceType;
 use crate::component::resources::{HostResourceData, HostResourceIndex, HostResourceTables};
 use crate::component::ResourceType;
+use crate::runtime::vm::component::{
+    CallContexts, ComponentInstance, InstanceFlags, ResourceTable, ResourceTables,
+};
+use crate::runtime::vm::{VMFuncRef, VMMemoryDefinition};
 use crate::store::{StoreId, StoreOpaque};
 use crate::{FuncType, StoreContextMut};
 use anyhow::{bail, Result};
 use std::ptr::NonNull;
 use std::sync::Arc;
 use wasmtime_environ::component::{ComponentTypes, StringEncoding, TypeResourceTableIndex};
-use wasmtime_runtime::component::{
-    CallContexts, ComponentInstance, InstanceFlags, ResourceTable, ResourceTables,
-};
-use wasmtime_runtime::{VMFuncRef, VMMemoryDefinition};
 
 /// Runtime representation of canonical ABI options in the component model.
 ///
diff --git a/crates/wasmtime/src/runtime/component/func/typed.rs b/crates/wasmtime/src/runtime/component/func/typed.rs
index 3240a884a..a328087e5 100644
--- a/crates/wasmtime/src/runtime/component/func/typed.rs
+++ b/crates/wasmtime/src/runtime/component/func/typed.rs
@@ -1,6 +1,8 @@
 use crate::component::func::{Func, LiftContext, LowerContext, Options};
 use crate::component::matching::InstanceType;
 use crate::component::storage::{storage_as_slice, storage_as_slice_mut};
+use crate::runtime::vm::component::ComponentInstance;
+use crate::runtime::vm::SendSyncPtr;
 use crate::{AsContextMut, StoreContext, StoreContextMut, ValRaw};
 use anyhow::{anyhow, bail, Context, Result};
 use std::borrow::Cow;
@@ -14,8 +16,6 @@ use wasmtime_environ::component::{
     CanonicalAbiInfo, ComponentTypes, InterfaceType, StringEncoding, VariantInfo, MAX_FLAT_PARAMS,
     MAX_FLAT_RESULTS,
 };
-use wasmtime_runtime::component::ComponentInstance;
-use wasmtime_runtime::SendSyncPtr;
 
 /// A statically-typed version of [`Func`] which takes `Params` as input and
 /// returns `Return`.
diff --git a/crates/wasmtime/src/runtime/component/instance.rs b/crates/wasmtime/src/runtime/component/instance.rs
index 7a10c3cc6..6ecb9c678 100644
--- a/crates/wasmtime/src/runtime/component/instance.rs
+++ b/crates/wasmtime/src/runtime/component/instance.rs
@@ -3,6 +3,8 @@ use crate::component::matching::InstanceType;
 use crate::component::{Component, ComponentNamedList, Func, Lift, Lower, ResourceType, TypedFunc};
 use crate::instance::OwnedImports;
 use crate::linker::DefinitionType;
+use crate::runtime::vm::component::{ComponentInstance, OwnedComponentInstance};
+use crate::runtime::vm::VMFuncRef;
 use crate::store::{StoreOpaque, Stored};
 use crate::{AsContextMut, Module, StoreContextMut};
 use anyhow::{anyhow, Context, Result};
@@ -12,8 +14,6 @@ use std::ptr::NonNull;
 use std::sync::Arc;
 use wasmtime_environ::{component::*, EngineOrModuleTypeIndex};
 use wasmtime_environ::{EntityIndex, EntityType, Global, PrimaryMap, WasmValType};
-use wasmtime_runtime::component::{ComponentInstance, OwnedComponentInstance};
-use wasmtime_runtime::VMFuncRef;
 
 /// An instantiated component.
 ///
@@ -153,16 +153,16 @@ impl Instance {
 }
 
 impl InstanceData {
-    pub fn lookup_def(&self, store: &mut StoreOpaque, def: &CoreDef) -> wasmtime_runtime::Export {
+    pub fn lookup_def(&self, store: &mut StoreOpaque, def: &CoreDef) -> crate::runtime::vm::Export {
         match def {
             CoreDef::Export(e) => self.lookup_export(store, e),
             CoreDef::Trampoline(idx) => {
-                wasmtime_runtime::Export::Function(wasmtime_runtime::ExportFunction {
+                crate::runtime::vm::Export::Function(crate::runtime::vm::ExportFunction {
                     func_ref: self.state.trampoline_func_ref(*idx),
                 })
             }
             CoreDef::InstanceFlags(idx) => {
-                wasmtime_runtime::Export::Global(wasmtime_runtime::ExportGlobal {
+                crate::runtime::vm::Export::Global(crate::runtime::vm::ExportGlobal {
                     definition: self.state.instance_flags(*idx).as_raw(),
                     vmctx: std::ptr::null_mut(),
                     global: Global {
@@ -178,7 +178,7 @@ impl InstanceData {
         &self,
         store: &mut StoreOpaque,
         item: &CoreExport<T>,
-    ) -> wasmtime_runtime::Export
+    ) -> crate::runtime::vm::Export
     where
         T: Copy + Into<EntityIndex>,
     {
@@ -410,7 +410,7 @@ impl<'a> Instantiator<'a> {
             .as_ref()
             .map(|dtor| self.data.lookup_def(store, dtor));
         let dtor = dtor.map(|export| match export {
-            wasmtime_runtime::Export::Function(f) => f.func_ref,
+            crate::runtime::vm::Export::Function(f) => f.func_ref,
             _ => unreachable!(),
         });
         let index = self
@@ -425,7 +425,7 @@ impl<'a> Instantiator<'a> {
 
     fn extract_memory(&mut self, store: &mut StoreOpaque, memory: &ExtractMemory) {
         let mem = match self.data.lookup_export(store, &memory.export) {
-            wasmtime_runtime::Export::Memory(m) => m,
+            crate::runtime::vm::Export::Memory(m) => m,
             _ => unreachable!(),
         };
         self.data
@@ -435,7 +435,7 @@ impl<'a> Instantiator<'a> {
 
     fn extract_realloc(&mut self, store: &mut StoreOpaque, realloc: &ExtractRealloc) {
         let func_ref = match self.data.lookup_def(store, &realloc.def) {
-            wasmtime_runtime::Export::Function(f) => f.func_ref,
+            crate::runtime::vm::Export::Function(f) => f.func_ref,
             _ => unreachable!(),
         };
         self.data.state.set_runtime_realloc(realloc.index, func_ref);
@@ -443,7 +443,7 @@ impl<'a> Instantiator<'a> {
 
     fn extract_post_return(&mut self, store: &mut StoreOpaque, post_return: &ExtractPostReturn) {
         let func_ref = match self.data.lookup_def(store, &post_return.def) {
-            wasmtime_runtime::Export::Function(f) => f.func_ref,
+            crate::runtime::vm::Export::Function(f) => f.func_ref,
             _ => unreachable!(),
         };
         self.data
@@ -500,7 +500,7 @@ impl<'a> Instantiator<'a> {
         // here. This can otherwise fail `Extern::from_wasmtime_export` because
         // there's no guarantee that there exists a trampoline for `f` so this
         // can't fall through to the case below
-        if let wasmtime_runtime::Export::Function(f) = &export {
+        if let crate::runtime::vm::Export::Function(f) = &export {
             let expected = match expected.unwrap_func() {
                 EngineOrModuleTypeIndex::Engine(e) => Some(e),
                 EngineOrModuleTypeIndex::Module(m) => module.signatures().shared_type(m),
diff --git a/crates/wasmtime/src/runtime/component/matching.rs b/crates/wasmtime/src/runtime/component/matching.rs
index ed97896dc..cce569ceb 100644
--- a/crates/wasmtime/src/runtime/component/matching.rs
+++ b/crates/wasmtime/src/runtime/component/matching.rs
@@ -1,6 +1,7 @@
 use crate::component::func::HostFunc;
 use crate::component::linker::{Definition, NameMap, Strings};
 use crate::component::ResourceType;
+use crate::runtime::vm::component::ComponentInstance;
 use crate::types::matching;
 use crate::Module;
 use anyhow::{anyhow, bail, Context, Result};
@@ -11,7 +12,6 @@ use wasmtime_environ::component::{
     TypeResourceTableIndex,
 };
 use wasmtime_environ::PrimaryMap;
-use wasmtime_runtime::component::ComponentInstance;
 
 pub struct TypeChecker<'a> {
     pub types: &'a Arc<ComponentTypes>,
diff --git a/crates/wasmtime/src/runtime/component/resources.rs b/crates/wasmtime/src/runtime/component/resources.rs
index c2b3cf697..789329523 100644
--- a/crates/wasmtime/src/runtime/component/resources.rs
+++ b/crates/wasmtime/src/runtime/component/resources.rs
@@ -1,6 +1,8 @@
 use crate::component::func::{bad_type_info, desc, LiftContext, LowerContext};
 use crate::component::matching::InstanceType;
 use crate::component::{ComponentType, Lift, Lower};
+use crate::runtime::vm::component::{ComponentInstance, InstanceFlags, ResourceTables};
+use crate::runtime::vm::{SendSyncPtr, VMFuncRef, ValRaw};
 use crate::store::{StoreId, StoreOpaque};
 use crate::{AsContextMut, StoreContextMut, Trap};
 use anyhow::{bail, ensure, Result};
@@ -14,8 +16,6 @@ use wasmtime_environ::component::{
     CanonicalAbiInfo, ComponentTypes, DefinedResourceIndex, InterfaceType, ResourceIndex,
     TypeResourceTableIndex,
 };
-use wasmtime_runtime::component::{ComponentInstance, InstanceFlags, ResourceTables};
-use wasmtime_runtime::{SendSyncPtr, VMFuncRef, ValRaw};
 
 /// Representation of a resource type in the component model.
 ///
diff --git a/crates/wasmtime/src/runtime/externals.rs b/crates/wasmtime/src/runtime/externals.rs
index c627f38e2..d457a13a5 100644
--- a/crates/wasmtime/src/runtime/externals.rs
+++ b/crates/wasmtime/src/runtime/externals.rs
@@ -104,24 +104,24 @@ impl Extern {
     }
 
     pub(crate) unsafe fn from_wasmtime_export(
-        wasmtime_export: wasmtime_runtime::Export,
+        wasmtime_export: crate::runtime::vm::Export,
         store: &mut StoreOpaque,
     ) -> Extern {
         match wasmtime_export {
-            wasmtime_runtime::Export::Function(f) => {
+            crate::runtime::vm::Export::Function(f) => {
                 Extern::Func(Func::from_wasmtime_function(f, store))
             }
-            wasmtime_runtime::Export::Memory(m) => {
+            crate::runtime::vm::Export::Memory(m) => {
                 if m.memory.memory.shared {
                     Extern::SharedMemory(SharedMemory::from_wasmtime_memory(m, store))
                 } else {
                     Extern::Memory(Memory::from_wasmtime_memory(m, store))
                 }
             }
-            wasmtime_runtime::Export::Global(g) => {
+            crate::runtime::vm::Export::Global(g) => {
                 Extern::Global(Global::from_wasmtime_global(g, store))
             }
-            wasmtime_runtime::Export::Table(t) => {
+            crate::runtime::vm::Export::Table(t) => {
                 Extern::Table(Table::from_wasmtime_table(t, store))
             }
         }
diff --git a/crates/wasmtime/src/runtime/externals/global.rs b/crates/wasmtime/src/runtime/externals/global.rs
index f2dbab34e..36da5f5b7 100644
--- a/crates/wasmtime/src/runtime/externals/global.rs
+++ b/crates/wasmtime/src/runtime/externals/global.rs
@@ -1,3 +1,4 @@
+use crate::runtime::vm::{GcRootsList, SendSyncPtr};
 use crate::{
     store::{AutoAssertNoGc, StoreData, StoreOpaque, Stored},
     trampoline::generate_global_export,
@@ -8,7 +9,6 @@ use anyhow::{bail, Context, Result};
 use std::ptr;
 use std::ptr::NonNull;
 use wasmtime_environ::TypeTrace;
-use wasmtime_runtime::{GcRootsList, SendSyncPtr};
 
 /// A WebAssembly `global` value which can be read and written to.
 ///
@@ -24,7 +24,7 @@ use wasmtime_runtime::{GcRootsList, SendSyncPtr};
 /// methods will panic.
 #[derive(Copy, Clone, Debug)]
 #[repr(transparent)] // here for the C API
-pub struct Global(pub(super) Stored<wasmtime_runtime::ExportGlobal>);
+pub struct Global(pub(super) Stored<crate::runtime::vm::ExportGlobal>);
 
 impl Global {
     /// Creates a new WebAssembly `global` value with the provide type `ty` and
@@ -226,14 +226,14 @@ impl Global {
     }
 
     pub(crate) unsafe fn from_wasmtime_global(
-        mut wasmtime_export: wasmtime_runtime::ExportGlobal,
+        mut wasmtime_export: crate::runtime::vm::ExportGlobal,
         store: &mut StoreOpaque,
     ) -> Global {
         wasmtime_export
             .global
             .wasm_ty
             .canonicalize_for_runtime_usage(&mut |module_index| {
-                wasmtime_runtime::Instance::from_vmctx(wasmtime_export.vmctx, |instance| {
+                crate::runtime::vm::Instance::from_vmctx(wasmtime_export.vmctx, |instance| {
                     instance.engine_type_index(module_index)
                 })
             });
@@ -245,8 +245,8 @@ impl Global {
         &data[self.0].global
     }
 
-    pub(crate) fn vmimport(&self, store: &StoreOpaque) -> wasmtime_runtime::VMGlobalImport {
-        wasmtime_runtime::VMGlobalImport {
+    pub(crate) fn vmimport(&self, store: &StoreOpaque) -> crate::runtime::vm::VMGlobalImport {
+        crate::runtime::vm::VMGlobalImport {
             from: store[self.0].definition,
         }
     }
diff --git a/crates/wasmtime/src/runtime/externals/table.rs b/crates/wasmtime/src/runtime/externals/table.rs
index da9cfd952..e7397750e 100644
--- a/crates/wasmtime/src/runtime/externals/table.rs
+++ b/crates/wasmtime/src/runtime/externals/table.rs
@@ -1,12 +1,12 @@
 use std::ptr::NonNull;
 
+use crate::runtime::vm::{self as runtime};
 use crate::store::{AutoAssertNoGc, StoreData, StoreOpaque, Stored};
 use crate::trampoline::generate_table_export;
 use crate::{AnyRef, AsContext, AsContextMut, ExternRef, Func, HeapType, Ref, TableType};
 use anyhow::{anyhow, bail, Context, Result};
 use runtime::{GcRootsList, SendSyncPtr};
 use wasmtime_environ::TypeTrace;
-use wasmtime_runtime::{self as runtime};
 
 /// A WebAssembly `table`, or an array of values.
 ///
@@ -23,7 +23,7 @@ use wasmtime_runtime::{self as runtime};
 /// methods will panic.
 #[derive(Copy, Clone, Debug)]
 #[repr(transparent)] // here for the C API
-pub struct Table(pub(super) Stored<wasmtime_runtime::ExportTable>);
+pub struct Table(pub(super) Stored<crate::runtime::vm::ExportTable>);
 
 impl Table {
     /// Creates a new [`Table`] with the given parameters.
@@ -138,7 +138,7 @@ impl Table {
     ) -> *mut runtime::Table {
         unsafe {
             let export = &store[self.0];
-            wasmtime_runtime::Instance::from_vmctx(export.vmctx, |handle| {
+            crate::runtime::vm::Instance::from_vmctx(export.vmctx, |handle| {
                 let idx = handle.table_index(&*export.definition);
                 handle.get_defined_table_with_lazy_init(idx, lazy_init_range)
             })
@@ -388,7 +388,7 @@ impl Table {
     }
 
     pub(crate) unsafe fn from_wasmtime_table(
-        mut wasmtime_export: wasmtime_runtime::ExportTable,
+        mut wasmtime_export: crate::runtime::vm::ExportTable,
         store: &mut StoreOpaque,
     ) -> Table {
         // Ensure that the table's type is engine-level canonicalized.
@@ -397,7 +397,7 @@ impl Table {
             .table
             .wasm_ty
             .canonicalize_for_runtime_usage(&mut |module_index| {
-                wasmtime_runtime::Instance::from_vmctx(wasmtime_export.vmctx, |instance| {
+                crate::runtime::vm::Instance::from_vmctx(wasmtime_export.vmctx, |instance| {
                     instance.engine_type_index(module_index)
                 })
             });
@@ -409,9 +409,9 @@ impl Table {
         &data[self.0].table.table
     }
 
-    pub(crate) fn vmimport(&self, store: &StoreOpaque) -> wasmtime_runtime::VMTableImport {
+    pub(crate) fn vmimport(&self, store: &StoreOpaque) -> crate::runtime::vm::VMTableImport {
         let export = &store[self.0];
-        wasmtime_runtime::VMTableImport {
+        crate::runtime::vm::VMTableImport {
             from: export.definition,
             vmctx: export.vmctx,
         }
diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs
index c0d5de6b1..c0c70bf08 100644
--- a/crates/wasmtime/src/runtime/func.rs
+++ b/crates/wasmtime/src/runtime/func.rs
@@ -1,3 +1,7 @@
+use crate::runtime::vm::{
+    ExportFunction, SendSyncPtr, StoreBox, VMArrayCallHostFuncContext, VMContext, VMFuncRef,
+    VMFunctionImport, VMNativeCallHostFuncContext, VMOpaqueContext,
+};
 use crate::runtime::Uninhabited;
 use crate::store::{AutoAssertNoGc, StoreData, StoreOpaque, Stored};
 use crate::type_registry::RegisteredType;
@@ -14,10 +18,6 @@ use std::pin::Pin;
 use std::ptr::{self, NonNull};
 use std::sync::Arc;
 use wasmtime_environ::VMSharedTypeIndex;
-use wasmtime_runtime::{
-    ExportFunction, SendSyncPtr, StoreBox, VMArrayCallHostFuncContext, VMContext, VMFuncRef,
-    VMFunctionImport, VMNativeCallHostFuncContext, VMOpaqueContext,
-};
 
 /// A reference to the abstract `nofunc` heap value.
 ///
@@ -1568,7 +1568,7 @@ pub(crate) fn invoke_wasm_and_catch_traps<T>(
             exit_wasm(store, exit);
             return Err(trap);
         }
-        let result = wasmtime_runtime::catch_traps(
+        let result = crate::runtime::vm::catch_traps(
             store.0.signal_handler(),
             store.0.engine().config().wasm_backtrace,
             store.0.engine().config().coredump_on_trap,
@@ -1616,7 +1616,7 @@ fn enter_wasm<T>(store: &mut StoreContextMut<'_, T>) -> Option<usize> {
         return None;
     }
 
-    let stack_pointer = wasmtime_runtime::get_stack_pointer();
+    let stack_pointer = crate::runtime::vm::get_stack_pointer();
 
     // Determine the stack pointer where, after which, any wasm code will
     // immediately trap. This is checked on the entry to all wasm functions.
@@ -1984,7 +1984,7 @@ pub trait IntoFunc<T, Params, Results>: Send + Sync + 'static {
 /// recommended to use this type.
 pub struct Caller<'a, T> {
     pub(crate) store: StoreContextMut<'a, T>,
-    caller: &'a wasmtime_runtime::Instance,
+    caller: &'a crate::runtime::vm::Instance,
 }
 
 impl<T> Caller<'_, T> {
@@ -1997,7 +1997,7 @@ impl<T> Caller<'_, T> {
         R: 'static,
     {
         assert!(!caller.is_null());
-        wasmtime_runtime::Instance::from_vmctx(caller, |instance| {
+        crate::runtime::vm::Instance::from_vmctx(caller, |instance| {
             let store = StoreContextMut::from_raw(instance.store());
             let gc_lifo_scope = store.0.gc_roots().enter_lifo_scope();
 
@@ -2240,7 +2240,7 @@ macro_rules! impl_into_func {
 
                     // With nothing else on the stack move `run` into this
                     // closure and then run it as part of `Caller::with`.
-                    let result = wasmtime_runtime::catch_unwind_and_longjmp(move || {
+                    let result = crate::runtime::vm::catch_unwind_and_longjmp(move || {
                         let caller_vmctx = VMContext::from_opaque(caller_vmctx);
                         Caller::with(caller_vmctx, run)
                     });
@@ -2539,9 +2539,8 @@ use self::rooted::*;
 /// `RootedHostFunc` instead of accidentally safely allowing access to its
 /// constructor.
 mod rooted {
-    use wasmtime_runtime::{SendSyncPtr, VMFuncRef};
-
     use super::HostFunc;
+    use crate::runtime::vm::{SendSyncPtr, VMFuncRef};
     use std::ptr::NonNull;
     use std::sync::Arc;
 
diff --git a/crates/wasmtime/src/runtime/func/typed.rs b/crates/wasmtime/src/runtime/func/typed.rs
index 9c4912c05..faacb3a15 100644
--- a/crates/wasmtime/src/runtime/func/typed.rs
+++ b/crates/wasmtime/src/runtime/func/typed.rs
@@ -1,4 +1,5 @@
 use super::{invoke_wasm_and_catch_traps, HostAbi};
+use crate::runtime::vm::{VMContext, VMFuncRef, VMNativeCallFunction, VMOpaqueContext};
 use crate::store::{AutoAssertNoGc, StoreOpaque};
 use crate::{
     AsContext, AsContextMut, Engine, Func, FuncType, HeapType, NoFunc, RefType, StoreContextMut,
@@ -11,7 +12,6 @@ use std::num::NonZeroUsize;
 use std::os::raw::c_void;
 use std::ptr::{self, NonNull};
 use wasmtime_environ::VMSharedTypeIndex;
-use wasmtime_runtime::{VMContext, VMFuncRef, VMNativeCallFunction, VMOpaqueContext};
 
 /// A statically typed WebAssembly function.
 ///
@@ -571,7 +571,7 @@ unsafe impl WasmTy for Option<NoFunc> {
 }
 
 unsafe impl WasmTy for Func {
-    type Abi = NonNull<wasmtime_runtime::VMFuncRef>;
+    type Abi = NonNull<crate::runtime::vm::VMFuncRef>;
 
     #[inline]
     fn valtype() -> ValType {
@@ -604,7 +604,7 @@ unsafe impl WasmTy for Func {
     unsafe fn abi_from_raw(raw: *mut ValRaw) -> Self::Abi {
         let p = (*raw).get_funcref();
         debug_assert!(!p.is_null());
-        NonNull::new_unchecked(p.cast::<wasmtime_runtime::VMFuncRef>())
+        NonNull::new_unchecked(p.cast::<crate::runtime::vm::VMFuncRef>())
     }
 
     #[inline]
@@ -624,7 +624,7 @@ unsafe impl WasmTy for Func {
 }
 
 unsafe impl WasmTy for Option<Func> {
-    type Abi = *mut wasmtime_runtime::VMFuncRef;
+    type Abi = *mut crate::runtime::vm::VMFuncRef;
 
     #[inline]
     fn valtype() -> ValType {
diff --git a/crates/wasmtime/src/runtime/gc/disabled/anyref.rs b/crates/wasmtime/src/runtime/gc/disabled/anyref.rs
index 0663d7e06..c5ceff13f 100644
--- a/crates/wasmtime/src/runtime/gc/disabled/anyref.rs
+++ b/crates/wasmtime/src/runtime/gc/disabled/anyref.rs
@@ -1,8 +1,8 @@
+use crate::runtime::vm::VMGcRef;
 use crate::{
     store::{AutoAssertNoGc, StoreOpaque},
     AsContext, AsContextMut, GcRefImpl, Result, Rooted, I31,
 };
-use wasmtime_runtime::VMGcRef;
 
 /// Support for `anyref` disabled at compile time because the `gc` cargo feature
 /// was not enabled.
diff --git a/crates/wasmtime/src/runtime/gc/disabled/externref.rs b/crates/wasmtime/src/runtime/gc/disabled/externref.rs
index 2ac05e871..5f7ccf66f 100644
--- a/crates/wasmtime/src/runtime/gc/disabled/externref.rs
+++ b/crates/wasmtime/src/runtime/gc/disabled/externref.rs
@@ -1,8 +1,8 @@
+use crate::runtime::vm::VMGcRef;
 use crate::{
     store::AutoAssertNoGc, AsContextMut, GcRefImpl, Result, Rooted, StoreContext, StoreContextMut,
 };
 use std::any::Any;
-use wasmtime_runtime::VMGcRef;
 
 /// Support for `externref` disabled at compile time because the `gc` cargo
 /// feature was not enabled.
diff --git a/crates/wasmtime/src/runtime/gc/disabled/rooting.rs b/crates/wasmtime/src/runtime/gc/disabled/rooting.rs
index 447508cda..b2f3b8ecc 100644
--- a/crates/wasmtime/src/runtime/gc/disabled/rooting.rs
+++ b/crates/wasmtime/src/runtime/gc/disabled/rooting.rs
@@ -1,3 +1,4 @@
+use crate::runtime::vm::{GcStore, VMExternRef, VMGcRef};
 use crate::{
     runtime::Uninhabited,
     store::{AutoAssertNoGc, StoreOpaque},
@@ -8,7 +9,6 @@ use std::ffi::c_void;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::ops::Deref;
-use wasmtime_runtime::{GcStore, VMExternRef, VMGcRef};
 
 mod sealed {
     use super::*;
diff --git a/crates/wasmtime/src/runtime/gc/enabled/anyref.rs b/crates/wasmtime/src/runtime/gc/enabled/anyref.rs
index 71c57ae61..e430c489b 100644
--- a/crates/wasmtime/src/runtime/gc/enabled/anyref.rs
+++ b/crates/wasmtime/src/runtime/gc/enabled/anyref.rs
@@ -1,12 +1,12 @@
 //! Implementation of `anyref` in Wasmtime.
 
+use crate::runtime::vm::VMGcRef;
 use crate::{
     store::{AutoAssertNoGc, StoreOpaque},
     AsContext, AsContextMut, GcRefImpl, GcRootIndex, HeapType, ManuallyRooted, RefType, Result,
     RootSet, Rooted, ValRaw, ValType, WasmTy, I31,
 };
 use std::num::NonZeroU64;
-use wasmtime_runtime::VMGcRef;
 
 /// An `anyref` GC reference.
 ///
diff --git a/crates/wasmtime/src/runtime/gc/enabled/externref.rs b/crates/wasmtime/src/runtime/gc/enabled/externref.rs
index 1fd024475..9f72af608 100644
--- a/crates/wasmtime/src/runtime/gc/enabled/externref.rs
+++ b/crates/wasmtime/src/runtime/gc/enabled/externref.rs
@@ -1,5 +1,6 @@
 //! Implementation of `externref` in Wasmtime.
 
+use crate::runtime::vm::VMGcRef;
 use crate::{
     store::{AutoAssertNoGc, StoreOpaque},
     AsContextMut, GcHeapOutOfMemory, GcRefImpl, GcRootIndex, HeapType, ManuallyRooted, RefType,
@@ -8,7 +9,6 @@ use crate::{
 use anyhow::Context;
 use std::any::Any;
 use std::num::NonZeroU64;
-use wasmtime_runtime::VMGcRef;
 
 /// An opaque, GC-managed reference to some host data that can be passed to
 /// WebAssembly.
diff --git a/crates/wasmtime/src/runtime/gc/enabled/i31.rs b/crates/wasmtime/src/runtime/gc/enabled/i31.rs
index e67e9d1ee..837430c87 100644
--- a/crates/wasmtime/src/runtime/gc/enabled/i31.rs
+++ b/crates/wasmtime/src/runtime/gc/enabled/i31.rs
@@ -4,11 +4,11 @@
 //! in order to get doc comments with example code that shows the use of `I31`
 //! with typed functions and such, we need to wrap it in a newtype.
 
+use crate::runtime::vm::{VMGcRef, ValRaw};
 use crate::{
     store::{AutoAssertNoGc, StoreOpaque},
     HeapType, RefType, Result, ValType, WasmTy,
 };
-use wasmtime_runtime::{VMGcRef, ValRaw};
 
 /// A 31-bit integer.
 ///
@@ -74,7 +74,7 @@ use wasmtime_runtime::{VMGcRef, ValRaw};
 /// # }
 /// ```
 #[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
-pub struct I31(wasmtime_runtime::I31);
+pub struct I31(crate::runtime::vm::I31);
 
 impl std::fmt::Debug for I31 {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -85,14 +85,14 @@ impl std::fmt::Debug for I31 {
     }
 }
 
-impl From<wasmtime_runtime::I31> for I31 {
+impl From<crate::runtime::vm::I31> for I31 {
     #[inline]
-    fn from(value: wasmtime_runtime::I31) -> Self {
+    fn from(value: crate::runtime::vm::I31) -> Self {
         Self(value)
     }
 }
 
-impl From<I31> for wasmtime_runtime::I31 {
+impl From<I31> for crate::runtime::vm::I31 {
     #[inline]
     fn from(value: I31) -> Self {
         value.0
@@ -100,8 +100,8 @@ impl From<I31> for wasmtime_runtime::I31 {
 }
 
 impl I31 {
-    /// Get this `wasmtime::I31`'s internal `wasmtime_runtime::I31`.
-    pub(crate) fn runtime_i31(self) -> wasmtime_runtime::I31 {
+    /// Get this `wasmtime::I31`'s internal `crate::runtime::vm::I31`.
+    pub(crate) fn runtime_i31(self) -> crate::runtime::vm::I31 {
         self.0
     }
 
@@ -122,7 +122,7 @@ impl I31 {
     /// ```
     #[inline]
     pub fn new_u32(value: u32) -> Option<Self> {
-        wasmtime_runtime::I31::new_u32(value).map(Self)
+        crate::runtime::vm::I31::new_u32(value).map(Self)
     }
 
     /// Construct a new `I31` from the given signed value.
@@ -142,7 +142,7 @@ impl I31 {
     /// ```
     #[inline]
     pub fn new_i32(value: i32) -> Option<Self> {
-        wasmtime_runtime::I31::new_i32(value).map(Self)
+        crate::runtime::vm::I31::new_i32(value).map(Self)
     }
 
     /// Construct a new `I31` from the given unsigned value.
@@ -164,7 +164,7 @@ impl I31 {
     /// ```
     #[inline]
     pub fn wrapping_u32(value: u32) -> Self {
-        Self(wasmtime_runtime::I31::wrapping_u32(value))
+        Self(crate::runtime::vm::I31::wrapping_u32(value))
     }
 
     /// Construct a new `I31` from the given signed value.
@@ -186,7 +186,7 @@ impl I31 {
     /// ```
     #[inline]
     pub fn wrapping_i32(value: i32) -> Self {
-        Self(wasmtime_runtime::I31::wrapping_i32(value))
+        Self(crate::runtime::vm::I31::wrapping_i32(value))
     }
 
     /// Get this `I31`'s value as an unsigned integer.
diff --git a/crates/wasmtime/src/runtime/gc/enabled/rooting.rs b/crates/wasmtime/src/runtime/gc/enabled/rooting.rs
index 2a120a6e5..deac3b672 100644
--- a/crates/wasmtime/src/runtime/gc/enabled/rooting.rs
+++ b/crates/wasmtime/src/runtime/gc/enabled/rooting.rs
@@ -102,6 +102,7 @@
 //! can. However, if you really must, consider also using an `AutoAssertNoGc`
 //! across the block of code that is manipulating raw GC references.
 
+use crate::runtime::vm::{GcRootsList, GcStore, VMGcRef};
 use crate::{
     store::{AutoAssertNoGc, StoreId, StoreOpaque},
     AsContext, AsContextMut, GcRef, Result, RootedGcRef,
@@ -113,7 +114,6 @@ use std::{
     hash::Hash,
     ops::{Deref, DerefMut},
 };
-use wasmtime_runtime::{GcRootsList, GcStore, VMGcRef};
 use wasmtime_slab::{Id as SlabId, Slab};
 
 mod sealed {
diff --git a/crates/wasmtime/src/runtime/instance.rs b/crates/wasmtime/src/runtime/instance.rs
index c018d864d..80db9340a 100644
--- a/crates/wasmtime/src/runtime/instance.rs
+++ b/crates/wasmtime/src/runtime/instance.rs
@@ -1,4 +1,8 @@
 use crate::linker::{Definition, DefinitionType};
+use crate::runtime::vm::{
+    Imports, InstanceAllocationRequest, StorePtr, VMContext, VMFuncRef, VMFunctionImport,
+    VMGlobalImport, VMMemoryImport, VMNativeCallFunction, VMOpaqueContext, VMTableImport,
+};
 use crate::store::{InstanceId, StoreOpaque, Stored};
 use crate::types::matching;
 use crate::{
@@ -13,10 +17,6 @@ use wasmparser::WasmFeatures;
 use wasmtime_environ::{
     EntityIndex, EntityType, FuncIndex, GlobalIndex, MemoryIndex, PrimaryMap, TableIndex, TypeTrace,
 };
-use wasmtime_runtime::{
-    Imports, InstanceAllocationRequest, StorePtr, VMContext, VMFuncRef, VMFunctionImport,
-    VMGlobalImport, VMMemoryImport, VMNativeCallFunction, VMOpaqueContext, VMTableImport,
-};
 
 /// An instantiated WebAssembly module.
 ///
@@ -703,9 +703,9 @@ impl OwnedImports {
     /// Note that this is unsafe as the validity of `item` is not verified and
     /// it contains a bunch of raw pointers.
     #[cfg(feature = "component-model")]
-    pub(crate) unsafe fn push_export(&mut self, item: &wasmtime_runtime::Export) {
+    pub(crate) unsafe fn push_export(&mut self, item: &crate::runtime::vm::Export) {
         match item {
-            wasmtime_runtime::Export::Function(f) => {
+            crate::runtime::vm::Export::Function(f) => {
                 let f = f.func_ref.as_ref();
                 self.functions.push(VMFunctionImport {
                     wasm_call: f.wasm_call.unwrap(),
@@ -714,16 +714,16 @@ impl OwnedImports {
                     vmctx: f.vmctx,
                 });
             }
-            wasmtime_runtime::Export::Global(g) => {
+            crate::runtime::vm::Export::Global(g) => {
                 self.globals.push(VMGlobalImport { from: g.definition });
             }
-            wasmtime_runtime::Export::Table(t) => {
+            crate::runtime::vm::Export::Table(t) => {
                 self.tables.push(VMTableImport {
                     from: t.definition,
                     vmctx: t.vmctx,
                 });
             }
-            wasmtime_runtime::Export::Memory(m) => {
+            crate::runtime::vm::Export::Memory(m) => {
                 self.memories.push(VMMemoryImport {
                     from: m.definition,
                     vmctx: m.vmctx,
diff --git a/crates/wasmtime/src/runtime/instantiate.rs b/crates/wasmtime/src/runtime/instantiate.rs
index c09b96d6b..d37b6c1a0 100644
--- a/crates/wasmtime/src/runtime/instantiate.rs
+++ b/crates/wasmtime/src/runtime/instantiate.rs
@@ -3,6 +3,7 @@
 //! `CompiledModule` to allow compiling and instantiating to be done as separate
 //! steps.
 
+use crate::runtime::vm::{CompiledModuleId, CompiledModuleIdAllocator, MmapVec};
 use crate::{code_memory::CodeMemory, profiling_agent::ProfilingAgent};
 use anyhow::Result;
 use std::str;
@@ -12,7 +13,6 @@ use wasmtime_environ::{
     FunctionName, Metadata, Module, ModuleInternedTypeIndex, PrimaryMap, StackMapInformation,
     WasmFunctionInfo,
 };
-use wasmtime_runtime::{CompiledModuleId, CompiledModuleIdAllocator, MmapVec};
 
 /// A compiled wasm module, ready to be instantiated.
 pub struct CompiledModule {
@@ -22,7 +22,7 @@ pub struct CompiledModule {
     meta: Metadata,
     code_memory: Arc<CodeMemory>,
     #[cfg(feature = "debug-builtins")]
-    dbg_jit_registration: Option<wasmtime_runtime::GdbJitImageRegistration>,
+    dbg_jit_registration: Option<crate::runtime::vm::GdbJitImageRegistration>,
     /// A unique ID used to register this module with the engine.
     unique_id: CompiledModuleId,
     func_names: Vec<FunctionName>,
@@ -78,7 +78,7 @@ impl CompiledModule {
                 (text.as_ptr(), text.len()),
             )
             .context("failed to create jit image for gdb")?;
-            let reg = wasmtime_runtime::GdbJitImageRegistration::register(bytes);
+            let reg = crate::runtime::vm::GdbJitImageRegistration::register(bytes);
             self.dbg_jit_registration = Some(reg);
         }
         profiler.register_module(&self.code_memory.mmap()[..], &|addr| {
diff --git a/crates/wasmtime/src/runtime/memory.rs b/crates/wasmtime/src/runtime/memory.rs
index 1bb48bcc7..4962ffc96 100644
--- a/crates/wasmtime/src/runtime/memory.rs
+++ b/crates/wasmtime/src/runtime/memory.rs
@@ -1,3 +1,4 @@
+use crate::runtime::vm::{RuntimeLinearMemory, VMMemoryImport};
 use crate::store::{StoreData, StoreOpaque, Stored};
 use crate::trampoline::generate_memory_export;
 use crate::Trap;
@@ -8,9 +9,8 @@ use std::ops::Range;
 use std::slice;
 use std::time::Instant;
 use wasmtime_environ::MemoryPlan;
-use wasmtime_runtime::{RuntimeLinearMemory, VMMemoryImport};
 
-pub use wasmtime_runtime::WaitResult;
+pub use crate::runtime::vm::WaitResult;
 
 /// Error for out of bounds [`Memory`] access.
 #[derive(Debug)]
@@ -201,7 +201,7 @@ impl std::error::Error for MemoryAccessError {}
 /// be provided.
 #[derive(Copy, Clone, Debug)]
 #[repr(transparent)] // here for the C API
-pub struct Memory(Stored<wasmtime_runtime::ExportMemory>);
+pub struct Memory(Stored<crate::runtime::vm::ExportMemory>);
 
 impl Memory {
     /// Creates a new WebAssembly memory given the configuration of `ty`.
@@ -544,17 +544,17 @@ impl Memory {
         store.on_fiber(|store| self.grow(store, delta)).await?
     }
 
-    fn wasmtime_memory(&self, store: &mut StoreOpaque) -> *mut wasmtime_runtime::Memory {
+    fn wasmtime_memory(&self, store: &mut StoreOpaque) -> *mut crate::runtime::vm::Memory {
         unsafe {
             let export = &store[self.0];
-            wasmtime_runtime::Instance::from_vmctx(export.vmctx, |handle| {
+            crate::runtime::vm::Instance::from_vmctx(export.vmctx, |handle| {
                 handle.get_defined_memory(export.index)
             })
         }
     }
 
     pub(crate) unsafe fn from_wasmtime_memory(
-        wasmtime_export: wasmtime_runtime::ExportMemory,
+        wasmtime_export: crate::runtime::vm::ExportMemory,
         store: &mut StoreOpaque,
     ) -> Memory {
         Memory(store.store_data_mut().insert(wasmtime_export))
@@ -564,9 +564,9 @@ impl Memory {
         &store[self.0].memory.memory
     }
 
-    pub(crate) fn vmimport(&self, store: &StoreOpaque) -> wasmtime_runtime::VMMemoryImport {
+    pub(crate) fn vmimport(&self, store: &StoreOpaque) -> crate::runtime::vm::VMMemoryImport {
         let export = &store[self.0];
-        wasmtime_runtime::VMMemoryImport {
+        crate::runtime::vm::VMMemoryImport {
             from: export.definition,
             vmctx: export.vmctx,
             index: export.index,
@@ -719,7 +719,7 @@ pub unsafe trait MemoryCreator: Send + Sync {
 /// # }
 /// ```
 #[derive(Clone)]
-pub struct SharedMemory(wasmtime_runtime::SharedMemory, Engine);
+pub struct SharedMemory(crate::runtime::vm::SharedMemory, Engine);
 
 impl SharedMemory {
     /// Construct a [`SharedMemory`] by providing both the `minimum` and
@@ -735,7 +735,7 @@ impl SharedMemory {
 
         let tunables = engine.tunables();
         let plan = MemoryPlan::for_memory(ty.wasmtime_memory().clone(), tunables);
-        let memory = wasmtime_runtime::SharedMemory::new(plan)?;
+        let memory = crate::runtime::vm::SharedMemory::new(plan)?;
         Ok(Self(memory, engine.clone()))
     }
 
@@ -902,7 +902,7 @@ impl SharedMemory {
 
     /// Construct a single-memory instance to provide a way to import
     /// [`SharedMemory`] into other modules.
-    pub(crate) fn vmimport(&self, store: &mut StoreOpaque) -> wasmtime_runtime::VMMemoryImport {
+    pub(crate) fn vmimport(&self, store: &mut StoreOpaque) -> crate::runtime::vm::VMMemoryImport {
         let export_memory = generate_memory_export(store, &self.ty(), Some(&self.0)).unwrap();
         VMMemoryImport {
             from: export_memory.definition,
@@ -915,10 +915,10 @@ impl SharedMemory {
     /// function is available to handle the case in which a Wasm module exports
     /// shared memory and the user wants host-side access to it.
     pub(crate) unsafe fn from_wasmtime_memory(
-        wasmtime_export: wasmtime_runtime::ExportMemory,
+        wasmtime_export: crate::runtime::vm::ExportMemory,
         store: &mut StoreOpaque,
     ) -> Self {
-        wasmtime_runtime::Instance::from_vmctx(wasmtime_export.vmctx, |handle| {
+        crate::runtime::vm::Instance::from_vmctx(wasmtime_export.vmctx, |handle| {
             let memory = handle
                 .get_defined_memory(wasmtime_export.index)
                 .as_mut()
diff --git a/crates/wasmtime/src/runtime/module.rs b/crates/wasmtime/src/runtime/module.rs
index 42906a361..22818f5b7 100644
--- a/crates/wasmtime/src/runtime/module.rs
+++ b/crates/wasmtime/src/runtime/module.rs
@@ -1,3 +1,7 @@
+use crate::runtime::vm::{
+    CompiledModuleId, MemoryImage, MmapVec, ModuleMemoryImages, VMArrayCallFunction,
+    VMNativeCallFunction, VMWasmCallFunction,
+};
 use crate::{
     code::CodeObject,
     code_memory::CodeMemory,
@@ -19,10 +23,6 @@ use wasmtime_environ::{
     CompiledModuleInfo, DefinedFuncIndex, DefinedMemoryIndex, EntityIndex, HostPtr, ModuleTypes,
     ObjectKind, VMOffsets, VMSharedTypeIndex,
 };
-use wasmtime_runtime::{
-    CompiledModuleId, MemoryImage, MmapVec, ModuleMemoryImages, VMArrayCallFunction,
-    VMNativeCallFunction, VMWasmCallFunction,
-};
 mod registry;
 
 pub use registry::{
@@ -896,13 +896,13 @@ impl Module {
 
     /// Returns the `ModuleInner` cast as `ModuleRuntimeInfo` for use
     /// by the runtime.
-    pub(crate) fn runtime_info(&self) -> Arc<dyn wasmtime_runtime::ModuleRuntimeInfo> {
+    pub(crate) fn runtime_info(&self) -> Arc<dyn crate::runtime::vm::ModuleRuntimeInfo> {
         // N.B.: this needs to return a clone because we cannot
         // statically cast the &Arc<ModuleInner> to &Arc<dyn Trait...>.
         self.inner.clone()
     }
 
-    pub(crate) fn module_info(&self) -> &dyn wasmtime_runtime::ModuleInfo {
+    pub(crate) fn module_info(&self) -> &dyn crate::runtime::vm::ModuleInfo {
         &*self.inner
     }
 
@@ -1056,7 +1056,7 @@ fn _assert_send_sync() {
     _assert::<Module>();
 }
 
-impl wasmtime_runtime::ModuleRuntimeInfo for ModuleInner {
+impl crate::runtime::vm::ModuleRuntimeInfo for ModuleInner {
     fn module(&self) -> &Arc<wasmtime_environ::Module> {
         self.module.module()
     }
@@ -1135,7 +1135,7 @@ impl wasmtime_runtime::ModuleRuntimeInfo for ModuleInner {
     }
 }
 
-impl wasmtime_runtime::ModuleInfo for ModuleInner {
+impl crate::runtime::vm::ModuleInfo for ModuleInner {
     fn lookup_stack_map(&self, pc: usize) -> Option<&wasmtime_environ::StackMap> {
         let text_offset = pc - self.module.text().as_ptr() as usize;
         let (index, func_offset) = self.module.func_by_text_offset(text_offset)?;
@@ -1187,12 +1187,12 @@ impl BareModuleInfo {
         }
     }
 
-    pub(crate) fn into_traitobj(self) -> Arc<dyn wasmtime_runtime::ModuleRuntimeInfo> {
+    pub(crate) fn into_traitobj(self) -> Arc<dyn crate::runtime::vm::ModuleRuntimeInfo> {
         Arc::new(self)
     }
 }
 
-impl wasmtime_runtime::ModuleRuntimeInfo for BareModuleInfo {
+impl crate::runtime::vm::ModuleRuntimeInfo for BareModuleInfo {
     fn module(&self) -> &Arc<wasmtime_environ::Module> {
         &self.module
     }
diff --git a/crates/wasmtime/src/runtime/module/registry.rs b/crates/wasmtime/src/runtime/module/registry.rs
index 5dab73736..8091c9407 100644
--- a/crates/wasmtime/src/runtime/module/registry.rs
+++ b/crates/wasmtime/src/runtime/module/registry.rs
@@ -3,6 +3,7 @@
 use crate::code::CodeObject;
 #[cfg(feature = "component-model")]
 use crate::component::Component;
+use crate::runtime::vm::VMWasmCallFunction;
 use crate::{code_memory::CodeMemory, FrameInfo, Module, Trap};
 use once_cell::sync::Lazy;
 use std::collections::btree_map::Entry;
@@ -12,7 +13,6 @@ use std::{
     sync::{Arc, RwLock},
 };
 use wasmtime_environ::VMSharedTypeIndex;
-use wasmtime_runtime::VMWasmCallFunction;
 
 /// Used for registering modules with a store.
 ///
@@ -68,7 +68,7 @@ impl ModuleRegistry {
     }
 
     /// Fetches information about a registered module given a program counter value.
-    pub fn lookup_module_info(&self, pc: usize) -> Option<&dyn wasmtime_runtime::ModuleInfo> {
+    pub fn lookup_module_info(&self, pc: usize) -> Option<&dyn crate::runtime::vm::ModuleInfo> {
         let (module, _) = self.module_and_offset(pc)?;
         Some(module.module_info())
     }
diff --git a/crates/wasmtime/src/runtime/profiling.rs b/crates/wasmtime/src/runtime/profiling.rs
index e947ec5d1..d73279910 100644
--- a/crates/wasmtime/src/runtime/profiling.rs
+++ b/crates/wasmtime/src/runtime/profiling.rs
@@ -1,3 +1,4 @@
+use crate::runtime::vm::Backtrace;
 use crate::{instantiate::CompiledModule, AsContext, Module};
 #[allow(unused_imports)]
 use anyhow::bail;
@@ -11,7 +12,6 @@ use std::ops::Range;
 use std::sync::Arc;
 use std::time::{Duration, Instant};
 use wasmtime_environ::demangle_function_name_or_index;
-use wasmtime_runtime::Backtrace;
 
 // TODO: collect more data
 // - Provide additional hooks for recording host-guest transitions, to be
diff --git a/crates/wasmtime/src/runtime/signatures.rs b/crates/wasmtime/src/runtime/signatures.rs
index 6ce6b0150..11374a7ab 100644
--- a/crates/wasmtime/src/runtime/signatures.rs
+++ b/crates/wasmtime/src/runtime/signatures.rs
@@ -1,13 +1,13 @@
 //! Implement a registry of function signatures, for fast indirect call
 //! signature checking.
 
+use crate::runtime::vm::VMSharedSignatureIndex;
 use std::{
     collections::{hash_map::Entry, HashMap},
     sync::RwLock,
 };
 use std::{convert::TryFrom, sync::Arc};
 use wasmtime_environ::{ModuleTypes, PrimaryMap, SignatureIndex, WasmFuncType};
-use wasmtime_runtime::VMSharedSignatureIndex;
 
 /// Represents a collection of shared signatures.
 ///
diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs
index bd105a1cb..45e06e6c4 100644
--- a/crates/wasmtime/src/runtime/store.rs
+++ b/crates/wasmtime/src/runtime/store.rs
@@ -79,6 +79,12 @@
 use crate::instance::InstanceData;
 use crate::linker::Definition;
 use crate::module::{BareModuleInfo, RegisteredModuleId};
+use crate::runtime::vm::mpk::{self, ProtectionKey, ProtectionMask};
+use crate::runtime::vm::{
+    Backtrace, ExportGlobal, GcHeapAllocationIndex, GcRootsList, GcStore,
+    InstanceAllocationRequest, InstanceAllocator, InstanceHandle, OnDemandInstanceAllocator,
+    SignalHandler, StoreBox, StorePtr, VMContext, VMFuncRef, VMGcRef, VMRuntimeLimits, WasmFault,
+};
 use crate::trampoline::VMHostGlobalContext;
 use crate::RootSet;
 use crate::{module::ModuleRegistry, Engine, Module, Trap, Val, ValRaw};
@@ -97,12 +103,6 @@ use std::ptr;
 use std::sync::atomic::AtomicU64;
 use std::sync::Arc;
 use std::task::{Context, Poll};
-use wasmtime_runtime::mpk::{self, ProtectionKey, ProtectionMask};
-use wasmtime_runtime::{
-    Backtrace, ExportGlobal, GcHeapAllocationIndex, GcRootsList, GcStore,
-    InstanceAllocationRequest, InstanceAllocator, InstanceHandle, OnDemandInstanceAllocator,
-    SignalHandler, StoreBox, StorePtr, VMContext, VMFuncRef, VMGcRef, VMRuntimeLimits, WasmFault,
-};
 
 mod context;
 pub use self::context::*;
@@ -373,9 +373,9 @@ pub struct StoreOpaque {
     /// and calls. These also interact with the `ResourceAny` type and its
     /// internal representation.
     #[cfg(feature = "component-model")]
-    component_host_table: wasmtime_runtime::component::ResourceTable,
+    component_host_table: crate::runtime::vm::component::ResourceTable,
     #[cfg(feature = "component-model")]
-    component_calls: wasmtime_runtime::component::CallContexts,
+    component_calls: crate::runtime::vm::component::CallContexts,
     #[cfg(feature = "component-model")]
     host_resource_data: crate::component::HostResourceData,
 }
@@ -558,8 +558,8 @@ impl<T> Store<T> {
             // throughout Wasmtime.
             unsafe {
                 let traitobj = std::mem::transmute::<
-                    *mut (dyn wasmtime_runtime::Store + '_),
-                    *mut (dyn wasmtime_runtime::Store + 'static),
+                    *mut (dyn crate::runtime::vm::Store + '_),
+                    *mut (dyn crate::runtime::vm::Store + 'static),
                 >(&mut *inner);
                 instance.set_store(traitobj);
             }
@@ -1478,7 +1478,7 @@ impl StoreOpaque {
             } else {
                 (
                     GcHeapAllocationIndex::default(),
-                    wasmtime_runtime::disabled_gc_heap(),
+                    crate::runtime::vm::disabled_gc_heap(),
                 )
             };
             Ok(GcStore::new(index, heap))
@@ -1488,7 +1488,7 @@ impl StoreOpaque {
         fn allocate_gc_store(_engine: &Engine) -> Result<GcStore> {
             Ok(GcStore::new(
                 GcHeapAllocationIndex::default(),
-                wasmtime_runtime::disabled_gc_heap(),
+                crate::runtime::vm::disabled_gc_heap(),
             ))
         }
     }
@@ -1623,7 +1623,7 @@ impl StoreOpaque {
 
     #[cfg(all(feature = "async", feature = "gc"))]
     async fn trace_roots_async(&mut self, gc_roots_list: &mut GcRootsList) {
-        use wasmtime_runtime::Yield;
+        use crate::runtime::vm::Yield;
 
         log::trace!("Begin trace GC roots");
 
@@ -1643,7 +1643,7 @@ impl StoreOpaque {
     fn trace_wasm_stack_roots(&mut self, gc_roots_list: &mut GcRootsList) {
         use std::ptr::NonNull;
 
-        use wasmtime_runtime::{ModuleInfoLookup, SendSyncPtr};
+        use crate::runtime::vm::{ModuleInfoLookup, SendSyncPtr};
 
         log::trace!("Begin trace GC roots :: Wasm stack");
 
@@ -1807,7 +1807,7 @@ impl StoreOpaque {
     /// executing on a fiber. This will yield execution back to the caller once.
     #[cfg(feature = "async")]
     fn async_yield_impl(&mut self) -> Result<()> {
-        use wasmtime_runtime::Yield;
+        use crate::runtime::vm::Yield;
 
         let mut future = Yield::new();
 
@@ -1841,7 +1841,7 @@ impl StoreOpaque {
         self.default_caller.vmctx()
     }
 
-    pub fn traitobj(&self) -> *mut dyn wasmtime_runtime::Store {
+    pub fn traitobj(&self) -> *mut dyn crate::runtime::vm::Store {
         self.default_caller.store()
     }
 
@@ -1971,8 +1971,8 @@ at https://bytecodealliance.org/security.
     pub(crate) fn component_resource_state(
         &mut self,
     ) -> (
-        &mut wasmtime_runtime::component::CallContexts,
-        &mut wasmtime_runtime::component::ResourceTable,
+        &mut crate::runtime::vm::component::CallContexts,
+        &mut crate::runtime::vm::component::ResourceTable,
         &mut crate::component::HostResourceData,
     ) {
         (
@@ -2052,7 +2052,7 @@ impl<T> StoreContextMut<'_, T> {
                 fiber,
                 current_poll_cx,
                 engine,
-                state: Some(wasmtime_runtime::AsyncWasmCallState::new()),
+                state: Some(crate::runtime::vm::AsyncWasmCallState::new()),
             }
         };
         future.await?;
@@ -2064,7 +2064,7 @@ impl<T> StoreContextMut<'_, T> {
             current_poll_cx: *mut *mut Context<'static>,
             engine: Engine,
             // See comments in `FiberFuture::resume` for this
-            state: Option<wasmtime_runtime::AsyncWasmCallState>,
+            state: Option<crate::runtime::vm::AsyncWasmCallState>,
         }
 
         // This is surely the most dangerous `unsafe impl Send` in the entire
@@ -2161,7 +2161,7 @@ impl<T> StoreContextMut<'_, T> {
 
                 struct Restore<'a, 'b> {
                     fiber: &'a mut FiberFuture<'b>,
-                    state: Option<wasmtime_runtime::PreviousAsyncWasmCallState>,
+                    state: Option<crate::runtime::vm::PreviousAsyncWasmCallState>,
                 }
 
                 impl Drop for Restore<'_, '_> {
@@ -2224,7 +2224,7 @@ impl<T> StoreContextMut<'_, T> {
                         // Wasmtime is incorrect.
                         Err(()) => {
                             if let Some(range) = self.fiber.stack().range() {
-                                wasmtime_runtime::AsyncWasmCallState::assert_current_state_not_in_range(range);
+                                crate::runtime::vm::AsyncWasmCallState::assert_current_state_not_in_range(range);
                             }
                             Poll::Pending
                         }
@@ -2355,7 +2355,7 @@ impl AsyncCx {
     }
 }
 
-unsafe impl<T> wasmtime_runtime::Store for StoreInner<T> {
+unsafe impl<T> crate::runtime::vm::Store for StoreInner<T> {
     fn vmruntime_limits(&self) -> *mut VMRuntimeLimits {
         <StoreOpaque>::vmruntime_limits(self)
     }
@@ -2547,7 +2547,7 @@ unsafe impl<T> wasmtime_runtime::Store for StoreInner<T> {
     }
 
     #[cfg(feature = "component-model")]
-    fn component_calls(&mut self) -> &mut wasmtime_runtime::component::CallContexts {
+    fn component_calls(&mut self) -> &mut crate::runtime::vm::component::CallContexts {
         &mut self.component_calls
     }
 }
@@ -2663,8 +2663,8 @@ impl Drop for StoreOpaque {
     }
 }
 
-impl wasmtime_runtime::ModuleInfoLookup for ModuleRegistry {
-    fn lookup(&self, pc: usize) -> Option<&dyn wasmtime_runtime::ModuleInfo> {
+impl crate::runtime::vm::ModuleInfoLookup for ModuleRegistry {
+    fn lookup(&self, pc: usize) -> Option<&dyn crate::runtime::vm::ModuleInfo> {
         self.lookup_module_info(pc)
     }
 }
diff --git a/crates/wasmtime/src/runtime/store/context.rs b/crates/wasmtime/src/runtime/store/context.rs
index 2e65c0c33..98211da55 100644
--- a/crates/wasmtime/src/runtime/store/context.rs
+++ b/crates/wasmtime/src/runtime/store/context.rs
@@ -32,7 +32,7 @@ impl<'a, T> StoreContextMut<'a, T> {
     /// Unfortunately there's not a ton of debug asserts we can add here, so we
     /// rely on testing to largely help show that this is correctly used.
     pub(crate) unsafe fn from_raw(
-        store: *mut dyn wasmtime_runtime::Store,
+        store: *mut dyn crate::runtime::vm::Store,
     ) -> StoreContextMut<'a, T> {
         StoreContextMut(&mut *(store as *mut StoreInner<T>))
     }
diff --git a/crates/wasmtime/src/runtime/store/data.rs b/crates/wasmtime/src/runtime/store/data.rs
index dad8654d0..319dd196a 100644
--- a/crates/wasmtime/src/runtime/store/data.rs
+++ b/crates/wasmtime/src/runtime/store/data.rs
@@ -22,10 +22,10 @@ impl InstanceId {
 pub struct StoreData {
     id: StoreId,
     funcs: Vec<crate::func::FuncData>,
-    tables: Vec<wasmtime_runtime::ExportTable>,
-    globals: Vec<wasmtime_runtime::ExportGlobal>,
+    tables: Vec<crate::runtime::vm::ExportTable>,
+    globals: Vec<crate::runtime::vm::ExportGlobal>,
     instances: Vec<crate::instance::InstanceData>,
-    memories: Vec<wasmtime_runtime::ExportMemory>,
+    memories: Vec<crate::runtime::vm::ExportMemory>,
     #[cfg(feature = "component-model")]
     pub(crate) components: crate::component::ComponentStoreData,
 }
@@ -48,10 +48,10 @@ macro_rules! impl_store_data {
 
 impl_store_data! {
     funcs => crate::func::FuncData,
-    tables => wasmtime_runtime::ExportTable,
-    globals => wasmtime_runtime::ExportGlobal,
+    tables => crate::runtime::vm::ExportTable,
+    globals => crate::runtime::vm::ExportGlobal,
     instances => crate::instance::InstanceData,
-    memories => wasmtime_runtime::ExportMemory,
+    memories => crate::runtime::vm::ExportMemory,
 }
 
 impl StoreData {
diff --git a/crates/wasmtime/src/runtime/store/func_refs.rs b/crates/wasmtime/src/runtime/store/func_refs.rs
index b84849cdc..0f5d7eca1 100644
--- a/crates/wasmtime/src/runtime/store/func_refs.rs
+++ b/crates/wasmtime/src/runtime/store/func_refs.rs
@@ -1,6 +1,9 @@
+//! Lifetime management of `VMFuncRef`s inside of stores, and filling in their
+//! trampolines.
+
 use crate::module::ModuleRegistry;
+use crate::runtime::vm::{SendSyncPtr, VMFuncRef, VMNativeCallHostFuncContext};
 use std::{ptr::NonNull, sync::Arc};
-use wasmtime_runtime::{SendSyncPtr, VMFuncRef, VMNativeCallHostFuncContext};
 
 /// An arena of `VMFuncRef`s.
 ///
diff --git a/crates/wasmtime/src/runtime/trampoline.rs b/crates/wasmtime/src/runtime/trampoline.rs
index 87d51da8e..169a3ff5e 100644
--- a/crates/wasmtime/src/runtime/trampoline.rs
+++ b/crates/wasmtime/src/runtime/trampoline.rs
@@ -12,16 +12,16 @@ pub(crate) use memory::MemoryCreatorProxy;
 use self::memory::create_memory;
 use self::table::create_table;
 use crate::module::BareModuleInfo;
+use crate::runtime::vm::{
+    Imports, InstanceAllocationRequest, InstanceAllocator, OnDemandInstanceAllocator, SharedMemory,
+    StorePtr, VMFunctionImport,
+};
 use crate::store::{InstanceId, StoreOpaque};
 use crate::{MemoryType, TableType};
 use anyhow::Result;
 use std::any::Any;
 use std::sync::Arc;
 use wasmtime_environ::{MemoryIndex, Module, TableIndex, VMSharedTypeIndex};
-use wasmtime_runtime::{
-    Imports, InstanceAllocationRequest, InstanceAllocator, OnDemandInstanceAllocator, SharedMemory,
-    StorePtr, VMFunctionImport,
-};
 
 fn create_handle(
     module: Module,
@@ -59,7 +59,7 @@ pub fn generate_memory_export(
     store: &mut StoreOpaque,
     m: &MemoryType,
     preallocation: Option<&SharedMemory>,
-) -> Result<wasmtime_runtime::ExportMemory> {
+) -> Result<crate::runtime::vm::ExportMemory> {
     let instance = create_memory(store, m, preallocation)?;
     Ok(store
         .instance_mut(instance)
@@ -69,7 +69,7 @@ pub fn generate_memory_export(
 pub fn generate_table_export(
     store: &mut StoreOpaque,
     t: &TableType,
-) -> Result<wasmtime_runtime::ExportTable> {
+) -> Result<crate::runtime::vm::ExportTable> {
     let instance = create_table(store, t)?;
     Ok(store
         .instance_mut(instance)
diff --git a/crates/wasmtime/src/runtime/trampoline/func.rs b/crates/wasmtime/src/runtime/trampoline/func.rs
index cfb0bb7ff..e197e3f4c 100644
--- a/crates/wasmtime/src/runtime/trampoline/func.rs
+++ b/crates/wasmtime/src/runtime/trampoline/func.rs
@@ -1,12 +1,12 @@
 //! Support for a calling of an imported function.
 
+use crate::runtime::vm::{
+    StoreBox, VMArrayCallHostFuncContext, VMContext, VMFuncRef, VMOpaqueContext,
+};
 use crate::type_registry::RegisteredType;
 use crate::{code_memory::CodeMemory, Engine, FuncType, ValRaw};
 use anyhow::Result;
 use std::ptr::NonNull;
-use wasmtime_runtime::{
-    StoreBox, VMArrayCallHostFuncContext, VMContext, VMFuncRef, VMOpaqueContext,
-};
 
 struct TrampolineState<F> {
     func: F,
@@ -46,7 +46,7 @@ unsafe extern "C" fn array_call_shim<F>(
     // below will trigger a longjmp, which won't run local destructors if we
     // have any. To prevent leaks we avoid having any local destructors by
     // avoiding local variables.
-    let result = wasmtime_runtime::catch_unwind_and_longjmp(|| {
+    let result = crate::runtime::vm::catch_unwind_and_longjmp(|| {
         let vmctx = VMArrayCallHostFuncContext::from_opaque(vmctx);
         // Double-check ourselves in debug mode, but we control
         // the `Any` here so an unsafe downcast should also
diff --git a/crates/wasmtime/src/runtime/trampoline/global.rs b/crates/wasmtime/src/runtime/trampoline/global.rs
index c88f4550f..742c53f15 100644
--- a/crates/wasmtime/src/runtime/trampoline/global.rs
+++ b/crates/wasmtime/src/runtime/trampoline/global.rs
@@ -1,7 +1,7 @@
+use crate::runtime::vm::{StoreBox, VMGlobalDefinition};
 use crate::store::{AutoAssertNoGc, StoreOpaque};
 use crate::{GlobalType, Mutability, Result, RootedGcRefImpl, Val};
 use std::ptr;
-use wasmtime_runtime::{StoreBox, VMGlobalDefinition};
 
 #[repr(C)]
 pub struct VMHostGlobalContext {
@@ -13,7 +13,7 @@ pub fn generate_global_export(
     store: &mut StoreOpaque,
     ty: GlobalType,
     val: Val,
-) -> Result<wasmtime_runtime::ExportGlobal> {
+) -> Result<crate::runtime::vm::ExportGlobal> {
     let global = wasmtime_environ::Global {
         wasm_ty: ty.content().to_wasm_type(),
         mutability: match ty.mutability() {
@@ -60,7 +60,7 @@ pub fn generate_global_export(
     };
 
     store.host_globals().push(ctx);
-    Ok(wasmtime_runtime::ExportGlobal {
+    Ok(crate::runtime::vm::ExportGlobal {
         definition,
         vmctx: std::ptr::null_mut(),
         global,
diff --git a/crates/wasmtime/src/runtime/trampoline/memory.rs b/crates/wasmtime/src/runtime/trampoline/memory.rs
index b44e537d1..d3e211956 100644
--- a/crates/wasmtime/src/runtime/trampoline/memory.rs
+++ b/crates/wasmtime/src/runtime/trampoline/memory.rs
@@ -1,5 +1,12 @@
 use crate::memory::{LinearMemory, MemoryCreator};
 use crate::module::BareModuleInfo;
+use crate::runtime::vm::mpk::ProtectionKey;
+use crate::runtime::vm::{
+    CompiledModuleId, GcHeapAllocationIndex, Imports, InstanceAllocationRequest, InstanceAllocator,
+    InstanceAllocatorImpl, Memory, MemoryAllocationIndex, MemoryImage, OnDemandInstanceAllocator,
+    RuntimeLinearMemory, RuntimeMemoryCreator, SharedMemory, StorePtr, Table, TableAllocationIndex,
+    VMMemoryDefinition,
+};
 use crate::store::{InstanceId, StoreOpaque};
 use crate::MemoryType;
 use anyhow::{anyhow, Result};
@@ -9,13 +16,6 @@ use wasmtime_environ::{
     DefinedMemoryIndex, DefinedTableIndex, EntityIndex, HostPtr, MemoryPlan, MemoryStyle, Module,
     VMOffsets, WASM_PAGE_SIZE,
 };
-use wasmtime_runtime::mpk::ProtectionKey;
-use wasmtime_runtime::{
-    CompiledModuleId, GcHeapAllocationIndex, Imports, InstanceAllocationRequest, InstanceAllocator,
-    InstanceAllocatorImpl, Memory, MemoryAllocationIndex, MemoryImage, OnDemandInstanceAllocator,
-    RuntimeLinearMemory, RuntimeMemoryCreator, SharedMemory, StorePtr, Table, TableAllocationIndex,
-    VMMemoryDefinition,
-};
 
 #[cfg(feature = "component-model")]
 use wasmtime_environ::{
@@ -270,8 +270,8 @@ unsafe impl InstanceAllocatorImpl for SingleMemoryInstance<'_> {
     #[cfg(feature = "gc")]
     fn allocate_gc_heap(
         &self,
-        _gc_runtime: &dyn wasmtime_runtime::GcRuntime,
-    ) -> Result<(GcHeapAllocationIndex, Box<dyn wasmtime_runtime::GcHeap>)> {
+        _gc_runtime: &dyn crate::runtime::vm::GcRuntime,
+    ) -> Result<(GcHeapAllocationIndex, Box<dyn crate::runtime::vm::GcHeap>)> {
         unreachable!()
     }
 
@@ -279,7 +279,7 @@ unsafe impl InstanceAllocatorImpl for SingleMemoryInstance<'_> {
     fn deallocate_gc_heap(
         &self,
         _allocation_index: GcHeapAllocationIndex,
-        _gc_heap: Box<dyn wasmtime_runtime::GcHeap>,
+        _gc_heap: Box<dyn crate::runtime::vm::GcHeap>,
     ) {
         unreachable!()
     }
diff --git a/crates/wasmtime/src/runtime/trap.rs b/crates/wasmtime/src/runtime/trap.rs
index 8d5b52188..1871560ff 100644
--- a/crates/wasmtime/src/runtime/trap.rs
+++ b/crates/wasmtime/src/runtime/trap.rs
@@ -70,18 +70,18 @@ use wasmtime_environ::{
 pub use wasmtime_environ::Trap;
 
 // Same safety requirements and caveats as
-// `wasmtime_runtime::raise_user_trap`.
+// `crate::runtime::vm::raise_user_trap`.
 pub(crate) unsafe fn raise(error: anyhow::Error) -> ! {
     let needs_backtrace = error.downcast_ref::<WasmBacktrace>().is_none();
-    wasmtime_runtime::raise_user_trap(error, needs_backtrace)
+    crate::runtime::vm::raise_user_trap(error, needs_backtrace)
 }
 
 #[cold] // traps are exceptional, this helps move handling off the main path
 pub(crate) fn from_runtime_box(
     store: &mut StoreOpaque,
-    runtime_trap: Box<wasmtime_runtime::Trap>,
+    runtime_trap: Box<crate::runtime::vm::Trap>,
 ) -> Error {
-    let wasmtime_runtime::Trap {
+    let crate::runtime::vm::Trap {
         reason,
         backtrace,
         coredumpstack,
@@ -100,7 +100,7 @@ pub(crate) fn from_runtime_box(
         // provide useful information to debug with for the embedder/caller,
         // otherwise the information about what the wasm was doing when the
         // error was generated would be lost.
-        wasmtime_runtime::TrapReason::User {
+        crate::runtime::vm::TrapReason::User {
             error,
             needs_backtrace,
         } => {
@@ -109,7 +109,7 @@ pub(crate) fn from_runtime_box(
             );
             (error, None)
         }
-        wasmtime_runtime::TrapReason::Jit {
+        crate::runtime::vm::TrapReason::Jit {
             pc,
             faulting_addr,
             trap,
@@ -125,7 +125,7 @@ pub(crate) fn from_runtime_box(
             }
             (err, Some(pc))
         }
-        wasmtime_runtime::TrapReason::Wasm(trap_code) => (trap_code.into(), None),
+        crate::runtime::vm::TrapReason::Wasm(trap_code) => (trap_code.into(), None),
     };
 
     if let Some(bt) = backtrace {
@@ -201,7 +201,7 @@ pub struct WasmBacktrace {
     // This is currently only present for the `Debug` implementation for extra
     // context.
     #[allow(dead_code)]
-    runtime_trace: wasmtime_runtime::Backtrace,
+    runtime_trace: crate::runtime::vm::Backtrace,
 }
 
 impl WasmBacktrace {
@@ -260,7 +260,7 @@ impl WasmBacktrace {
             WasmBacktrace {
                 wasm_trace: Vec::new(),
                 hint_wasm_backtrace_details_env: false,
-                runtime_trace: wasmtime_runtime::Backtrace::empty(),
+                runtime_trace: crate::runtime::vm::Backtrace::empty(),
             }
         }
     }
@@ -275,14 +275,14 @@ impl WasmBacktrace {
         let store = store.as_context();
         Self::from_captured(
             store.0,
-            wasmtime_runtime::Backtrace::new(store.0.runtime_limits()),
+            crate::runtime::vm::Backtrace::new(store.0.runtime_limits()),
             None,
         )
     }
 
     fn from_captured(
         store: &StoreOpaque,
-        runtime_trace: wasmtime_runtime::Backtrace,
+        runtime_trace: crate::runtime::vm::Backtrace,
         trap_pc: Option<usize>,
     ) -> Self {
         let mut wasm_trace = Vec::<FrameInfo>::with_capacity(runtime_trace.frames().len());
@@ -310,7 +310,7 @@ impl WasmBacktrace {
             };
 
             // NB: The PC we are looking up _must_ be a Wasm PC since
-            // `wasmtime_runtime::Backtrace` only contains Wasm frames.
+            // `crate::runtime::vm::Backtrace` only contains Wasm frames.
             //
             // However, consider the case where we have multiple, nested calls
             // across stores (with host code in between, by necessity, since
@@ -326,13 +326,13 @@ impl WasmBacktrace {
             //     | Wasm in store B |  V
             //     +-----------------+
             //
-            // In this scenario, the `wasmtime_runtime::Backtrace` will contain
-            // two frames: Wasm in store B followed by Wasm in store A. But
-            // `store.modules()` will only have the module information for
-            // modules instantiated within this store. Therefore, we use `if let
-            // Some(..)` instead of the `unwrap` you might otherwise expect and
-            // we ignore frames from modules that were not registered in this
-            // store's module registry.
+            // In this scenario, the `crate::runtime::vm::Backtrace` will
+            // contain two frames: Wasm in store B followed by Wasm in store
+            // A. But `store.modules()` will only have the module information
+            // for modules instantiated within this store. Therefore, we use `if
+            // let Some(..)` instead of the `unwrap` you might otherwise expect
+            // and we ignore frames from modules that were not registered in
+            // this store's module registry.
             if let Some((info, module)) = store.modules().lookup_frame_info(pc_to_lookup) {
                 wasm_trace.push(info);
 
diff --git a/crates/wasmtime/src/runtime/v128.rs b/crates/wasmtime/src/runtime/v128.rs
index c4ad50088..9987c49a2 100644
--- a/crates/wasmtime/src/runtime/v128.rs
+++ b/crates/wasmtime/src/runtime/v128.rs
@@ -3,11 +3,11 @@
     allow(unused_imports)
 )]
 
+use crate::runtime::vm::V128Abi;
 use crate::store::{AutoAssertNoGc, StoreOpaque};
 use crate::{Result, ValRaw, ValType, WasmTy};
 use std::cmp::Ordering;
 use std::fmt;
-use wasmtime_runtime::V128Abi;
 
 /// Representation of a 128-bit vector type, `v128`, for WebAssembly.
 ///
diff --git a/crates/wasmtime/src/runtime/values.rs b/crates/wasmtime/src/runtime/values.rs
index b06c697d1..efcd1fb99 100644
--- a/crates/wasmtime/src/runtime/values.rs
+++ b/crates/wasmtime/src/runtime/values.rs
@@ -1,3 +1,4 @@
+use crate::runtime::vm::{TableElement, VMGcRef};
 use crate::store::{AutoAssertNoGc, StoreOpaque};
 use crate::{
     AnyRef, AsContext, AsContextMut, ExternRef, Func, HeapType, RefType, Rooted, RootedGcRefImpl,
@@ -5,9 +6,8 @@ use crate::{
 };
 use anyhow::{bail, Context, Result};
 use std::ptr;
-use wasmtime_runtime::{TableElement, VMGcRef};
 
-pub use wasmtime_runtime::ValRaw;
+pub use crate::runtime::vm::ValRaw;
 
 /// Possible runtime values that a WebAssembly module can either consume or
 /// produce.
diff --git a/crates/runtime/src/lib.rs b/crates/wasmtime/src/runtime/vm.rs
similarity index 89%
rename from crates/runtime/src/lib.rs
rename to crates/wasmtime/src/runtime/vm.rs
index 868336377..8e6f6ce7b 100644
--- a/crates/runtime/src/lib.rs
+++ b/crates/wasmtime/src/runtime/vm.rs
@@ -43,33 +43,33 @@ pub mod mpk;
 #[cfg(feature = "debug-builtins")]
 pub use wasmtime_jit_debug::gdb_jit_int::GdbJitImageRegistration;
 
-pub use crate::arch::{get_stack_pointer, V128Abi};
-pub use crate::async_yield::*;
-pub use crate::export::*;
-pub use crate::gc::*;
-pub use crate::imports::Imports;
-pub use crate::instance::{
+pub use crate::runtime::vm::arch::{get_stack_pointer, V128Abi};
+pub use crate::runtime::vm::async_yield::*;
+pub use crate::runtime::vm::export::*;
+pub use crate::runtime::vm::gc::*;
+pub use crate::runtime::vm::imports::Imports;
+pub use crate::runtime::vm::instance::{
     GcHeapAllocationIndex, Instance, InstanceAllocationRequest, InstanceAllocator,
     InstanceAllocatorImpl, InstanceHandle, MemoryAllocationIndex, OnDemandInstanceAllocator,
     StorePtr, TableAllocationIndex,
 };
 #[cfg(feature = "pooling-allocator")]
-pub use crate::instance::{
+pub use crate::runtime::vm::instance::{
     InstanceLimits, PoolingInstanceAllocator, PoolingInstanceAllocatorConfig,
 };
-pub use crate::memory::{DefaultMemoryCreator, Memory, RuntimeLinearMemory, RuntimeMemoryCreator};
-pub use crate::mmap::Mmap;
-pub use crate::mmap_vec::MmapVec;
-pub use crate::mpk::MpkEnabled;
-pub use crate::store_box::*;
-pub use crate::sys::unwind::UnwindRegistration;
-pub use crate::table::{Table, TableElement};
-pub use crate::traphandlers::*;
-pub use crate::vmcontext::{
+pub use crate::runtime::vm::memory::{Memory, RuntimeLinearMemory, RuntimeMemoryCreator};
+pub use crate::runtime::vm::mmap::Mmap;
+pub use crate::runtime::vm::mmap_vec::MmapVec;
+pub use crate::runtime::vm::mpk::MpkEnabled;
+pub use crate::runtime::vm::store_box::*;
+pub use crate::runtime::vm::sys::unwind::UnwindRegistration;
+pub use crate::runtime::vm::table::{Table, TableElement};
+pub use crate::runtime::vm::traphandlers::*;
+pub use crate::runtime::vm::vmcontext::{
     VMArrayCallFunction, VMArrayCallHostFuncContext, VMContext, VMFuncRef, VMFunctionBody,
-    VMFunctionImport, VMGlobalDefinition, VMGlobalImport, VMInvokeArgument, VMMemoryDefinition,
-    VMMemoryImport, VMNativeCallFunction, VMNativeCallHostFuncContext, VMOpaqueContext,
-    VMRuntimeLimits, VMTableDefinition, VMTableImport, VMWasmCallFunction, ValRaw,
+    VMFunctionImport, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport,
+    VMNativeCallFunction, VMNativeCallHostFuncContext, VMOpaqueContext, VMRuntimeLimits,
+    VMTableImport, VMWasmCallFunction, ValRaw,
 };
 pub use send_sync_ptr::SendSyncPtr;
 
@@ -77,17 +77,14 @@ mod module_id;
 pub use module_id::{CompiledModuleId, CompiledModuleIdAllocator};
 
 mod cow;
-pub use crate::cow::{MemoryImage, MemoryImageSlot, ModuleMemoryImages};
-
-/// Version number of this crate.
-pub const VERSION: &str = env!("CARGO_PKG_VERSION");
+pub use crate::runtime::vm::cow::{MemoryImage, MemoryImageSlot, ModuleMemoryImages};
 
 /// Dynamic runtime functionality needed by this crate throughout the execution
 /// of a wasm instance.
 ///
 /// This trait is used to store a raw pointer trait object within each
 /// `VMContext`. This raw pointer trait object points back to the
-/// `wasmtime::Store` internally but is type-erased so this `wasmtime_runtime`
+/// `wasmtime::Store` internally but is type-erased so this `wasmtime-runtime`
 /// crate doesn't need the entire `wasmtime` crate to build.
 ///
 /// Note that this is an extra-unsafe trait because no heed is paid to the
diff --git a/crates/runtime/src/arch/aarch64.rs b/crates/wasmtime/src/runtime/vm/arch/aarch64.rs
similarity index 100%
rename from crates/runtime/src/arch/aarch64.rs
rename to crates/wasmtime/src/runtime/vm/arch/aarch64.rs
diff --git a/crates/runtime/src/arch/mod.rs b/crates/wasmtime/src/runtime/vm/arch/mod.rs
similarity index 100%
rename from crates/runtime/src/arch/mod.rs
rename to crates/wasmtime/src/runtime/vm/arch/mod.rs
diff --git a/crates/runtime/src/arch/riscv64.rs b/crates/wasmtime/src/runtime/vm/arch/riscv64.rs
similarity index 100%
rename from crates/runtime/src/arch/riscv64.rs
rename to crates/wasmtime/src/runtime/vm/arch/riscv64.rs
diff --git a/crates/runtime/src/arch/s390x.S b/crates/wasmtime/src/runtime/vm/arch/s390x.S
similarity index 100%
rename from crates/runtime/src/arch/s390x.S
rename to crates/wasmtime/src/runtime/vm/arch/s390x.S
diff --git a/crates/runtime/src/arch/s390x.rs b/crates/wasmtime/src/runtime/vm/arch/s390x.rs
similarity index 100%
rename from crates/runtime/src/arch/s390x.rs
rename to crates/wasmtime/src/runtime/vm/arch/s390x.rs
diff --git a/crates/runtime/src/arch/x86_64.rs b/crates/wasmtime/src/runtime/vm/arch/x86_64.rs
similarity index 100%
rename from crates/runtime/src/arch/x86_64.rs
rename to crates/wasmtime/src/runtime/vm/arch/x86_64.rs
diff --git a/crates/runtime/src/async_yield.rs b/crates/wasmtime/src/runtime/vm/async_yield.rs
similarity index 100%
rename from crates/runtime/src/async_yield.rs
rename to crates/wasmtime/src/runtime/vm/async_yield.rs
diff --git a/crates/runtime/src/component.rs b/crates/wasmtime/src/runtime/vm/component.rs
similarity index 99%
rename from crates/runtime/src/component.rs
rename to crates/wasmtime/src/runtime/vm/component.rs
index ccdf55717..eff73a65b 100644
--- a/crates/runtime/src/component.rs
+++ b/crates/wasmtime/src/runtime/vm/component.rs
@@ -6,7 +6,7 @@
 //! Eventually it's intended that module-to-module calls, which would be
 //! cranelift-compiled adapters, will use this `VMComponentContext` as well.
 
-use crate::{
+use crate::runtime::vm::{
     SendSyncPtr, Store, VMArrayCallFunction, VMFuncRef, VMGlobalDefinition, VMMemoryDefinition,
     VMNativeCallFunction, VMOpaqueContext, VMWasmCallFunction, ValRaw,
 };
diff --git a/crates/runtime/src/component/libcalls.rs b/crates/wasmtime/src/runtime/vm/component/libcalls.rs
similarity index 98%
rename from crates/runtime/src/component/libcalls.rs
rename to crates/wasmtime/src/runtime/vm/component/libcalls.rs
index ce3c00460..525e983b9 100644
--- a/crates/runtime/src/component/libcalls.rs
+++ b/crates/wasmtime/src/runtime/vm/component/libcalls.rs
@@ -1,6 +1,6 @@
 //! Implementation of string transcoding required by the component model.
 
-use crate::component::{ComponentInstance, VMComponentContext};
+use crate::runtime::vm::component::{ComponentInstance, VMComponentContext};
 use anyhow::{anyhow, Result};
 use std::cell::Cell;
 use std::slice;
@@ -129,13 +129,13 @@ mod trampolines {
                     //
                     // Additionally assume that every function below returns a
                     // `Result` where errors turn into traps.
-                    let result = crate::traphandlers::catch_unwind_and_longjmp(|| {
+                    let result = crate::runtime::vm::traphandlers::catch_unwind_and_longjmp(|| {
                         shims!(@invoke $name() $($pname)*)
                     });
                     match result {
                         Ok(ret) => shims!(@convert_ret ret $($pname: $param)*),
-                        Err(err) => crate::traphandlers::raise_trap(
-                            crate::traphandlers::TrapReason::User {
+                        Err(err) => crate::runtime::vm::traphandlers::raise_trap(
+                            crate::runtime::vm::traphandlers::TrapReason::User {
                                 error: err,
                                 needs_backtrace: true,
                             },
diff --git a/crates/runtime/src/component/resources.rs b/crates/wasmtime/src/runtime/vm/component/resources.rs
similarity index 100%
rename from crates/runtime/src/component/resources.rs
rename to crates/wasmtime/src/runtime/vm/component/resources.rs
diff --git a/crates/runtime/src/const_expr.rs b/crates/wasmtime/src/runtime/vm/const_expr.rs
similarity index 98%
rename from crates/runtime/src/const_expr.rs
rename to crates/wasmtime/src/runtime/vm/const_expr.rs
index 54a47589c..48d809da2 100644
--- a/crates/runtime/src/const_expr.rs
+++ b/crates/wasmtime/src/runtime/vm/const_expr.rs
@@ -1,6 +1,6 @@
 //! Evaluating const expressions.
 
-use crate::{Instance, VMGcRef, ValRaw, I31};
+use crate::runtime::vm::{Instance, VMGcRef, ValRaw, I31};
 use anyhow::{anyhow, bail, Result};
 use smallvec::SmallVec;
 use wasmtime_environ::{ConstExpr, FuncIndex, GlobalIndex, Module};
diff --git a/crates/runtime/src/cow.rs b/crates/wasmtime/src/runtime/vm/cow.rs
similarity index 99%
rename from crates/runtime/src/cow.rs
rename to crates/wasmtime/src/runtime/vm/cow.rs
index 908e80d49..eeacbdff4 100644
--- a/crates/runtime/src/cow.rs
+++ b/crates/wasmtime/src/runtime/vm/cow.rs
@@ -1,8 +1,8 @@
 //! Copy-on-write initialization support: creation of backing images for
 //! modules, and logic to support mapping these backing images into memory.
 
-use crate::sys::vm::{self, MemoryImageSource};
-use crate::{MmapVec, SendSyncPtr};
+use crate::runtime::vm::sys::vm::{self, MemoryImageSource};
+use crate::runtime::vm::{MmapVec, SendSyncPtr};
 use anyhow::Result;
 use std::ffi::c_void;
 use std::ops::Range;
@@ -157,7 +157,7 @@ impl ModuleMemoryImages {
             _ => return Ok(None),
         };
         let mut memories = PrimaryMap::with_capacity(map.len());
-        let page_size = crate::page_size() as u32;
+        let page_size = crate::runtime::vm::page_size() as u32;
         for (memory_index, init) in map {
             // mmap-based-initialization only works for defined memories with a
             // known starting point of all zeros, so bail out if the mmeory is
@@ -682,13 +682,13 @@ mod test {
     use std::sync::Arc;
 
     use super::{MemoryImage, MemoryImageSlot, MemoryImageSource, MemoryPlan, MemoryStyle};
-    use crate::mmap::Mmap;
+    use crate::runtime::vm::mmap::Mmap;
     use anyhow::Result;
     use wasmtime_environ::Memory;
 
     fn create_memfd_with_data(offset: usize, data: &[u8]) -> Result<MemoryImage> {
         // Offset must be page-aligned.
-        let page_size = crate::page_size();
+        let page_size = crate::runtime::vm::page_size();
         assert_eq!(offset & (page_size - 1), 0);
 
         // The image length is rounded up to the nearest page size
diff --git a/crates/runtime/src/debug_builtins.rs b/crates/wasmtime/src/runtime/vm/debug_builtins.rs
similarity index 95%
rename from crates/runtime/src/debug_builtins.rs
rename to crates/wasmtime/src/runtime/vm/debug_builtins.rs
index 82ac1cf37..beef757ae 100644
--- a/crates/runtime/src/debug_builtins.rs
+++ b/crates/wasmtime/src/runtime/vm/debug_builtins.rs
@@ -1,7 +1,7 @@
 #![doc(hidden)]
 
-use crate::instance::Instance;
-use crate::vmcontext::VMContext;
+use crate::runtime::vm::instance::Instance;
+use crate::runtime::vm::vmcontext::VMContext;
 use wasmtime_environ::{EntityRef, MemoryIndex};
 use wasmtime_versioned_export_macros::versioned_export;
 
diff --git a/crates/runtime/src/export.rs b/crates/wasmtime/src/runtime/vm/export.rs
similarity index 98%
rename from crates/runtime/src/export.rs
rename to crates/wasmtime/src/runtime/vm/export.rs
index bd05c1b40..90e8000d8 100644
--- a/crates/runtime/src/export.rs
+++ b/crates/wasmtime/src/runtime/vm/export.rs
@@ -1,4 +1,4 @@
-use crate::vmcontext::{
+use crate::runtime::vm::vmcontext::{
     VMContext, VMFuncRef, VMGlobalDefinition, VMMemoryDefinition, VMTableDefinition,
 };
 use std::ptr::NonNull;
diff --git a/crates/runtime/src/gc.rs b/crates/wasmtime/src/runtime/vm/gc.rs
similarity index 99%
rename from crates/runtime/src/gc.rs
rename to crates/wasmtime/src/runtime/vm/gc.rs
index bbbc05ccf..d321e8986 100644
--- a/crates/runtime/src/gc.rs
+++ b/crates/wasmtime/src/runtime/vm/gc.rs
@@ -20,7 +20,7 @@ pub use gc_runtime::*;
 pub use host_data::*;
 pub use i31::*;
 
-use crate::GcHeapAllocationIndex;
+use crate::runtime::vm::GcHeapAllocationIndex;
 use anyhow::{bail, Result};
 use wasmtime_environ::StackMap;
 
diff --git a/crates/runtime/src/gc/disabled.rs b/crates/wasmtime/src/runtime/vm/gc/disabled.rs
similarity index 91%
rename from crates/runtime/src/gc/disabled.rs
rename to crates/wasmtime/src/runtime/vm/gc/disabled.rs
index 8cdcd044c..795e3fc1a 100644
--- a/crates/runtime/src/gc/disabled.rs
+++ b/crates/wasmtime/src/runtime/vm/gc/disabled.rs
@@ -5,7 +5,7 @@
 
 #![allow(missing_docs)]
 
-use crate::{GcHeap, GcRuntime};
+use crate::runtime::vm::{GcHeap, GcRuntime};
 use anyhow::Result;
 
 pub fn default_gc_runtime() -> impl GcRuntime {
diff --git a/crates/runtime/src/gc/enabled.rs b/crates/wasmtime/src/runtime/vm/gc/enabled.rs
similarity index 90%
rename from crates/runtime/src/gc/enabled.rs
rename to crates/wasmtime/src/runtime/vm/gc/enabled.rs
index 44ea24b1d..d54575321 100644
--- a/crates/runtime/src/gc/enabled.rs
+++ b/crates/wasmtime/src/runtime/vm/gc/enabled.rs
@@ -7,7 +7,7 @@ mod free_list;
 pub use drc::*;
 pub use externref::*;
 
-use crate::GcRuntime;
+use crate::runtime::vm::GcRuntime;
 
 /// Get the default GC runtime.
 pub fn default_gc_runtime() -> impl GcRuntime {
diff --git a/crates/runtime/src/gc/enabled/drc.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs
similarity index 99%
rename from crates/runtime/src/gc/enabled/drc.rs
rename to crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs
index 56bba9838..a43a2f955 100644
--- a/crates/runtime/src/gc/enabled/drc.rs
+++ b/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs
@@ -42,7 +42,7 @@
 //! <https://openresearch-repository.anu.edu.au/bitstream/1885/42030/2/hon-thesis.pdf>
 
 use super::free_list::FreeList;
-use crate::{
+use crate::runtime::vm::{
     ExternRefHostDataId, ExternRefHostDataTable, GarbageCollection, GcHeap, GcHeapObject,
     GcProgress, GcRootsIter, GcRuntime, Mmap, TypedGcRef, VMExternRef, VMGcHeader, VMGcRef,
 };
@@ -903,7 +903,7 @@ mod tests {
 
         assert_eq!(
             offsets.vm_drc_header_ref_count(),
-            actual_offset.try_into().unwrap(),
+            u32::try_from(actual_offset).unwrap(),
         );
     }
 
diff --git a/crates/runtime/src/gc/enabled/externref.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/externref.rs
similarity index 98%
rename from crates/runtime/src/gc/enabled/externref.rs
rename to crates/wasmtime/src/runtime/vm/gc/enabled/externref.rs
index 49fda6655..3e3461308 100644
--- a/crates/runtime/src/gc/enabled/externref.rs
+++ b/crates/wasmtime/src/runtime/vm/gc/enabled/externref.rs
@@ -1,4 +1,4 @@
-use crate::{GcHeap, GcStore, VMGcRef};
+use crate::runtime::vm::{GcHeap, GcStore, VMGcRef};
 use wasmtime_environ::VMGcKind;
 
 /// A `VMGcRef` that we know points to an `externref`.
diff --git a/crates/runtime/src/gc/enabled/free_list.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs
similarity index 100%
rename from crates/runtime/src/gc/enabled/free_list.rs
rename to crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs
diff --git a/crates/runtime/src/gc/gc_ref.rs b/crates/wasmtime/src/runtime/vm/gc/gc_ref.rs
similarity index 99%
rename from crates/runtime/src/gc/gc_ref.rs
rename to crates/wasmtime/src/runtime/vm/gc/gc_ref.rs
index b9de515f4..952811368 100644
--- a/crates/runtime/src/gc/gc_ref.rs
+++ b/crates/wasmtime/src/runtime/vm/gc/gc_ref.rs
@@ -1,4 +1,4 @@
-use crate::{GcHeap, GcStore, I31};
+use crate::runtime::vm::{GcHeap, GcStore, I31};
 use anyhow::{Context, Result};
 use std::num::NonZeroU32;
 use wasmtime_environ::{VMGcKind, VMSharedTypeIndex};
diff --git a/crates/runtime/src/gc/gc_runtime.rs b/crates/wasmtime/src/runtime/vm/gc/gc_runtime.rs
similarity index 99%
rename from crates/runtime/src/gc/gc_runtime.rs
rename to crates/wasmtime/src/runtime/vm/gc/gc_runtime.rs
index 1d2741dc5..b36c841d8 100644
--- a/crates/runtime/src/gc/gc_runtime.rs
+++ b/crates/wasmtime/src/runtime/vm/gc/gc_runtime.rs
@@ -1,6 +1,6 @@
 //! Traits for abstracting over our different garbage collectors.
 
-use crate::{
+use crate::runtime::vm::{
     ExternRefHostDataId, ExternRefHostDataTable, SendSyncPtr, VMExternRef, VMGcHeader, VMGcRef,
 };
 use anyhow::Result;
@@ -482,7 +482,7 @@ pub enum GcProgress {
 pub async fn collect_async<'a>(mut collection: Box<dyn GarbageCollection<'a> + 'a>) {
     loop {
         match collection.collect_increment() {
-            GcProgress::Continue => crate::Yield::new().await,
+            GcProgress::Continue => crate::runtime::vm::Yield::new().await,
             GcProgress::Complete => return,
         }
     }
diff --git a/crates/runtime/src/gc/host_data.rs b/crates/wasmtime/src/runtime/vm/gc/host_data.rs
similarity index 100%
rename from crates/runtime/src/gc/host_data.rs
rename to crates/wasmtime/src/runtime/vm/gc/host_data.rs
diff --git a/crates/runtime/src/gc/i31.rs b/crates/wasmtime/src/runtime/vm/gc/i31.rs
similarity index 100%
rename from crates/runtime/src/gc/i31.rs
rename to crates/wasmtime/src/runtime/vm/gc/i31.rs
diff --git a/crates/runtime/src/helpers.c b/crates/wasmtime/src/runtime/vm/helpers.c
similarity index 100%
rename from crates/runtime/src/helpers.c
rename to crates/wasmtime/src/runtime/vm/helpers.c
diff --git a/crates/runtime/src/imports.rs b/crates/wasmtime/src/runtime/vm/imports.rs
similarity index 89%
rename from crates/runtime/src/imports.rs
rename to crates/wasmtime/src/runtime/vm/imports.rs
index fe6031293..a1b47e17d 100644
--- a/crates/runtime/src/imports.rs
+++ b/crates/wasmtime/src/runtime/vm/imports.rs
@@ -1,4 +1,6 @@
-use crate::vmcontext::{VMFunctionImport, VMGlobalImport, VMMemoryImport, VMTableImport};
+use crate::runtime::vm::vmcontext::{
+    VMFunctionImport, VMGlobalImport, VMMemoryImport, VMTableImport,
+};
 
 /// Resolved import pointers.
 ///
diff --git a/crates/runtime/src/instance.rs b/crates/wasmtime/src/runtime/vm/instance.rs
similarity index 99%
rename from crates/runtime/src/instance.rs
rename to crates/wasmtime/src/runtime/vm/instance.rs
index d9a072e46..687d894d2 100644
--- a/crates/runtime/src/instance.rs
+++ b/crates/wasmtime/src/runtime/vm/instance.rs
@@ -2,16 +2,16 @@
 //! wasm module (except its callstack and register state). An
 //! `InstanceHandle` is a reference-counting handle for an `Instance`.
 
-use crate::const_expr::{ConstEvalContext, ConstExprEvaluator};
-use crate::export::Export;
-use crate::memory::{Memory, RuntimeMemoryCreator};
-use crate::table::{Table, TableElement, TableElementType};
-use crate::vmcontext::{
+use crate::runtime::vm::const_expr::{ConstEvalContext, ConstExprEvaluator};
+use crate::runtime::vm::export::Export;
+use crate::runtime::vm::memory::{Memory, RuntimeMemoryCreator};
+use crate::runtime::vm::table::{Table, TableElement, TableElementType};
+use crate::runtime::vm::vmcontext::{
     VMBuiltinFunctionsArray, VMContext, VMFuncRef, VMFunctionImport, VMGlobalDefinition,
     VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMOpaqueContext, VMRuntimeLimits,
     VMTableDefinition, VMTableImport,
 };
-use crate::{
+use crate::runtime::vm::{
     ExportFunction, ExportGlobal, ExportMemory, ExportTable, GcStore, Imports, ModuleRuntimeInfo,
     SendSyncPtr, Store, VMFunctionBody, VMGcRef, WasmFault,
 };
@@ -355,15 +355,6 @@ impl Instance {
         unsafe { *self.vmctx_plus_offset(self.offsets().vmctx_vmmemory_pointer(index)) }
     }
 
-    /// Return the memories defined within this instance (not imported).
-    pub fn defined_memories<'a>(
-        &'a self,
-    ) -> impl ExactSizeIterator<Item = (DefinedMemoryIndex, &'a Memory)> + 'a {
-        self.memories
-            .iter()
-            .map(|(index, (_alloc_index, memory))| (index, memory))
-    }
-
     /// Return the indexed `VMGlobalDefinition`.
     fn global_ptr(&mut self, index: DefinedGlobalIndex) -> *mut VMGlobalDefinition {
         unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_vmglobal_definition(index)) }
diff --git a/crates/runtime/src/instance/allocator.rs b/crates/wasmtime/src/runtime/vm/instance/allocator.rs
similarity index 95%
rename from crates/runtime/src/instance/allocator.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator.rs
index 143b3f268..b5e701fc4 100644
--- a/crates/runtime/src/instance/allocator.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator.rs
@@ -1,20 +1,20 @@
-use crate::const_expr::{ConstEvalContext, ConstExprEvaluator};
-use crate::imports::Imports;
-use crate::instance::{Instance, InstanceHandle};
-use crate::memory::Memory;
-use crate::mpk::ProtectionKey;
-use crate::table::Table;
-use crate::{CompiledModuleId, ModuleRuntimeInfo, Store, VMFuncRef, VMGcRef};
+use crate::runtime::vm::const_expr::{ConstEvalContext, ConstExprEvaluator};
+use crate::runtime::vm::imports::Imports;
+use crate::runtime::vm::instance::{Instance, InstanceHandle};
+use crate::runtime::vm::memory::Memory;
+use crate::runtime::vm::mpk::ProtectionKey;
+use crate::runtime::vm::table::Table;
+use crate::runtime::vm::{CompiledModuleId, ModuleRuntimeInfo, Store, VMFuncRef, VMGcRef};
 use anyhow::{anyhow, bail, Result};
 use std::{alloc, any::Any, mem, ptr, sync::Arc};
 use wasmtime_environ::{
     DefinedMemoryIndex, DefinedTableIndex, HostPtr, InitMemory, MemoryInitialization,
-    MemoryInitializer, MemoryPlan, Module, PrimaryMap, TableInitialValue, TablePlan, TableSegment,
-    Trap, VMOffsets, WasmHeapTopType, WasmValType, WASM_PAGE_SIZE,
+    MemoryInitializer, MemoryPlan, Module, PrimaryMap, TableInitialValue, TablePlan, Trap,
+    VMOffsets, WasmHeapTopType, WasmValType, WASM_PAGE_SIZE,
 };
 
 #[cfg(feature = "gc")]
-use crate::{GcHeap, GcRuntime};
+use crate::runtime::vm::{GcHeap, GcRuntime};
 
 #[cfg(feature = "component-model")]
 use wasmtime_environ::{
@@ -63,6 +63,7 @@ pub struct InstanceAllocationRequest<'a> {
     pub store: StorePtr,
 
     /// Indicates '--wmemcheck' flag.
+    #[cfg_attr(not(feature = "wmemcheck"), allow(dead_code))]
     pub wmemcheck: bool,
 
     /// Request that the instance's memories be protected by a specific
@@ -524,24 +525,18 @@ pub trait InstanceAllocator: InstanceAllocatorImpl {
 // must use the defaults. This blanket impl provides both of those things.
 impl<T: InstanceAllocatorImpl> InstanceAllocator for T {}
 
-fn get_table_init_start(init: &TableSegment, instance: &mut Instance) -> Result<u32> {
-    match init.base {
-        Some(base) => {
-            let val = unsafe { *(*instance.defined_or_imported_global_ptr(base)).as_u32() };
-
-            init.offset
-                .checked_add(val)
-                .ok_or_else(|| anyhow!("element segment global base overflows"))
-        }
-        None => Ok(init.offset),
-    }
-}
-
 fn check_table_init_bounds(instance: &mut Instance, module: &Module) -> Result<()> {
+    let mut const_evaluator = ConstExprEvaluator::default();
+
     for segment in module.table_initialization.segments.iter() {
         let table = unsafe { &*instance.get_table(segment.table_index) };
-        let start = get_table_init_start(segment, instance)?;
-        let start = usize::try_from(start).unwrap();
+        let mut context = ConstEvalContext::new(instance, module);
+        let start = unsafe {
+            const_evaluator
+                .eval(&mut context, &segment.offset)
+                .expect("const expression should be valid")
+        };
+        let start = usize::try_from(start.get_u32()).unwrap();
         let end = start.checked_add(usize::try_from(segment.elements.len()).unwrap());
 
         match end {
@@ -609,12 +604,17 @@ fn initialize_tables(instance: &mut Instance, module: &Module) -> Result<()> {
     // iterates over all segments (Segments mode) or leftover
     // segments (FuncTable mode) to initialize.
     for segment in module.table_initialization.segments.iter() {
-        let start = get_table_init_start(segment, instance)?;
+        let mut context = ConstEvalContext::new(instance, module);
+        let start = unsafe {
+            const_evaluator
+                .eval(&mut context, &segment.offset)
+                .expect("const expression should be valid")
+        };
         instance.table_init_segment(
             &mut const_evaluator,
             segment.table_index,
             &segment.elements,
-            start,
+            start.get_u32(),
             0,
             segment.elements.len(),
         )?;
diff --git a/crates/runtime/src/instance/allocator/on_demand.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/on_demand.rs
similarity index 94%
rename from crates/runtime/src/instance/allocator/on_demand.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator/on_demand.rs
index bd8941bbd..bfad26f32 100644
--- a/crates/runtime/src/instance/allocator/on_demand.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator/on_demand.rs
@@ -1,11 +1,11 @@
 use super::{
     InstanceAllocationRequest, InstanceAllocatorImpl, MemoryAllocationIndex, TableAllocationIndex,
 };
-use crate::instance::RuntimeMemoryCreator;
-use crate::memory::{DefaultMemoryCreator, Memory};
-use crate::mpk::ProtectionKey;
-use crate::table::Table;
-use crate::CompiledModuleId;
+use crate::runtime::vm::instance::RuntimeMemoryCreator;
+use crate::runtime::vm::memory::{DefaultMemoryCreator, Memory};
+use crate::runtime::vm::mpk::ProtectionKey;
+use crate::runtime::vm::table::Table;
+use crate::runtime::vm::CompiledModuleId;
 use anyhow::Result;
 use std::sync::Arc;
 use wasmtime_environ::{
@@ -13,7 +13,7 @@ use wasmtime_environ::{
 };
 
 #[cfg(feature = "gc")]
-use crate::{GcHeap, GcHeapAllocationIndex, GcRuntime};
+use crate::runtime::vm::{GcHeap, GcHeapAllocationIndex, GcRuntime};
 
 #[cfg(feature = "async")]
 use wasmtime_fiber::RuntimeFiberStackCreator;
@@ -209,7 +209,7 @@ unsafe impl InstanceAllocatorImpl for OnDemandInstanceAllocator {
     fn deallocate_gc_heap(
         &self,
         allocation_index: GcHeapAllocationIndex,
-        gc_heap: Box<dyn crate::GcHeap>,
+        gc_heap: Box<dyn crate::runtime::vm::GcHeap>,
     ) {
         debug_assert_eq!(allocation_index, GcHeapAllocationIndex::default());
         drop(gc_heap);
diff --git a/crates/runtime/src/instance/allocator/pooling.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs
similarity index 99%
rename from crates/runtime/src/instance/allocator/pooling.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs
index dbed737cc..9af809e6b 100644
--- a/crates/runtime/src/instance/allocator/pooling.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs
@@ -42,7 +42,7 @@ cfg_if::cfg_if! {
 use super::{
     InstanceAllocationRequest, InstanceAllocatorImpl, MemoryAllocationIndex, TableAllocationIndex,
 };
-use crate::{
+use crate::runtime::vm::{
     instance::Instance,
     mpk::{self, MpkEnabled, ProtectionKey, ProtectionMask},
     CompiledModuleId, Memory, Table,
@@ -62,7 +62,7 @@ use wasmtime_environ::{
 #[cfg(feature = "gc")]
 use super::GcHeapAllocationIndex;
 #[cfg(feature = "gc")]
-use crate::{GcHeap, GcRuntime};
+use crate::runtime::vm::{GcHeap, GcRuntime};
 #[cfg(feature = "gc")]
 use gc_heap_pool::GcHeapPool;
 
diff --git a/crates/runtime/src/instance/allocator/pooling/gc_heap_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/gc_heap_pool.rs
similarity index 97%
rename from crates/runtime/src/instance/allocator/pooling/gc_heap_pool.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator/pooling/gc_heap_pool.rs
index a5599bee1..24331eb16 100644
--- a/crates/runtime/src/instance/allocator/pooling/gc_heap_pool.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/gc_heap_pool.rs
@@ -1,6 +1,6 @@
 use super::index_allocator::{SimpleIndexAllocator, SlotId};
 use super::GcHeapAllocationIndex;
-use crate::{GcHeap, GcRuntime, PoolingInstanceAllocatorConfig, Result};
+use crate::runtime::vm::{GcHeap, GcRuntime, PoolingInstanceAllocatorConfig, Result};
 use anyhow::anyhow;
 use std::sync::Mutex;
 
diff --git a/crates/runtime/src/instance/allocator/pooling/generic_stack_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/generic_stack_pool.rs
similarity index 97%
rename from crates/runtime/src/instance/allocator/pooling/generic_stack_pool.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator/pooling/generic_stack_pool.rs
index 33fad0e1b..3b8bc9920 100644
--- a/crates/runtime/src/instance/allocator/pooling/generic_stack_pool.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/generic_stack_pool.rs
@@ -1,6 +1,6 @@
 #![cfg_attr(not(asan), allow(dead_code))]
 
-use crate::PoolingInstanceAllocatorConfig;
+use crate::runtime::vm::PoolingInstanceAllocatorConfig;
 use anyhow::{bail, Result};
 use std::sync::atomic::{AtomicU64, Ordering};
 
diff --git a/crates/runtime/src/instance/allocator/pooling/index_allocator.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/index_allocator.rs
similarity index 99%
rename from crates/runtime/src/instance/allocator/pooling/index_allocator.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator/pooling/index_allocator.rs
index 7d35f8e3f..ffb87cf5f 100644
--- a/crates/runtime/src/instance/allocator/pooling/index_allocator.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/index_allocator.rs
@@ -1,6 +1,6 @@
 //! Index/slot allocator policies for the pooling allocator.
 
-use crate::CompiledModuleId;
+use crate::runtime::vm::CompiledModuleId;
 use std::collections::hash_map::{Entry, HashMap};
 use std::mem;
 use std::sync::Mutex;
@@ -482,7 +482,7 @@ impl List {
 #[cfg(test)]
 mod test {
     use super::*;
-    use crate::CompiledModuleIdAllocator;
+    use crate::runtime::vm::CompiledModuleIdAllocator;
     use wasmtime_environ::EntityRef;
 
     #[test]
diff --git a/crates/runtime/src/instance/allocator/pooling/memory_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs
similarity index 99%
rename from crates/runtime/src/instance/allocator/pooling/memory_pool.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs
index 52088f51d..01f704d72 100644
--- a/crates/runtime/src/instance/allocator/pooling/memory_pool.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs
@@ -54,8 +54,8 @@ use super::{
     index_allocator::{MemoryInModule, ModuleAffinityIndexAllocator, SlotId},
     MemoryAllocationIndex,
 };
-use crate::mpk::{self, ProtectionKey, ProtectionMask};
-use crate::{
+use crate::runtime::vm::mpk::{self, ProtectionKey, ProtectionMask};
+use crate::runtime::vm::{
     CompiledModuleId, InstanceAllocationRequest, InstanceLimits, Memory, MemoryImageSlot, Mmap,
     MpkEnabled, PoolingInstanceAllocatorConfig,
 };
@@ -720,7 +720,7 @@ fn calculate(constraints: &SlabConstraints) -> Result<SlabLayout> {
     };
 
     // The page-aligned slot size; equivalent to `memory_and_guard_size`.
-    let page_alignment = crate::page_size() - 1;
+    let page_alignment = crate::runtime::vm::page_size() - 1;
     let slot_bytes = slot_bytes
         .checked_add(page_alignment)
         .and_then(|slot_bytes| Some(slot_bytes & !page_alignment))
@@ -752,7 +752,7 @@ fn calculate(constraints: &SlabConstraints) -> Result<SlabLayout> {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::PoolingInstanceAllocator;
+    use crate::runtime::vm::PoolingInstanceAllocator;
     use proptest::prelude::*;
 
     #[cfg(target_pointer_width = "64")]
@@ -838,7 +838,10 @@ mod tests {
             .iter()
             .map(|s| s.allocator.num_empty_slots())
             .sum();
-        assert_eq!(max_memory_slots, available_memory_slots.try_into().unwrap());
+        assert_eq!(
+            max_memory_slots,
+            u32::try_from(available_memory_slots).unwrap()
+        );
     }
 
     #[test]
@@ -991,6 +994,6 @@ mod tests {
     }
 
     fn is_aligned(bytes: usize) -> bool {
-        bytes % crate::page_size() == 0
+        bytes % crate::runtime::vm::page_size() == 0
     }
 }
diff --git a/crates/runtime/src/instance/allocator/pooling/table_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs
similarity index 95%
rename from crates/runtime/src/instance/allocator/pooling/table_pool.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs
index 3ffe42387..004b401e8 100644
--- a/crates/runtime/src/instance/allocator/pooling/table_pool.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs
@@ -2,8 +2,10 @@ use super::{
     index_allocator::{SimpleIndexAllocator, SlotId},
     round_up_to_pow2, TableAllocationIndex,
 };
-use crate::sys::vm::{commit_table_pages, decommit_table_pages};
-use crate::{InstanceAllocationRequest, Mmap, PoolingInstanceAllocatorConfig, SendSyncPtr, Table};
+use crate::runtime::vm::sys::vm::{commit_table_pages, decommit_table_pages};
+use crate::runtime::vm::{
+    InstanceAllocationRequest, Mmap, PoolingInstanceAllocatorConfig, SendSyncPtr, Table,
+};
 use anyhow::{anyhow, bail, Context, Result};
 use std::mem;
 use std::ptr::NonNull;
@@ -28,7 +30,7 @@ pub struct TablePool {
 impl TablePool {
     /// Create a new `TablePool`.
     pub fn new(config: &PoolingInstanceAllocatorConfig) -> Result<Self> {
-        let page_size = crate::page_size();
+        let page_size = crate::runtime::vm::page_size();
 
         let table_size = round_up_to_pow2(
             mem::size_of::<*mut u8>()
@@ -195,7 +197,7 @@ impl TablePool {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::InstanceLimits;
+    use crate::runtime::vm::InstanceLimits;
 
     #[cfg(target_pointer_width = "64")]
     #[test]
@@ -211,7 +213,7 @@ mod tests {
             ..Default::default()
         })?;
 
-        let host_page_size = crate::page_size();
+        let host_page_size = crate::runtime::vm::page_size();
 
         assert_eq!(pool.table_size, host_page_size);
         assert_eq!(pool.max_total_tables, 7);
diff --git a/crates/runtime/src/instance/allocator/pooling/unix_stack_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs
similarity index 96%
rename from crates/runtime/src/instance/allocator/pooling/unix_stack_pool.rs
rename to crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs
index ef9621ab4..6f30b505e 100644
--- a/crates/runtime/src/instance/allocator/pooling/unix_stack_pool.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs
@@ -4,8 +4,8 @@ use super::{
     index_allocator::{SimpleIndexAllocator, SlotId},
     round_up_to_pow2,
 };
-use crate::sys::vm::{commit_stack_pages, reset_stack_pages_to_zero};
-use crate::{Mmap, PoolingInstanceAllocatorConfig};
+use crate::runtime::vm::sys::vm::{commit_stack_pages, reset_stack_pages_to_zero};
+use crate::runtime::vm::{Mmap, PoolingInstanceAllocatorConfig};
 use anyhow::{anyhow, bail, Context, Result};
 
 /// Represents a pool of execution stacks (used for the async fiber implementation).
@@ -33,7 +33,7 @@ impl StackPool {
     pub fn new(config: &PoolingInstanceAllocatorConfig) -> Result<Self> {
         use rustix::mm::{mprotect, MprotectFlags};
 
-        let page_size = crate::page_size();
+        let page_size = crate::runtime::vm::page_size();
 
         // Add a page to the stack size for the guard page when using fiber stacks
         let stack_size = if config.stack_size == 0 {
@@ -178,7 +178,7 @@ impl StackPool {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::InstanceLimits;
+    use crate::runtime::vm::InstanceLimits;
 
     #[cfg(all(unix, target_pointer_width = "64", feature = "async", not(miri)))]
     #[test]
@@ -194,7 +194,7 @@ mod tests {
         };
         let pool = StackPool::new(&config)?;
 
-        let native_page_size = crate::page_size();
+        let native_page_size = crate::runtime::vm::page_size();
         assert_eq!(pool.stack_size, 2 * native_page_size);
         assert_eq!(pool.max_stacks, 10);
         assert_eq!(pool.page_size, native_page_size);
diff --git a/crates/runtime/src/libcalls.rs b/crates/wasmtime/src/runtime/vm/libcalls.rs
similarity index 98%
rename from crates/runtime/src/libcalls.rs
rename to crates/wasmtime/src/runtime/vm/libcalls.rs
index c2074eeee..cee1f3173 100644
--- a/crates/runtime/src/libcalls.rs
+++ b/crates/wasmtime/src/runtime/vm/libcalls.rs
@@ -19,7 +19,7 @@
 //!
 //! * The libcall must be entered via a Wasm-to-libcall trampoline that saves
 //!   the last Wasm FP and PC for stack walking purposes. (For more details, see
-//!   `crates/runtime/src/backtrace.rs`.)
+//!   `crates/wasmtime/src/runtime/vm/backtrace.rs`.)
 //!
 //! To make it easier to correctly handle all these things, **all** libcalls
 //! must be defined via the `libcall!` helper macro! See its doc comments below
@@ -54,9 +54,9 @@
 //! }
 //! ```
 
-use crate::table::{Table, TableElementType};
-use crate::vmcontext::VMFuncRef;
-use crate::{Instance, TrapReason, VMGcRef};
+use crate::runtime::vm::table::{Table, TableElementType};
+use crate::runtime::vm::vmcontext::VMFuncRef;
+use crate::runtime::vm::{Instance, TrapReason, VMGcRef};
 #[cfg(feature = "wmemcheck")]
 use anyhow::bail;
 use anyhow::Result;
@@ -87,7 +87,7 @@ pub mod raw {
     // between doc comments and `cfg`s.
     #![allow(unused_doc_comments, unused_attributes)]
 
-    use crate::{Instance, TrapReason, VMContext};
+    use crate::runtime::vm::{Instance, TrapReason, VMContext};
 
     macro_rules! libcall {
         (
@@ -110,7 +110,7 @@ pub mod raw {
                 ) $( -> libcall!(@ty $result))? {
                     $(#[cfg($attr)])?
                     {
-                        let ret = crate::traphandlers::catch_unwind_and_longjmp(|| {
+                        let ret = crate::runtime::vm::traphandlers::catch_unwind_and_longjmp(|| {
                             Instance::from_vmctx(vmctx, |instance| {
                                 {
                                     super::$name(instance, $($pname),*)
@@ -171,7 +171,7 @@ pub mod raw {
         unsafe fn convert(self) -> T {
             match self {
                 Ok(t) => t,
-                Err(e) => crate::traphandlers::raise_trap(e.into()),
+                Err(e) => crate::runtime::vm::traphandlers::raise_trap(e.into()),
             }
         }
     }
diff --git a/crates/runtime/src/memory.rs b/crates/wasmtime/src/runtime/vm/memory.rs
similarity index 98%
rename from crates/runtime/src/memory.rs
rename to crates/wasmtime/src/runtime/vm/memory.rs
index d0e5fd87a..6d1a246bc 100644
--- a/crates/runtime/src/memory.rs
+++ b/crates/wasmtime/src/runtime/vm/memory.rs
@@ -2,9 +2,11 @@
 //!
 //! `RuntimeLinearMemory` is to WebAssembly linear memories what `Table` is to WebAssembly tables.
 
-use crate::mmap::Mmap;
-use crate::vmcontext::VMMemoryDefinition;
-use crate::{MemoryImage, MemoryImageSlot, SendSyncPtr, SharedMemory, Store, WaitResult};
+use crate::runtime::vm::mmap::Mmap;
+use crate::runtime::vm::vmcontext::VMMemoryDefinition;
+use crate::runtime::vm::{
+    MemoryImage, MemoryImageSlot, SendSyncPtr, SharedMemory, Store, WaitResult,
+};
 use anyhow::Error;
 use anyhow::{bail, format_err, Result};
 use std::ops::Range;
@@ -607,16 +609,6 @@ impl Memory {
         self.0.byte_size()
     }
 
-    /// Returns the maximum number of pages the memory can grow to at runtime.
-    ///
-    /// Returns `None` if the memory is unbounded.
-    ///
-    /// The runtime maximum may not be equal to the maximum from the linear memory's
-    /// Wasm type when it is being constrained by an instance allocator.
-    pub fn maximum_byte_size(&self) -> Option<usize> {
-        self.0.maximum_byte_size()
-    }
-
     /// Returns whether or not this memory needs initialization. It
     /// may not if it already has initial content thanks to a CoW
     /// mechanism.
diff --git a/crates/runtime/src/mmap.rs b/crates/wasmtime/src/runtime/vm/mmap.rs
similarity index 95%
rename from crates/runtime/src/mmap.rs
rename to crates/wasmtime/src/runtime/vm/mmap.rs
index 4275cd68f..439b82057 100644
--- a/crates/runtime/src/mmap.rs
+++ b/crates/wasmtime/src/runtime/vm/mmap.rs
@@ -1,7 +1,7 @@
 //! Low-level abstraction for allocating and managing zero-filled pages
 //! of memory.
 
-use crate::sys::mmap;
+use crate::runtime::vm::sys::mmap;
 use anyhow::{Context, Result};
 use std::fs::File;
 use std::ops::Range;
@@ -20,7 +20,7 @@ impl Mmap {
     /// Create a new `Mmap` pointing to at least `size` bytes of page-aligned
     /// accessible memory.
     pub fn with_at_least(size: usize) -> Result<Self> {
-        let page_size = crate::page_size();
+        let page_size = crate::runtime::vm::page_size();
         let rounded_size = (size + (page_size - 1)) & !(page_size - 1);
         Self::accessible_reserved(rounded_size, rounded_size)
     }
@@ -51,7 +51,7 @@ impl Mmap {
     /// This function will panic if `accessible_size` is greater than
     /// `mapping_size` or if either of them are not page-aligned.
     pub fn accessible_reserved(accessible_size: usize, mapping_size: usize) -> Result<Self> {
-        let page_size = crate::page_size();
+        let page_size = crate::runtime::vm::page_size();
         assert!(accessible_size <= mapping_size);
         assert_eq!(mapping_size & (page_size - 1), 0);
         assert_eq!(accessible_size & (page_size - 1), 0);
@@ -91,7 +91,7 @@ impl Mmap {
     /// This function will panic if `start` or `len` is not page aligned or if
     /// either are outside the bounds of this mapping.
     pub fn make_accessible(&mut self, start: usize, len: usize) -> Result<()> {
-        let page_size = crate::page_size();
+        let page_size = crate::runtime::vm::page_size();
         assert_eq!(start & (page_size - 1), 0);
         assert_eq!(len & (page_size - 1), 0);
         assert!(len <= self.len());
@@ -180,7 +180,7 @@ impl Mmap {
         assert!(range.end <= self.len());
         assert!(range.start <= range.end);
         assert!(
-            range.start % crate::page_size() == 0,
+            range.start % crate::runtime::vm::page_size() == 0,
             "changing of protections isn't page-aligned",
         );
         self.sys
@@ -194,7 +194,7 @@ impl Mmap {
         assert!(range.end <= self.len());
         assert!(range.start <= range.end);
         assert!(
-            range.start % crate::page_size() == 0,
+            range.start % crate::runtime::vm::page_size() == 0,
             "changing of protections isn't page-aligned",
         );
         self.sys
diff --git a/crates/runtime/src/mmap_vec.rs b/crates/wasmtime/src/runtime/vm/mmap_vec.rs
similarity index 99%
rename from crates/runtime/src/mmap_vec.rs
rename to crates/wasmtime/src/runtime/vm/mmap_vec.rs
index 1b089fc03..c39c6accb 100644
--- a/crates/runtime/src/mmap_vec.rs
+++ b/crates/wasmtime/src/runtime/vm/mmap_vec.rs
@@ -1,4 +1,4 @@
-use crate::Mmap;
+use crate::runtime::vm::Mmap;
 use anyhow::{Context, Result};
 use std::fs::File;
 use std::ops::{Deref, DerefMut, Range};
diff --git a/crates/runtime/src/module_id.rs b/crates/wasmtime/src/runtime/vm/module_id.rs
similarity index 100%
rename from crates/runtime/src/module_id.rs
rename to crates/wasmtime/src/runtime/vm/module_id.rs
diff --git a/crates/runtime/src/mpk/disabled.rs b/crates/wasmtime/src/runtime/vm/mpk/disabled.rs
similarity index 100%
rename from crates/runtime/src/mpk/disabled.rs
rename to crates/wasmtime/src/runtime/vm/mpk/disabled.rs
diff --git a/crates/runtime/src/mpk/enabled.rs b/crates/wasmtime/src/runtime/vm/mpk/enabled.rs
similarity index 99%
rename from crates/runtime/src/mpk/enabled.rs
rename to crates/wasmtime/src/runtime/vm/mpk/enabled.rs
index 792b35de0..c6bd9af34 100644
--- a/crates/runtime/src/mpk/enabled.rs
+++ b/crates/wasmtime/src/runtime/vm/mpk/enabled.rs
@@ -144,7 +144,7 @@ impl ProtectionMask {
 #[cfg(test)]
 macro_rules! skip_if_mpk_unavailable {
     () => {
-        if !crate::mpk::is_supported() {
+        if !crate::runtime::vm::mpk::is_supported() {
             println!("> mpk is not supported: ignoring test");
             return;
         }
diff --git a/crates/runtime/src/mpk/mod.rs b/crates/wasmtime/src/runtime/vm/mpk/mod.rs
similarity index 97%
rename from crates/runtime/src/mpk/mod.rs
rename to crates/wasmtime/src/runtime/vm/mpk/mod.rs
index 55f822aa5..a5a65d3b7 100644
--- a/crates/runtime/src/mpk/mod.rs
+++ b/crates/wasmtime/src/runtime/vm/mpk/mod.rs
@@ -11,7 +11,7 @@
 //! a 2022 paper: [Segue and ColorGuard: Optimizing SFI Performance and
 //! Scalability on Modern x86][colorguard].
 //!
-//! [pooling allocator]: crate::PoolingInstanceAllocator
+//! [pooling allocator]: crate::runtime::vm::PoolingInstanceAllocator
 //! [Linux documentation]:
 //!     https://www.kernel.org/doc/html/latest/core-api/protection-keys.html
 //! [colorguard]: https://plas2022.github.io/files/pdf/SegueColorGuard.pdf
diff --git a/crates/runtime/src/mpk/pkru.rs b/crates/wasmtime/src/runtime/vm/mpk/pkru.rs
similarity index 98%
rename from crates/runtime/src/mpk/pkru.rs
rename to crates/wasmtime/src/runtime/vm/mpk/pkru.rs
index 0bb7f6321..acf017bec 100644
--- a/crates/runtime/src/mpk/pkru.rs
+++ b/crates/wasmtime/src/runtime/vm/mpk/pkru.rs
@@ -79,7 +79,7 @@ pub fn is_intel_cpu() -> bool {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::mpk::enabled::skip_if_mpk_unavailable;
+    use crate::runtime::vm::mpk::enabled::skip_if_mpk_unavailable;
 
     #[test]
     #[ignore = "cannot be run with other tests that munge the PKRU register"]
diff --git a/crates/runtime/src/mpk/sys.rs b/crates/wasmtime/src/runtime/vm/mpk/sys.rs
similarity index 99%
rename from crates/runtime/src/mpk/sys.rs
rename to crates/wasmtime/src/runtime/vm/mpk/sys.rs
index 671ea4eb9..acf503adf 100644
--- a/crates/runtime/src/mpk/sys.rs
+++ b/crates/wasmtime/src/runtime/vm/mpk/sys.rs
@@ -9,7 +9,7 @@
 //! [`pkey_mprotect`]: https://man7.org/linux/man-pages/man2/pkey_mprotect.2.html
 //! [`pkeys`]: https://man7.org/linux/man-pages/man7/pkeys.7.html
 
-use crate::page_size;
+use crate::runtime::vm::page_size;
 use anyhow::Result;
 use std::io::Error;
 
diff --git a/crates/runtime/src/send_sync_ptr.rs b/crates/wasmtime/src/runtime/vm/send_sync_ptr.rs
similarity index 100%
rename from crates/runtime/src/send_sync_ptr.rs
rename to crates/wasmtime/src/runtime/vm/send_sync_ptr.rs
diff --git a/crates/runtime/src/store_box.rs b/crates/wasmtime/src/runtime/vm/store_box.rs
similarity index 100%
rename from crates/runtime/src/store_box.rs
rename to crates/wasmtime/src/runtime/vm/store_box.rs
diff --git a/crates/runtime/src/sys/custom/capi.rs b/crates/wasmtime/src/runtime/vm/sys/custom/capi.rs
similarity index 100%
rename from crates/runtime/src/sys/custom/capi.rs
rename to crates/wasmtime/src/runtime/vm/sys/custom/capi.rs
diff --git a/crates/runtime/src/sys/custom/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/custom/mmap.rs
similarity index 97%
rename from crates/runtime/src/sys/custom/mmap.rs
rename to crates/wasmtime/src/runtime/vm/sys/custom/mmap.rs
index b457cdfc8..69d3f20aa 100644
--- a/crates/runtime/src/sys/custom/mmap.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/custom/mmap.rs
@@ -1,6 +1,6 @@
 use super::cvt;
-use crate::sys::capi;
-use crate::SendSyncPtr;
+use crate::runtime::vm::sys::capi;
+use crate::runtime::vm::SendSyncPtr;
 use anyhow::{bail, Result};
 use std::fs::File;
 use std::ops::Range;
diff --git a/crates/runtime/src/sys/custom/mod.rs b/crates/wasmtime/src/runtime/vm/sys/custom/mod.rs
similarity index 100%
rename from crates/runtime/src/sys/custom/mod.rs
rename to crates/wasmtime/src/runtime/vm/sys/custom/mod.rs
diff --git a/crates/runtime/src/sys/custom/traphandlers.rs b/crates/wasmtime/src/runtime/vm/sys/custom/traphandlers.rs
similarity index 90%
rename from crates/runtime/src/sys/custom/traphandlers.rs
rename to crates/wasmtime/src/runtime/vm/sys/custom/traphandlers.rs
index 65ea6afe5..c48f09b71 100644
--- a/crates/runtime/src/sys/custom/traphandlers.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/custom/traphandlers.rs
@@ -1,8 +1,8 @@
-use crate::traphandlers::{tls, TrapTest};
-use crate::VMContext;
+use crate::runtime::vm::traphandlers::{tls, TrapTest};
+use crate::runtime::vm::VMContext;
 use std::mem;
 
-pub use crate::sys::capi::{self, wasmtime_longjmp};
+pub use crate::runtime::vm::sys::capi::{self, wasmtime_longjmp};
 
 #[allow(missing_docs)]
 pub type SignalHandler<'a> = dyn Fn() + Send + Sync + 'a;
diff --git a/crates/runtime/src/sys/custom/unwind.rs b/crates/wasmtime/src/runtime/vm/sys/custom/unwind.rs
similarity index 100%
rename from crates/runtime/src/sys/custom/unwind.rs
rename to crates/wasmtime/src/runtime/vm/sys/custom/unwind.rs
diff --git a/crates/runtime/src/sys/custom/vm.rs b/crates/wasmtime/src/runtime/vm/sys/custom/vm.rs
similarity index 97%
rename from crates/runtime/src/sys/custom/vm.rs
rename to crates/wasmtime/src/runtime/vm/sys/custom/vm.rs
index e9785b781..530f47157 100644
--- a/crates/runtime/src/sys/custom/vm.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/custom/vm.rs
@@ -1,6 +1,6 @@
 use super::cvt;
-use crate::sys::capi;
-use crate::SendSyncPtr;
+use crate::runtime::vm::sys::capi;
+use crate::runtime::vm::SendSyncPtr;
 use std::fs::File;
 use std::io;
 use std::ptr::{self, NonNull};
diff --git a/crates/runtime/src/sys/miri/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/miri/mmap.rs
similarity index 90%
rename from crates/runtime/src/sys/miri/mmap.rs
rename to crates/wasmtime/src/runtime/vm/sys/miri/mmap.rs
index 6b4cb413e..2796e1fa5 100644
--- a/crates/runtime/src/sys/miri/mmap.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/miri/mmap.rs
@@ -5,7 +5,7 @@
 //! like becoming executable or becoming readonly or being created from files,
 //! but it's enough to get various tests running relying on memories and such.
 
-use crate::SendSyncPtr;
+use crate::runtime::vm::SendSyncPtr;
 use anyhow::{bail, Result};
 use std::alloc::{self, Layout};
 use std::fs::File;
@@ -32,7 +32,7 @@ impl Mmap {
     }
 
     pub fn reserve(size: usize) -> Result<Self> {
-        let layout = Layout::from_size_align(size, crate::page_size()).unwrap();
+        let layout = Layout::from_size_align(size, crate::runtime::vm::page_size()).unwrap();
         let ptr = unsafe { alloc::alloc(layout) };
         if ptr.is_null() {
             bail!("failed to allocate memory");
@@ -87,7 +87,8 @@ impl Drop for Mmap {
             return;
         }
         unsafe {
-            let layout = Layout::from_size_align(self.len(), crate::page_size()).unwrap();
+            let layout =
+                Layout::from_size_align(self.len(), crate::runtime::vm::page_size()).unwrap();
             alloc::dealloc(self.as_mut_ptr(), layout);
         }
     }
diff --git a/crates/runtime/src/sys/miri/mod.rs b/crates/wasmtime/src/runtime/vm/sys/miri/mod.rs
similarity index 100%
rename from crates/runtime/src/sys/miri/mod.rs
rename to crates/wasmtime/src/runtime/vm/sys/miri/mod.rs
diff --git a/crates/runtime/src/sys/miri/traphandlers.rs b/crates/wasmtime/src/runtime/vm/sys/miri/traphandlers.rs
similarity index 96%
rename from crates/runtime/src/sys/miri/traphandlers.rs
rename to crates/wasmtime/src/runtime/vm/sys/miri/traphandlers.rs
index dffbd25f9..00e22fc55 100644
--- a/crates/runtime/src/sys/miri/traphandlers.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/miri/traphandlers.rs
@@ -4,7 +4,7 @@
 // Note that no actual JIT code runs in MIRI so this is purely here for
 // host-to-host calls.
 
-use crate::VMContext;
+use crate::runtime::vm::VMContext;
 
 struct WasmtimeLongjmp;
 
diff --git a/crates/runtime/src/sys/miri/unwind.rs b/crates/wasmtime/src/runtime/vm/sys/miri/unwind.rs
similarity index 100%
rename from crates/runtime/src/sys/miri/unwind.rs
rename to crates/wasmtime/src/runtime/vm/sys/miri/unwind.rs
diff --git a/crates/runtime/src/sys/miri/vm.rs b/crates/wasmtime/src/runtime/vm/sys/miri/vm.rs
similarity index 100%
rename from crates/runtime/src/sys/miri/vm.rs
rename to crates/wasmtime/src/runtime/vm/sys/miri/vm.rs
diff --git a/crates/runtime/src/sys/mod.rs b/crates/wasmtime/src/runtime/vm/sys/mod.rs
similarity index 100%
rename from crates/runtime/src/sys/mod.rs
rename to crates/wasmtime/src/runtime/vm/sys/mod.rs
diff --git a/crates/runtime/src/sys/unix/machports.rs b/crates/wasmtime/src/runtime/vm/sys/unix/machports.rs
similarity index 98%
rename from crates/runtime/src/sys/unix/machports.rs
rename to crates/wasmtime/src/runtime/vm/sys/unix/machports.rs
index 83a4c5037..113f5b722 100644
--- a/crates/runtime/src/sys/unix/machports.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/unix/machports.rs
@@ -33,8 +33,8 @@
 
 #![allow(non_snake_case, clippy::cast_sign_loss)]
 
-use crate::sys::traphandlers::wasmtime_longjmp;
-use crate::traphandlers::tls;
+use crate::runtime::vm::sys::traphandlers::wasmtime_longjmp;
+use crate::runtime::vm::traphandlers::tls;
 use mach2::exc::*;
 use mach2::exception_types::*;
 use mach2::kern_return::*;
@@ -325,7 +325,7 @@ unsafe fn handle_exception(request: &mut ExceptionRequest) -> bool {
     // pointer value and if `MAP` changes happen after we read our entry that's
     // ok since they won't invalidate our entry.
     let (pc, fp) = get_pc_and_fp(&thread_state);
-    let trap = match crate::traphandlers::GET_WASM_TRAP(pc as usize) {
+    let trap = match crate::runtime::vm::traphandlers::GET_WASM_TRAP(pc as usize) {
         Some(trap) => trap,
         None => return false,
     };
diff --git a/crates/runtime/src/sys/unix/macos_traphandlers.rs b/crates/wasmtime/src/runtime/vm/sys/unix/macos_traphandlers.rs
similarity index 100%
rename from crates/runtime/src/sys/unix/macos_traphandlers.rs
rename to crates/wasmtime/src/runtime/vm/sys/unix/macos_traphandlers.rs
diff --git a/crates/runtime/src/sys/unix/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs
similarity index 99%
rename from crates/runtime/src/sys/unix/mmap.rs
rename to crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs
index acce400a9..ec3b06b34 100644
--- a/crates/runtime/src/sys/unix/mmap.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/unix/mmap.rs
@@ -1,4 +1,4 @@
-use crate::SendSyncPtr;
+use crate::runtime::vm::SendSyncPtr;
 use anyhow::{anyhow, Context, Result};
 use rustix::mm::{mprotect, MprotectFlags};
 use std::fs::File;
diff --git a/crates/runtime/src/sys/unix/mod.rs b/crates/wasmtime/src/runtime/vm/sys/unix/mod.rs
similarity index 100%
rename from crates/runtime/src/sys/unix/mod.rs
rename to crates/wasmtime/src/runtime/vm/sys/unix/mod.rs
diff --git a/crates/runtime/src/sys/unix/signals.rs b/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs
similarity index 99%
rename from crates/runtime/src/sys/unix/signals.rs
rename to crates/wasmtime/src/runtime/vm/sys/unix/signals.rs
index 45961a0ea..44634476e 100644
--- a/crates/runtime/src/sys/unix/signals.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs
@@ -1,7 +1,7 @@
 //! Trap handling on Unix based on POSIX signals.
 
-use crate::traphandlers::{tls, TrapTest};
-use crate::VMContext;
+use crate::runtime::vm::traphandlers::{tls, TrapTest};
+use crate::runtime::vm::VMContext;
 use std::cell::RefCell;
 use std::io;
 use std::mem::{self, MaybeUninit};
@@ -349,7 +349,7 @@ pub fn lazy_per_thread_init() {
 
         // ... but failing that we need to allocate our own, so do all that
         // here.
-        let page_size = crate::page_size();
+        let page_size = crate::runtime::vm::page_size();
         let guard_size = page_size;
         let alloc_size = guard_size + MIN_STACK_SIZE;
 
diff --git a/crates/runtime/src/sys/unix/unwind.rs b/crates/wasmtime/src/runtime/vm/sys/unix/unwind.rs
similarity index 98%
rename from crates/runtime/src/sys/unix/unwind.rs
rename to crates/wasmtime/src/runtime/vm/sys/unix/unwind.rs
index 86c8993f3..96cd79d46 100644
--- a/crates/runtime/src/sys/unix/unwind.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/unix/unwind.rs
@@ -1,6 +1,6 @@
 //! Module for System V ABI unwind registry.
 
-use crate::SendSyncPtr;
+use crate::runtime::vm::SendSyncPtr;
 use anyhow::Result;
 use std::ptr::{self, NonNull};
 use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
@@ -88,7 +88,7 @@ impl UnwindRegistration {
         unwind_len: usize,
     ) -> Result<UnwindRegistration> {
         debug_assert_eq!(
-            unwind_info as usize % crate::page_size(),
+            unwind_info as usize % crate::runtime::vm::page_size(),
             0,
             "The unwind info must always be aligned to a page"
         );
diff --git a/crates/runtime/src/sys/unix/vm.rs b/crates/wasmtime/src/runtime/vm/sys/unix/vm.rs
similarity index 100%
rename from crates/runtime/src/sys/unix/vm.rs
rename to crates/wasmtime/src/runtime/vm/sys/unix/vm.rs
diff --git a/crates/runtime/src/sys/windows/mmap.rs b/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs
similarity index 99%
rename from crates/runtime/src/sys/windows/mmap.rs
rename to crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs
index 42142dfa0..6dc3e61dd 100644
--- a/crates/runtime/src/sys/windows/mmap.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/windows/mmap.rs
@@ -1,4 +1,4 @@
-use crate::SendSyncPtr;
+use crate::runtime::vm::SendSyncPtr;
 use anyhow::{anyhow, bail, Context, Result};
 use std::fs::{File, OpenOptions};
 use std::io;
diff --git a/crates/runtime/src/sys/windows/mod.rs b/crates/wasmtime/src/runtime/vm/sys/windows/mod.rs
similarity index 100%
rename from crates/runtime/src/sys/windows/mod.rs
rename to crates/wasmtime/src/runtime/vm/sys/windows/mod.rs
diff --git a/crates/runtime/src/sys/windows/traphandlers.rs b/crates/wasmtime/src/runtime/vm/sys/windows/traphandlers.rs
similarity index 97%
rename from crates/runtime/src/sys/windows/traphandlers.rs
rename to crates/wasmtime/src/runtime/vm/sys/windows/traphandlers.rs
index 6563d3986..87159e065 100644
--- a/crates/runtime/src/sys/windows/traphandlers.rs
+++ b/crates/wasmtime/src/runtime/vm/sys/windows/traphandlers.rs
@@ -1,5 +1,5 @@
-use crate::traphandlers::{tls, TrapTest};
-use crate::VMContext;
+use crate::runtime::vm::traphandlers::{tls, TrapTest};
+use crate::runtime::vm::VMContext;
 use std::io;
 use windows_sys::Win32::Foundation::*;
 use windows_sys::Win32::System::Diagnostics::Debug::*;
diff --git a/crates/runtime/src/sys/windows/unwind.rs b/crates/wasmtime/src/runtime/vm/sys/windows/unwind.rs
similarity index 100%
rename from crates/runtime/src/sys/windows/unwind.rs
rename to crates/wasmtime/src/runtime/vm/sys/windows/unwind.rs
diff --git a/crates/runtime/src/sys/windows/vm.rs b/crates/wasmtime/src/runtime/vm/sys/windows/vm.rs
similarity index 100%
rename from crates/runtime/src/sys/windows/vm.rs
rename to crates/wasmtime/src/runtime/vm/sys/windows/vm.rs
diff --git a/crates/runtime/src/table.rs b/crates/wasmtime/src/runtime/vm/table.rs
similarity index 99%
rename from crates/runtime/src/table.rs
rename to crates/wasmtime/src/runtime/vm/table.rs
index 20c94f64e..f38f9f369 100644
--- a/crates/runtime/src/table.rs
+++ b/crates/wasmtime/src/runtime/vm/table.rs
@@ -4,8 +4,8 @@
 
 #![cfg_attr(feature = "gc", allow(irrefutable_let_patterns))]
 
-use crate::vmcontext::{VMFuncRef, VMTableDefinition};
-use crate::{GcStore, SendSyncPtr, Store, VMGcRef};
+use crate::runtime::vm::vmcontext::{VMFuncRef, VMTableDefinition};
+use crate::runtime::vm::{GcStore, SendSyncPtr, Store, VMGcRef};
 use anyhow::{bail, ensure, format_err, Error, Result};
 use sptr::Strict;
 use std::ops::Range;
diff --git a/crates/runtime/src/threads/mod.rs b/crates/wasmtime/src/runtime/vm/threads/mod.rs
similarity index 100%
rename from crates/runtime/src/threads/mod.rs
rename to crates/wasmtime/src/runtime/vm/threads/mod.rs
diff --git a/crates/runtime/src/threads/parking_spot.rs b/crates/wasmtime/src/runtime/vm/threads/parking_spot.rs
similarity index 99%
rename from crates/runtime/src/threads/parking_spot.rs
rename to crates/wasmtime/src/runtime/vm/threads/parking_spot.rs
index fca5cf192..1263f651a 100644
--- a/crates/runtime/src/threads/parking_spot.rs
+++ b/crates/wasmtime/src/runtime/vm/threads/parking_spot.rs
@@ -11,7 +11,7 @@
 
 #![deny(missing_docs)]
 
-use crate::{SendSyncPtr, WaitResult};
+use crate::runtime::vm::{SendSyncPtr, WaitResult};
 use std::collections::BTreeMap;
 use std::ptr::NonNull;
 use std::sync::atomic::{AtomicU32, AtomicU64, Ordering::SeqCst};
@@ -555,7 +555,7 @@ mod tests {
                         .spot
                         .wait32(&self.semaphore, old_semaphore_value, None, &mut waiter)
                     {
-                        crate::WaitResult::Mismatch => {}
+                        crate::runtime::vm::WaitResult::Mismatch => {}
                         _ => break,
                     }
                     old_semaphore_value = self.semaphore.load(Ordering::SeqCst);
diff --git a/crates/runtime/src/threads/shared_memory.rs b/crates/wasmtime/src/runtime/vm/threads/shared_memory.rs
similarity index 97%
rename from crates/runtime/src/threads/shared_memory.rs
rename to crates/wasmtime/src/runtime/vm/threads/shared_memory.rs
index 0837d1530..4561ae45e 100644
--- a/crates/runtime/src/threads/shared_memory.rs
+++ b/crates/wasmtime/src/runtime/vm/threads/shared_memory.rs
@@ -1,7 +1,7 @@
-use crate::memory::{validate_atomic_addr, MmapMemory};
-use crate::threads::parking_spot::{ParkingSpot, Waiter};
-use crate::vmcontext::VMMemoryDefinition;
-use crate::{Memory, RuntimeLinearMemory, Store, WaitResult};
+use crate::runtime::vm::memory::{validate_atomic_addr, MmapMemory};
+use crate::runtime::vm::threads::parking_spot::{ParkingSpot, Waiter};
+use crate::runtime::vm::vmcontext::VMMemoryDefinition;
+use crate::runtime::vm::{Memory, RuntimeLinearMemory, Store, WaitResult};
 use anyhow::Error;
 use anyhow::{bail, Result};
 use std::cell::RefCell;
diff --git a/crates/runtime/src/threads/shared_memory_disabled.rs b/crates/wasmtime/src/runtime/vm/threads/shared_memory_disabled.rs
similarity index 93%
rename from crates/runtime/src/threads/shared_memory_disabled.rs
rename to crates/wasmtime/src/runtime/vm/threads/shared_memory_disabled.rs
index f102444c4..4e106d25c 100644
--- a/crates/runtime/src/threads/shared_memory_disabled.rs
+++ b/crates/wasmtime/src/runtime/vm/threads/shared_memory_disabled.rs
@@ -1,6 +1,6 @@
 #![allow(missing_docs)]
 
-use crate::{RuntimeLinearMemory, Store, VMMemoryDefinition, WaitResult};
+use crate::runtime::vm::{RuntimeLinearMemory, Store, VMMemoryDefinition, WaitResult};
 use anyhow::{bail, Result};
 use std::ops::Range;
 use std::time::Instant;
@@ -22,7 +22,7 @@ impl SharedMemory {
         match *self {}
     }
 
-    pub fn as_memory(self) -> crate::Memory {
+    pub fn as_memory(self) -> crate::runtime::vm::Memory {
         match self {}
     }
 
diff --git a/crates/runtime/src/traphandlers.rs b/crates/wasmtime/src/runtime/vm/traphandlers.rs
similarity index 96%
rename from crates/runtime/src/traphandlers.rs
rename to crates/wasmtime/src/runtime/vm/traphandlers.rs
index 8acfef727..4aa02cef3 100644
--- a/crates/runtime/src/traphandlers.rs
+++ b/crates/wasmtime/src/runtime/vm/traphandlers.rs
@@ -10,15 +10,15 @@ mod coredump;
 #[path = "traphandlers/coredump_disabled.rs"]
 mod coredump;
 
-use crate::sys::traphandlers;
-use crate::{Instance, VMContext, VMRuntimeLimits};
+use crate::runtime::vm::sys::traphandlers;
+use crate::runtime::vm::{Instance, VMContext, VMRuntimeLimits};
 use anyhow::Error;
 use std::cell::{Cell, UnsafeCell};
 use std::mem::MaybeUninit;
 use std::ptr;
 use std::sync::Once;
 
-pub use self::backtrace::{Backtrace, Frame};
+pub use self::backtrace::Backtrace;
 pub use self::coredump::CoreDumpStack;
 pub use self::tls::{tls_eager_initialize, AsyncWasmCallState, PreviousAsyncWasmCallState};
 
@@ -99,20 +99,6 @@ pub unsafe fn raise_user_trap(error: Error, needs_backtrace: bool) -> ! {
     })
 }
 
-/// Raises a trap from inside library code immediately.
-///
-/// This function performs as-if a wasm trap was just executed. This trap
-/// payload is then returned from `catch_traps` below.
-///
-/// # Safety
-///
-/// Only safe to call when wasm code is on the stack, aka `catch_traps` must
-/// have been previously called. Additionally no Rust destructors can be on the
-/// stack. They will be skipped and not executed.
-pub unsafe fn raise_lib_trap(trap: wasmtime_environ::Trap) -> ! {
-    raise_trap(TrapReason::Wasm(trap))
-}
-
 /// Invokes the closure `f` and returns the result.
 ///
 /// If `f` panics and this crate is compiled with `panic=unwind` this will
@@ -203,19 +189,6 @@ impl TrapReason {
             needs_backtrace: true,
         }
     }
-
-    /// Create a new `TrapReason::User` that already has a backtrace.
-    pub fn user_with_backtrace(error: Error) -> Self {
-        TrapReason::User {
-            error,
-            needs_backtrace: false,
-        }
-    }
-
-    /// Is this a JIT trap?
-    pub fn is_jit(&self) -> bool {
-        matches!(self, TrapReason::Jit { .. })
-    }
 }
 
 impl From<Error> for TrapReason {
diff --git a/crates/runtime/src/traphandlers/backtrace.rs b/crates/wasmtime/src/runtime/vm/traphandlers/backtrace.rs
similarity index 97%
rename from crates/runtime/src/traphandlers/backtrace.rs
rename to crates/wasmtime/src/runtime/vm/traphandlers/backtrace.rs
index 4cab189dc..a33757b22 100644
--- a/crates/runtime/src/traphandlers/backtrace.rs
+++ b/crates/wasmtime/src/runtime/vm/traphandlers/backtrace.rs
@@ -10,9 +10,10 @@
 //! To perform (1) we maintain the entry stack pointer (SP) and exit frame
 //! pointer (FP) and program counter (PC) each time we call into Wasm and Wasm
 //! calls into the host via trampolines (see
-//! `crates/runtime/src/trampolines`). The most recent entry is stored in
-//! `VMRuntimeLimits` and older entries are saved in `CallThreadState`. This
-//! lets us identify ranges of contiguous Wasm frames on the stack.
+//! `crates/wasmtime/src/runtime/vm/trampolines`). The most recent entry is
+//! stored in `VMRuntimeLimits` and older entries are saved in
+//! `CallThreadState`. This lets us identify ranges of contiguous Wasm frames on
+//! the stack.
 //!
 //! To solve (2) and walk the Wasm frames within a region of contiguous Wasm
 //! frames on the stack, we configure Cranelift's `preserve_frame_pointers =
@@ -20,8 +21,8 @@
 //! exit FP and stopping once we reach the entry SP (meaning that the next older
 //! frame is a host frame).
 
-use crate::arch;
-use crate::{
+use crate::runtime::vm::arch;
+use crate::runtime::vm::{
     traphandlers::{tls, CallThreadState},
     VMRuntimeLimits,
 };
diff --git a/crates/runtime/src/traphandlers/coredump_disabled.rs b/crates/wasmtime/src/runtime/vm/traphandlers/coredump_disabled.rs
similarity index 75%
rename from crates/runtime/src/traphandlers/coredump_disabled.rs
rename to crates/wasmtime/src/runtime/vm/traphandlers/coredump_disabled.rs
index 3a203ce61..d4dc86a1d 100644
--- a/crates/runtime/src/traphandlers/coredump_disabled.rs
+++ b/crates/wasmtime/src/runtime/vm/traphandlers/coredump_disabled.rs
@@ -1,5 +1,5 @@
-use crate::traphandlers::CallThreadState;
-use crate::VMRuntimeLimits;
+use crate::runtime::vm::traphandlers::CallThreadState;
+use crate::runtime::vm::VMRuntimeLimits;
 
 /// A WebAssembly Coredump
 #[derive(Debug)]
diff --git a/crates/runtime/src/traphandlers/coredump_enabled.rs b/crates/wasmtime/src/runtime/vm/traphandlers/coredump_enabled.rs
similarity index 76%
rename from crates/runtime/src/traphandlers/coredump_enabled.rs
rename to crates/wasmtime/src/runtime/vm/traphandlers/coredump_enabled.rs
index d60fd6458..21acb1224 100644
--- a/crates/runtime/src/traphandlers/coredump_enabled.rs
+++ b/crates/wasmtime/src/runtime/vm/traphandlers/coredump_enabled.rs
@@ -1,6 +1,6 @@
 use wasm_encoder::CoreDumpValue;
 
-use crate::{Backtrace, VMRuntimeLimits};
+use crate::runtime::vm::{Backtrace, VMRuntimeLimits};
 
 use super::CallThreadState;
 
@@ -10,13 +10,16 @@ pub struct CoreDumpStack {
     /// The backtrace containing the stack frames for the CoreDump
     pub bt: Backtrace,
 
-    /// Unimplemented
-    /// The indices of the locals and operand_stack all map to each other (ie.
-    /// index 0 is the locals for the first frame in the backtrace, etc)
+    /// The locals for each frame in the backtrace.
+    ///
+    /// This is not currently implemented.
+    #[allow(dead_code)]
     pub locals: Vec<Vec<CoreDumpValue>>,
 
-    /// Unimplemented
     /// The operands for each stack frame
+    ///
+    /// This is not currently implemented.
+    #[allow(dead_code)]
     pub operand_stack: Vec<Vec<CoreDumpValue>>,
 }
 
diff --git a/crates/runtime/src/vmcontext.rs b/crates/wasmtime/src/runtime/vm/vmcontext.rs
similarity index 97%
rename from crates/runtime/src/vmcontext.rs
rename to crates/wasmtime/src/runtime/vm/vmcontext.rs
index 718586229..04ce80439 100644
--- a/crates/runtime/src/vmcontext.rs
+++ b/crates/wasmtime/src/runtime/vm/vmcontext.rs
@@ -3,7 +3,7 @@
 
 mod vm_host_func_context;
 
-use crate::{GcStore, VMGcRef};
+use crate::runtime::vm::{GcStore, VMGcRef};
 use sptr::Strict;
 use std::cell::UnsafeCell;
 use std::ffi::c_void;
@@ -426,7 +426,7 @@ mod test_vmglobal_definition {
     #[test]
     #[cfg(feature = "gc")]
     fn check_vmglobal_can_contain_gc_ref() {
-        assert!(size_of::<crate::VMGcRef>() <= size_of::<VMGlobalDefinition>());
+        assert!(size_of::<crate::runtime::vm::VMGcRef>() <= size_of::<VMGlobalDefinition>());
     }
 }
 
@@ -750,7 +750,7 @@ macro_rules! define_builtin_array {
             #[allow(unused_doc_comments)]
             pub const INIT: VMBuiltinFunctionsArray = VMBuiltinFunctionsArray {
                 $(
-                    $name: crate::libcalls::raw::$name,
+                    $name: crate::runtime::vm::libcalls::raw::$name,
                 )*
             };
         }
@@ -773,42 +773,6 @@ const _: () = {
     )
 };
 
-/// The storage for a WebAssembly invocation argument
-///
-/// TODO: These could be packed more densely, rather than using the same size for every type.
-#[derive(Debug, Copy, Clone)]
-#[repr(C, align(16))]
-pub struct VMInvokeArgument([u8; 16]);
-
-#[cfg(test)]
-mod test_vm_invoke_argument {
-    use super::VMInvokeArgument;
-    use std::mem::{align_of, size_of};
-    use wasmtime_environ::{Module, PtrSize, VMOffsets};
-
-    #[test]
-    fn check_vm_invoke_argument_alignment() {
-        assert_eq!(align_of::<VMInvokeArgument>(), 16);
-    }
-
-    #[test]
-    fn check_vmglobal_definition_offsets() {
-        let module = Module::new();
-        let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
-        assert_eq!(
-            size_of::<VMInvokeArgument>(),
-            usize::from(offsets.ptr.size_of_vmglobal_definition())
-        );
-    }
-}
-
-impl VMInvokeArgument {
-    /// Create a new invocation argument filled with zeroes
-    pub fn new() -> Self {
-        Self([0; 16])
-    }
-}
-
 /// Structure used to control interrupting wasm code.
 #[derive(Debug)]
 #[repr(C)]
@@ -908,7 +872,7 @@ mod test_vmruntime_limits {
         let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
         assert_eq!(
             offsets.vmctx_runtime_limits(),
-            offsets.ptr.vmcontext_runtime_limits().into()
+            u32::from(offsets.ptr.vmcontext_runtime_limits())
         );
     }
 
diff --git a/crates/runtime/src/vmcontext/vm_host_func_context.rs b/crates/wasmtime/src/runtime/vm/vmcontext/vm_host_func_context.rs
similarity index 98%
rename from crates/runtime/src/vmcontext/vm_host_func_context.rs
rename to crates/wasmtime/src/runtime/vm/vmcontext/vm_host_func_context.rs
index 547e3dcac..2876a3746 100644
--- a/crates/runtime/src/vmcontext/vm_host_func_context.rs
+++ b/crates/wasmtime/src/runtime/vm/vmcontext/vm_host_func_context.rs
@@ -3,7 +3,7 @@
 //! Keep in sync with `wasmtime_environ::VMHostFuncOffsets`.
 
 use super::VMOpaqueContext;
-use crate::{StoreBox, VMFuncRef};
+use crate::runtime::vm::{StoreBox, VMFuncRef};
 use std::any::Any;
 use wasmtime_environ::{VM_ARRAY_CALL_HOST_FUNC_MAGIC, VM_NATIVE_CALL_HOST_FUNC_MAGIC};
 
diff --git a/docs/WASI-tutorial.md b/docs/WASI-tutorial.md
index c2702febc..b419c6eb7 100644
--- a/docs/WASI-tutorial.md
+++ b/docs/WASI-tutorial.md
@@ -10,11 +10,11 @@ this using the `wasmtime` runtime.
     - [Compiling to WASI](#compiling-to-wasi)
         - [From C](#from-c)
         - [From Rust](#from-rust)
-    - [Executing in `wasmtime` runtime](#executing-in-wasmtime-runtime)
+    - [Executing in Wasmtime](#executing-in-wasmtime)
   - [Web assembly text example](#web-assembly-text-example)
 
 ## Running common languages with WASI
-## Compiling to WASI
+### Compiling to WASI
 #### From C
 Let's start with a simple C program which performs a file copy, which will
 show to compile and run programs, as well as perform simple sandbox
@@ -165,7 +165,7 @@ $ file target/wasm32-wasi/debug/demo.wasm
 demo.wasm: WebAssembly (wasm) binary module version 0x1 (MVP)
 ```
 
-## Executing in `wasmtime` runtime
+### Executing in Wasmtime
 The resultant WebAssembly module `demo.wasm` compiled either from C or Rust is simply
 a single file containing a self-contained wasm module, that doesn't require
 any supporting JS code.
diff --git a/docs/contributing-architecture.md b/docs/contributing-architecture.md
index 294a5ad5e..a2d6bc288 100644
--- a/docs/contributing-architecture.md
+++ b/docs/contributing-architecture.md
@@ -63,7 +63,7 @@ their implications in Wasmtime:
   other. A `Store` cannot be used simultaneously from multiple threads (almost
   all operations require `&mut self`).
 
-* `wasmtime_runtime::InstanceHandle` - this is the low-level representation of a
+* `wasmtime::runtime::vm::InstanceHandle` - this is the low-level representation of a
   WebAssembly instance. At the same time this is also used as the representation
   for all host-defined objects. For example if you call `wasmtime::Memory::new`
   it'll create an `InstanceHandle` under the hood. This is a very `unsafe` type
@@ -82,13 +82,13 @@ their implications in Wasmtime:
   `wasmtime::Table::new`), but for an instantiated WebAssembly module these
   fields will have more information. After an `InstanceHandle` in memory is a
   `VMContext`, which will be discussed next. `InstanceHandle` values are the
-  main internal runtime representation and what the `wasmtime_runtime` crate
+  main internal runtime representation and what the `crate::runtime::vm` code
   works with. The `wasmtime::Store` holds onto all these `InstanceHandle` values
   and deallocates them at the appropriate time. From the runtime perspective it
   simplifies things so the graph of wasm modules communicating to each other is
   reduced to simply `InstanceHandle` values all talking to themselves.
 
-* `wasmtime_runtime::VMContext` - this is a raw pointer, within an allocation of
+* `crate::runtime::vm::VMContext` - this is a raw pointer, within an allocation of
   an `InstanceHandle`, that is passed around in JIT code. A `VMContext` does not
   have a structure defined in Rust (it's a 0-sized structure) because its
   contents are dynamically determined based on the `VMOffsets`, or the source
@@ -111,7 +111,7 @@ their implications in Wasmtime:
     stack overflow.
   * Hold a pointer to a `VMExternRefActivationsTable` for fast-path insertion of
     `externref` values into the table.
-  * Hold a pointer to a `*mut dyn wasmtime_runtime::Store` so store-level
+  * Hold a pointer to a `*mut dyn crate::runtime::vm::Store` so store-level
     operations can be performed in libcalls.
 
   A comment about the layout of a `VMContext` can be found in the `vmoffsets.rs`
@@ -268,11 +268,11 @@ The rough flow of instantiation looks like:
    completed before instantiation is finished. For MVP wasm this only involves
    loading the import into the correct index array, but for module linking this
    could involve instantiating other modules, handling `alias` fields, etc. In
-   any case the result of this step is a `wasmtime_runtime::Imports` array which
-   has the values for all imported items into the wasm module. Note that in
-   this case an import is typically some sort of raw pointer to the actual
-   state plus the `VMContext` of the instance that was imported from. The
-   final result of this step is an `InstanceAllocationRequest`, which is then
+   any case the result of this step is a `crate::runtime::vm::Imports` array
+   which has the values for all imported items into the wasm module. Note that
+   in this case an import is typically some sort of raw pointer to the actual
+   state plus the `VMContext` of the instance that was imported from. The final
+   result of this step is an `InstanceAllocationRequest`, which is then
    submitted to the configured instance allocator, either on-demand or pooling.
 
 3. The `InstanceHandle` corresponding to this instance is allocated. How this
@@ -315,11 +315,11 @@ traps.
 Wasmtime today implements traps with `longjmp` and `setjmp`. The `setjmp`
 function cannot be defined in Rust (even unsafely --
 (https://github.com/rust-lang/rfcs/issues/2625) so the
-`crates/runtime/src/helpers.c` file actually calls setjmp/longjmp. Note that in
-general the operation of `longjmp` is not safe to execute in Rust because it
-skips stack-based destructors, so after `setjmp` when we call back into Rust to
-execute wasm we need to be careful in Wasmtime to not have any significant
-destructors on the stack once wasm is called.
+`crates/wasmtime/src/runtime/vm/helpers.c` file actually calls
+setjmp/longjmp. Note that in general the operation of `longjmp` is not safe to
+execute in Rust because it skips stack-based destructors, so after `setjmp` when
+we call back into Rust to execute wasm we need to be careful in Wasmtime to not
+have any significant destructors on the stack once wasm is called.
 
 Traps can happen from a few different sources:
 
@@ -457,10 +457,9 @@ values that are actively in use on the stack.
 The main Wasmtime internal crates are:
 
 * `wasmtime` - the safe public API of `wasmtime`.
-* `wasmtime-runtime` - low-level runtime implementation of Wasmtime. This
-  is where `VMContext` and `InstanceHandle` live. This crate is theoretically
-  agnostic to how JIT code was compiled and the runtime that it's running
-  within.
+  * `wasmtime::runtime::vm` - low-level runtime implementation of Wasmtime. This
+    is where `VMContext` and `InstanceHandle` live. This module used to be a
+    crate, but has since been folding into `wasmtime`.
 * `wasmtime-environ` - low-level compilation support. This is where translation
   of the `Module` and its environment happens, although no compilation actually
   happens in this crate (although it defines an interface for compilers). The
diff --git a/examples/min-platform/README.md b/examples/min-platform/README.md
index 766865136..14eac757d 100644
--- a/examples/min-platform/README.md
+++ b/examples/min-platform/README.md
@@ -20,9 +20,10 @@ The example is organized into a few locations:
   customized and these files are only examples.
 
 * `examples/min-platform/embedding/wasmtime-platform.{h,c}` - an example
-  implementation of the platform dependencies that Wasmtime requires. This
-  is defined and documented in `crates/runtime/src/sys/custom/capi.rs`. The
-  example here implements the required functions with Linux syscalls.
+  implementation of the platform dependencies that Wasmtime requires. This is
+  defined and documented in
+  `crates/wasmtime/src/runtime/vm/sys/custom/capi.rs`. The example here
+  implements the required functions with Linux syscalls.
 
 * `examples/min-platform/{Cargo.toml,src}` - an example "host embedding" which
   loads and runs the `embedding` from above. This is a bit contrived and mostly
diff --git a/examples/min-platform/build.sh b/examples/min-platform/build.sh
index 33a7893c1..89f821714 100755
--- a/examples/min-platform/build.sh
+++ b/examples/min-platform/build.sh
@@ -25,7 +25,7 @@ set -ex
 #   cargo install cbindgen
 #
 # which ensures that Rust & C agree on types and such.
-cbindgen ../../crates/runtime/src/sys/custom/capi.rs \
+cbindgen ../../crates/wasmtime/src/runtime/vm/sys/custom/capi.rs \
     --lang C \
     --cpp-compat > embedding/wasmtime-platform.h
 clang -shared -O2 -o libwasmtime-platform.so ./embedding/wasmtime-platform.c \
diff --git a/examples/min-platform/embedding/src/allocator.rs b/examples/min-platform/embedding/src/allocator.rs
index a360c97a6..fc77490ae 100644
--- a/examples/min-platform/embedding/src/allocator.rs
+++ b/examples/min-platform/embedding/src/allocator.rs
@@ -61,7 +61,7 @@ unsafe impl GlobalAlloc for MyGlobalDmalloc {
     }
 }
 
-// Hand-copied from `crates/runtime/src/sys/custom/capi.rs`.
+// Hand-copied from `crates/wasmtime/src/runtime/vm/sys/custom/capi.rs`.
 const PROT_READ: u32 = 1 << 0;
 const PROT_WRITE: u32 = 1 << 1;
 extern "C" {
diff --git a/examples/min-platform/src/main.rs b/examples/min-platform/src/main.rs
index 3ecd9e5a7..64689be1b 100644
--- a/examples/min-platform/src/main.rs
+++ b/examples/min-platform/src/main.rs
@@ -28,7 +28,7 @@ fn main() -> Result<()> {
     // on much. Wasmtime build in a "minimal platform" mode is allowed to
     // depend on some standard C symbols such as `memcpy` but any OS-related
     // symbol must be prefixed by `wasmtime_*` and be documented in
-    // `crates/runtime/src/sys/custom/capi.rs`.
+    // `crates/wasmtime/src/runtime/vm/sys/custom/capi.rs`.
     //
     // This is effectively a double-check of the above assesrtion and showing
     // how running `libembedding.so` in this case requires only minimal
diff --git a/scripts/publish.rs b/scripts/publish.rs
index d6dc0299e..325ed1d81 100644
--- a/scripts/publish.rs
+++ b/scripts/publish.rs
@@ -11,7 +11,7 @@ use std::collections::HashMap;
 use std::env;
 use std::fs;
 use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
+use std::process::{Command, ExitStatus, Output, Stdio};
 use std::thread;
 use std::time::Duration;
 
@@ -54,7 +54,6 @@ const CRATES_TO_PUBLISH: &[&str] = &[
     "wasmtime-fiber",
     "wasmtime-environ",
     "wasmtime-wmemcheck",
-    "wasmtime-runtime",
     "wasmtime-cranelift",
     "wasmtime-cache",
     "winch-codegen",
@@ -151,11 +150,7 @@ fn main() {
             // update C API version in wasmtime.h
             update_capi_version();
             // update the lock file
-            assert!(Command::new("cargo")
-                .arg("fetch")
-                .status()
-                .unwrap()
-                .success());
+            run_cmd(Command::new("cargo").arg("fetch"));
         }
 
         "publish" => {
@@ -199,6 +194,32 @@ fn main() {
     }
 }
 
+fn cmd_output(cmd: &mut Command) -> Output {
+    eprintln!("Running: `{:?}`", cmd);
+    match cmd.output() {
+        Ok(o) => o,
+        Err(e) => panic!("Failed to run `{:?}`: {}", cmd, e),
+    }
+}
+
+fn cmd_status(cmd: &mut Command) -> ExitStatus {
+    eprintln!("Running: `{:?}`", cmd);
+    match cmd.status() {
+        Ok(s) => s,
+        Err(e) => panic!("Failed to run `{:?}`: {}", cmd, e),
+    }
+}
+
+fn run_cmd(cmd: &mut Command) {
+    let status = cmd_status(cmd);
+    assert!(
+        status.success(),
+        "Command `{:?}` exited with failure status: {}",
+        cmd,
+        status
+    );
+}
+
 fn find_crates(dir: &Path, ws: &Workspace, dst: &mut Vec<Crate>) {
     if dir.join("Cargo.toml").exists() {
         let krate = read_crate(Some(ws), &dir.join("Cargo.toml"));
@@ -398,10 +419,9 @@ fn publish(krate: &Crate) -> bool {
 
     // First make sure the crate isn't already published at this version. This
     // script may be re-run and there's no need to re-attempt previous work.
-    let output = Command::new("curl")
-        .arg(&format!("https://crates.io/api/v1/crates/{}", krate.name))
-        .output()
-        .expect("failed to invoke `curl`");
+    let output = cmd_output(
+        Command::new("curl").arg(&format!("https://crates.io/api/v1/crates/{}", krate.name)),
+    );
     if output.status.success()
         && String::from_utf8_lossy(&output.stdout)
             .contains(&format!("\"newest_version\":\"{}\"", krate.version))
@@ -413,12 +433,12 @@ fn publish(krate: &Crate) -> bool {
         return true;
     }
 
-    let status = Command::new("cargo")
-        .arg("publish")
-        .current_dir(krate.manifest.parent().unwrap())
-        .arg("--no-verify")
-        .status()
-        .expect("failed to run cargo");
+    let status = cmd_status(
+        Command::new("cargo")
+            .arg("publish")
+            .current_dir(krate.manifest.parent().unwrap())
+            .arg("--no-verify"),
+    );
     if !status.success() {
         println!("FAIL: failed to publish `{}`: {}", krate.name, status);
         return false;
@@ -427,13 +447,10 @@ fn publish(krate: &Crate) -> bool {
     // After we've published then make sure that the `wasmtime-publish` group is
     // added to this crate for future publications. If it's already present
     // though we can skip the `cargo owner` modification.
-    let output = Command::new("curl")
-        .arg(&format!(
-            "https://crates.io/api/v1/crates/{}/owners",
-            krate.name
-        ))
-        .output()
-        .expect("failed to invoke `curl`");
+    let output = cmd_output(Command::new("curl").arg(&format!(
+        "https://crates.io/api/v1/crates/{}/owners",
+        krate.name
+    )));
     if output.status.success()
         && String::from_utf8_lossy(&output.stdout).contains("wasmtime-publish")
     {
@@ -447,19 +464,13 @@ fn publish(krate: &Crate) -> bool {
     // Note that the status is ignored here. This fails most of the time because
     // the owner is already set and present, so we only want to add this to
     // crates which haven't previously been published.
-    let status = Command::new("cargo")
-        .arg("owner")
-        .arg("-a")
-        .arg("github:bytecodealliance:wasmtime-publish")
-        .arg(&krate.name)
-        .status()
-        .expect("failed to run cargo");
-    if !status.success() {
-        panic!(
-            "FAIL: failed to add wasmtime-publish as owner `{}`: {}",
-            krate.name, status
-        );
-    }
+    run_cmd(
+        Command::new("cargo")
+            .arg("owner")
+            .arg("-a")
+            .arg("github:bytecodealliance:wasmtime-publish")
+            .arg(&krate.name),
+    );
 
     true
 }
@@ -474,11 +485,7 @@ fn verify(crates: &[Crate]) {
 
     drop(fs::remove_dir_all(".cargo"));
     drop(fs::remove_dir_all("vendor"));
-    let vendor = Command::new("cargo")
-        .arg("vendor")
-        .stderr(Stdio::inherit())
-        .output()
-        .unwrap();
+    let vendor = cmd_output(Command::new("cargo").arg("vendor").stderr(Stdio::inherit()));
     assert!(vendor.status.success());
 
     fs::create_dir_all(".cargo").unwrap();
@@ -500,18 +507,16 @@ fn verify(crates: &[Crate]) {
         if krate.name.contains("wasi-nn") {
             cmd.arg("--no-verify");
         }
-        let status = cmd.status().unwrap();
-        assert!(status.success(), "failed to verify {:?}", &krate.manifest);
-        let tar = Command::new("tar")
-            .arg("xf")
-            .arg(format!(
-                "../target/package/{}-{}.crate",
-                krate.name, krate.version
-            ))
-            .current_dir("./vendor")
-            .status()
-            .unwrap();
-        assert!(tar.success());
+        run_cmd(&mut cmd);
+        run_cmd(
+            Command::new("tar")
+                .arg("xf")
+                .arg(format!(
+                    "../target/package/{}-{}.crate",
+                    krate.name, krate.version
+                ))
+                .current_dir("./vendor"),
+        );
         fs::write(
             format!(
                 "./vendor/{}-{}/.cargo-checksum.json",
diff --git a/src/common.rs b/src/common.rs
index 4cbd70f32..866cbbd47 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -174,11 +174,11 @@ impl RunCommon {
         // modules on disk that they're opened once to detect what they are and
         // then again internally in Wasmtime as part of the `deserialize_file`
         // API. Currently there's no way to pass the `MmapVec` here through to
-        // Wasmtime itself (that'd require making `wasmtime-runtime` a public
-        // dependency or `MmapVec` a public type, both of which aren't ready to
-        // happen at this time). It's hoped though that opening a file twice
-        // isn't too bad in the grand scheme of things with respect to the CLI.
-        match wasmtime_runtime::MmapVec::from_file(path) {
+        // Wasmtime itself (that'd require making `MmapVec` a public type, both
+        // which isn't ready to happen at this time). It's hoped though that
+        // opening a file twice isn't too bad in the grand scheme of things with
+        // respect to the CLI.
+        match wasmtime::_internal::MmapVec::from_file(path) {
             Ok(map) => self.load_module_contents(
                 engine,
                 path,
diff --git a/supply-chain/config.toml b/supply-chain/config.toml
index 79a239e79..95111256c 100644
--- a/supply-chain/config.toml
+++ b/supply-chain/config.toml
@@ -133,9 +133,6 @@ audit-as-crates-io = true
 [policy.wasmtime-jit-icache-coherence]
 audit-as-crates-io = true
 
-[policy.wasmtime-runtime]
-audit-as-crates-io = true
-
 [policy.wasmtime-slab]
 audit-as-crates-io = true
 


Test patch:
diff --git a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs
index 454e768c0..c55540ef4 100644
--- a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs
+++ b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs
@@ -61,6 +61,7 @@ impl Inst {
     }
 
     fn xmm_rm_r_evex(op: Avx512Opcode, src1: Reg, src2: RegMem, dst: Writable<Reg>) -> Self {
+        debug_assert_ne!(op, Avx512Opcode::Vpermi2b);
         src2.assert_regclass_is(RegClass::Float);
         debug_assert!(src1.class() == RegClass::Float);
         debug_assert!(dst.to_reg().class() == RegClass::Float);
@@ -72,6 +73,27 @@ impl Inst {
         }
     }
 
+    fn xmm_rm_r_evex3(
+        op: Avx512Opcode,
+        src1: Reg,
+        src2: Reg,
+        src3: RegMem,
+        dst: Writable<Reg>,
+    ) -> Self {
+        debug_assert_eq!(op, Avx512Opcode::Vpermi2b);
+        src3.assert_regclass_is(RegClass::Float);
+        debug_assert!(src1.class() == RegClass::Float);
+        debug_assert!(src2.class() == RegClass::Float);
+        debug_assert!(dst.to_reg().class() == RegClass::Float);
+        Inst::XmmRmREvex3 {
+            op,
+            src1: Xmm::new(src1).unwrap(),
+            src2: Xmm::new(src2).unwrap(),
+            src3: XmmMem::new(src3).unwrap(),
+            dst: WritableXmm::from_writable_reg(dst).unwrap(),
+        }
+    }
+
     // TODO Can be replaced by `Inst::move` (high-level) and `Inst::unary_rm_r` (low-level)
     fn xmm_mov(op: SseOpcode, src: RegMem, dst: Writable<Reg>) -> Inst {
         src.assert_regclass_is(RegClass::Float);
@@ -4189,19 +4211,37 @@ fn test_x64_emit() {
     insns.push((
         Inst::xmm_rm_r_evex(Avx512Opcode::Vpmullq, xmm10, RegMem::reg(xmm14), w_xmm1),
         "62D2AD0840CE",
-        "vpmullq %xmm10, %xmm14, %xmm1",
+        "vpmullq %xmm14, %xmm10, %xmm1",
     ));
 
     insns.push((
-        Inst::xmm_rm_r_evex(Avx512Opcode::Vpermi2b, xmm10, RegMem::reg(xmm14), w_xmm1),
+        Inst::xmm_rm_r_evex(Avx512Opcode::Vpsraq, xmm10, RegMem::reg(xmm14), w_xmm1),
+        "62D1AD08E2CE",
+        "vpsraq  %xmm14, %xmm10, %xmm1",
+    ));
+
+    insns.push((
+        Inst::xmm_rm_r_evex3(
+            Avx512Opcode::Vpermi2b,
+            xmm1,
+            xmm10,
+            RegMem::reg(xmm14),
+            w_xmm1,
+        ),
         "62D22D0875CE",
-        "vpermi2b %xmm10, %xmm14, %xmm1",
+        "vpermi2b %xmm14, %xmm10, %xmm1, %xmm1",
     ));
 
     insns.push((
-        Inst::xmm_rm_r_evex(Avx512Opcode::Vpermi2b, xmm0, RegMem::reg(xmm1), w_xmm2),
+        Inst::xmm_rm_r_evex3(
+            Avx512Opcode::Vpermi2b,
+            xmm2,
+            xmm0,
+            RegMem::reg(xmm1),
+            w_xmm2,
+        ),
         "62F27D0875D1",
-        "vpermi2b %xmm0, %xmm1, %xmm2",
+        "vpermi2b %xmm1, %xmm0, %xmm2, %xmm2",
     ));
 
     insns.push((
diff --git a/cranelift/filetests/filetests/egraph/icmp.clif b/cranelift/filetests/filetests/egraph/icmp.clif
index 01e6db2aa..44f50201d 100644
--- a/cranelift/filetests/filetests/egraph/icmp.clif
+++ b/cranelift/filetests/filetests/egraph/icmp.clif
@@ -125,3 +125,48 @@ block0(v0: i8):
 ;     return v4
 ; }
 
+function %eq_one_of_icmp(i8) -> i8 fast {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = icmp eq v0, v1
+    v3 = iconst.i8 1
+    v4 = icmp eq v2, v3
+    return v4
+}
+
+; function %eq_one_of_icmp(i8) -> i8 fast {
+; block0(v0: i8):
+;     v1 = iconst.i8 5
+;     v2 = icmp eq v0, v1  ; v1 = 5
+;     return v2
+; }
+
+function %ne_one_of_icmp(i8) -> i8 fast {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = icmp eq v0, v1
+    v3 = iconst.i8 1
+    v4 = icmp ne v2, v3
+    return v4
+}
+
+; function %ne_one_of_icmp(i8) -> i8 fast {
+; block0(v0: i8):
+;     v1 = iconst.i8 5
+;     v5 = icmp ne v0, v1  ; v1 = 5
+;     return v5
+; }
+
+function %negate_lt(i8, i8) -> i8 fast {
+block0(v0: i8, v1: i8):
+    v2 = icmp ult v0, v1
+    v3 = iconst.i8 1
+    v4 = icmp ne v2, v3
+    return v4
+}
+
+; function %negate_lt(i8, i8) -> i8 fast {
+; block0(v0: i8, v1: i8):
+;     v5 = icmp uge v0, v1
+;     return v5
+; }
diff --git a/cranelift/filetests/filetests/isa/x64/shuffle-avx512.clif b/cranelift/filetests/filetests/isa/x64/shuffle-avx512.clif
index 2ccae2002..e0dad66c7 100644
--- a/cranelift/filetests/filetests/isa/x64/shuffle-avx512.clif
+++ b/cranelift/filetests/filetests/isa/x64/shuffle-avx512.clif
@@ -15,7 +15,7 @@ block0(v0: i8x16, v1: i8x16):
 ;   movdqa  %xmm0, %xmm5
 ;   movdqu  const(0), %xmm0
 ;   movdqa  %xmm5, %xmm6
-;   vpermi2b %xmm0, %xmm6, %xmm1, %xmm0
+;   vpermi2b %xmm1, %xmm6, %xmm0, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -54,7 +54,7 @@ block0(v0: i8x16, v1: i8x16):
 ;   movdqa  %xmm0, %xmm5
 ;   movdqu  const(0), %xmm0
 ;   movdqa  %xmm5, %xmm6
-;   vpermi2b %xmm0, %xmm6, %xmm1, %xmm0
+;   vpermi2b %xmm1, %xmm6, %xmm0, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
diff --git a/cranelift/filetests/filetests/isa/x64/simd-i64x2-mul-avx512.clif b/cranelift/filetests/filetests/isa/x64/simd-i64x2-mul-avx512.clif
new file mode 100644
index 000000000..6f0e6dbc8
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/x64/simd-i64x2-mul-avx512.clif
@@ -0,0 +1,33 @@
+test compile precise-output
+target x86_64 sse42 has_avx has_avx2 has_avx512dq has_avx512vl
+
+function %imul(i64x2, i64x2) -> i64x2, i64x2 {
+block0(v0: i64x2, v1: i64x2):
+  ;; Force register allocation to pick a different destination than
+  ;; source for at least one of these instructions.
+  v2 = imul v0, v1
+  v3 = imul v2, v1
+  return v2, v3
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   vpmullq %xmm1, %xmm0, %xmm0
+;   vpmullq %xmm1, %xmm0, %xmm1
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   vpmullq %xmm1, %xmm0, %xmm0
+;   vpmullq %xmm1, %xmm0, %xmm1
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
diff --git a/cranelift/filetests/filetests/isa/x64/simd-i64x2-shift-avx512.clif b/cranelift/filetests/filetests/isa/x64/simd-i64x2-shift-avx512.clif
index 22210f479..d7a6796b9 100644
--- a/cranelift/filetests/filetests/isa/x64/simd-i64x2-shift-avx512.clif
+++ b/cranelift/filetests/filetests/isa/x64/simd-i64x2-shift-avx512.clif
@@ -1,19 +1,26 @@
 test compile precise-output
 target x86_64 sse42 has_avx has_avx2 has_avx512f has_avx512vl
 
-function %sshr(i64x2, i64) -> i64x2 {
+function %sshr(i64x2, i64) -> i64x2, i64x2 {
 block0(v0: i64x2, v1: i64):
+  ;; Force register allocation to pick a different destination than
+  ;; source for at least one of these instructions.
   v2 = sshr v0, v1
-  return v2
+  v3 = sshr v2, v1
+  return v2, v3
 }
 
 ; VCode:
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
+;   movq    %rdi, %r9
+;   andq    %r9, $63, %r9
+;   vmovd   %r9d, %xmm1
+;   vpsraq  %xmm1, %xmm0, %xmm0
 ;   andq    %rdi, $63, %rdi
-;   vmovd   %edi, %xmm5
-;   vpsraq  %xmm5, %xmm0, %xmm0
+;   vmovd   %edi, %xmm1
+;   vpsraq  %xmm1, %xmm0, %xmm1
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -23,9 +30,13 @@ block0(v0: i64x2, v1: i64):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
+;   movq %rdi, %r9
+;   andq $0x3f, %r9
+;   vmovd %r9d, %xmm1
+;   vpsraq %xmm1, %xmm0, %xmm0
 ;   andq $0x3f, %rdi
-;   vmovd %edi, %xmm5
-;   vpsraq %xmm5, %xmm0, %xmm0
+;   vmovd %edi, %xmm1
+;   vpsraq %xmm1, %xmm0, %xmm1
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
diff --git a/cranelift/filetests/filetests/runtests/icmp-of-icmp.clif b/cranelift/filetests/filetests/runtests/icmp-of-icmp.clif
new file mode 100644
index 000000000..273d80dac
--- /dev/null
+++ b/cranelift/filetests/filetests/runtests/icmp-of-icmp.clif
@@ -0,0 +1,56 @@
+test interpret
+test run
+set opt_level=speed
+target aarch64
+target x86_64
+target s390x
+target riscv64
+target riscv64 has_c has_zcb
+
+function %eq_eq_zero(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = icmp eq v0, v1
+    v3 = iconst.i8 0
+    v4 = icmp eq v2, v3
+    return v4
+}
+
+; run: %eq_eq_zero(5) == 0
+; run: %eq_eq_zero(3) == 1
+
+function %ne_eq_one(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = icmp eq v0, v1
+    v3 = iconst.i8 1
+    v4 = icmp ne v2, v3
+    return v4
+}
+
+; run: %ne_eq_one(5) == 0
+; run: %ne_eq_one(3) == 1
+
+function %ne_eq_zero(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = icmp eq v0, v1
+    v3 = iconst.i8 0
+    v4 = icmp ne v2, v3
+    return v4
+}
+
+; run: %ne_eq_zero(5) == 1
+; run: %ne_eq_zero(3) == 0
+
+function %eq_eq_one(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = icmp eq v0, v1
+    v3 = iconst.i8 1
+    v4 = icmp eq v2, v3
+    return v4
+}
+
+; run: %eq_eq_one(5) == 1
+; run: %eq_eq_one(3) == 0
diff --git a/tests/all/main.rs b/tests/all/main.rs
index 2b173037a..f778edfde 100644
--- a/tests/all/main.rs
+++ b/tests/all/main.rs
@@ -97,7 +97,7 @@ pub(crate) fn small_pool_config() -> wasmtime::PoolingAllocationConfig {
     // When testing, we may choose to start with MPK force-enabled to ensure
     // we use that functionality.
     if std::env::var("WASMTIME_TEST_FORCE_MPK").is_ok() {
-        config.memory_protection_keys(wasmtime_runtime::MpkEnabled::Enable);
+        config.memory_protection_keys(wasmtime::MpkEnabled::Enable);
     }
 
     #[cfg(feature = "async")]
diff --git a/tests/all/memory.rs b/tests/all/memory.rs
index 71ce7cbfb..538bd744c 100644
--- a/tests/all/memory.rs
+++ b/tests/all/memory.rs
@@ -2,7 +2,6 @@ use rayon::prelude::*;
 use std::sync::atomic::{AtomicU32, Ordering::SeqCst};
 use std::time::{Duration, Instant};
 use wasmtime::*;
-use wasmtime_runtime::mpk;
 
 fn module(engine: &Engine) -> Result<Module> {
     let mut wat = format!("(module\n");
@@ -247,7 +246,7 @@ fn guards_present_pooling() -> Result<()> {
 #[test]
 #[cfg_attr(miri, ignore)]
 fn guards_present_pooling_mpk() -> Result<()> {
-    if !mpk::is_supported() {
+    if !wasmtime::PoolingAllocationConfig::are_memory_protection_keys_available() {
         println!("skipping `guards_present_pooling_mpk` test; mpk is not supported");
         return Ok(());
     }
diff --git a/tests/all/wast.rs b/tests/all/wast.rs
index c7f94c144..89ce349f0 100644
--- a/tests/all/wast.rs
+++ b/tests/all/wast.rs
@@ -4,10 +4,10 @@ use once_cell::sync::Lazy;
 use std::path::Path;
 use std::sync::{Condvar, Mutex};
 use wasmtime::{
-    Config, Engine, InstanceAllocationStrategy, PoolingAllocationConfig, Store, Strategy,
+    Config, Engine, InstanceAllocationStrategy, MpkEnabled, PoolingAllocationConfig, Store,
+    Strategy,
 };
 use wasmtime_environ::WASM_PAGE_SIZE;
-use wasmtime_runtime::MpkEnabled;
 use wasmtime_wast::{SpectestConfig, WastContext};
 
 include!(concat!(env!("OUT_DIR"), "/wast_testsuite_tests.rs"));