1#![deny(missing_docs)]
4#![warn(clippy::cast_sign_loss)]
7
8use crate::prelude::*;
9use crate::store::StoreOpaque;
10use alloc::sync::Arc;
11use core::fmt;
12use core::ops::Deref;
13use core::ops::DerefMut;
14use core::ptr::NonNull;
15use core::sync::atomic::{AtomicUsize, Ordering};
16use wasmtime_environ::{
17 DefinedFuncIndex, DefinedMemoryIndex, HostPtr, VMOffsets, VMSharedTypeIndex,
18};
19
20#[cfg(feature = "gc")]
21use wasmtime_environ::ModuleInternedTypeIndex;
22
23#[cfg(has_host_compiler_backend)]
24mod arch;
25#[cfg(feature = "component-model")]
26pub mod component;
27mod const_expr;
28mod export;
29mod gc;
30mod imports;
31mod instance;
32mod memory;
33mod mmap_vec;
34mod provenance;
35mod send_sync_ptr;
36mod store_box;
37mod sys;
38mod table;
39mod traphandlers;
40mod unwind;
41mod vmcontext;
42
43#[cfg(feature = "threads")]
44mod parking_spot;
45
46#[cfg(all(has_host_compiler_backend, feature = "debug-builtins"))]
50pub mod debug_builtins;
51pub mod libcalls;
52pub mod mpk;
53
54#[cfg(feature = "pulley")]
55pub(crate) mod interpreter;
56#[cfg(not(feature = "pulley"))]
57pub(crate) mod interpreter_disabled;
58#[cfg(not(feature = "pulley"))]
59pub(crate) use interpreter_disabled as interpreter;
60
61#[cfg(feature = "debug-builtins")]
62pub use wasmtime_jit_debug::gdb_jit_int::GdbJitImageRegistration;
63
64#[cfg(has_host_compiler_backend)]
65pub use crate::runtime::vm::arch::get_stack_pointer;
66pub use crate::runtime::vm::export::*;
67pub use crate::runtime::vm::gc::*;
68pub use crate::runtime::vm::imports::Imports;
69pub use crate::runtime::vm::instance::{
70 GcHeapAllocationIndex, Instance, InstanceAllocationRequest, InstanceAllocator,
71 InstanceAllocatorImpl, InstanceAndStore, InstanceHandle, MemoryAllocationIndex,
72 OnDemandInstanceAllocator, StorePtr, TableAllocationIndex,
73};
74#[cfg(feature = "pooling-allocator")]
75pub use crate::runtime::vm::instance::{
76 InstanceLimits, PoolConcurrencyLimitError, PoolingInstanceAllocator,
77 PoolingInstanceAllocatorConfig,
78};
79pub use crate::runtime::vm::interpreter::*;
80pub use crate::runtime::vm::memory::{
81 Memory, MemoryBase, RuntimeLinearMemory, RuntimeMemoryCreator, SharedMemory,
82};
83pub use crate::runtime::vm::mmap_vec::MmapVec;
84pub use crate::runtime::vm::provenance::*;
85pub use crate::runtime::vm::store_box::*;
86#[cfg(feature = "std")]
87pub use crate::runtime::vm::sys::mmap::open_file_for_mmap;
88#[cfg(has_host_compiler_backend)]
89pub use crate::runtime::vm::sys::unwind::UnwindRegistration;
90pub use crate::runtime::vm::table::{Table, TableElement};
91pub use crate::runtime::vm::traphandlers::*;
92pub use crate::runtime::vm::unwind::*;
93pub use crate::runtime::vm::vmcontext::{
94 VMArrayCallFunction, VMArrayCallHostFuncContext, VMContext, VMFuncRef, VMFunctionBody,
95 VMFunctionImport, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport,
96 VMOpaqueContext, VMRuntimeLimits, VMTableImport, VMTagImport, VMWasmCallFunction, ValRaw,
97};
98pub use send_sync_ptr::SendSyncPtr;
99
100mod module_id;
101pub use module_id::CompiledModuleId;
102
103#[cfg(has_virtual_memory)]
104mod byte_count;
105#[cfg(has_virtual_memory)]
106mod cow;
107#[cfg(not(has_virtual_memory))]
108mod cow_disabled;
109#[cfg(has_virtual_memory)]
110mod mmap;
111
112#[cfg(feature = "async")]
113mod async_yield;
114#[cfg(feature = "async")]
115pub use crate::runtime::vm::async_yield::*;
116
117#[cfg(feature = "gc-null")]
118mod send_sync_unsafe_cell;
119#[cfg(feature = "gc-null")]
120pub use send_sync_unsafe_cell::SendSyncUnsafeCell;
121
122cfg_if::cfg_if! {
123 if #[cfg(has_virtual_memory)] {
124 pub use crate::runtime::vm::byte_count::*;
125 pub use crate::runtime::vm::mmap::{Mmap, MmapOffset};
126 pub use self::cow::{MemoryImage, MemoryImageSlot, ModuleMemoryImages};
127 } else {
128 pub use self::cow_disabled::{MemoryImage, MemoryImageSlot, ModuleMemoryImages};
129 }
130}
131
132pub unsafe trait VMStore {
145 fn store_opaque(&self) -> &StoreOpaque;
147
148 fn store_opaque_mut(&mut self) -> &mut StoreOpaque;
150
151 fn memory_growing(
154 &mut self,
155 current: usize,
156 desired: usize,
157 maximum: Option<usize>,
158 ) -> Result<bool, Error>;
159
160 fn memory_grow_failed(&mut self, error: Error) -> Result<()>;
165
166 fn table_growing(
169 &mut self,
170 current: usize,
171 desired: usize,
172 maximum: Option<usize>,
173 ) -> Result<bool, Error>;
174
175 fn table_grow_failed(&mut self, error: Error) -> Result<()>;
180
181 fn out_of_gas(&mut self) -> Result<(), Error>;
185
186 #[cfg(target_has_atomic = "64")]
190 fn new_epoch(&mut self) -> Result<u64, Error>;
191
192 fn maybe_async_gc(&mut self, root: Option<VMGcRef>) -> Result<Option<VMGcRef>>;
202
203 #[cfg(feature = "component-model")]
205 fn component_calls(&mut self) -> &mut component::CallContexts;
206}
207
208impl Deref for dyn VMStore + '_ {
209 type Target = StoreOpaque;
210
211 fn deref(&self) -> &Self::Target {
212 self.store_opaque()
213 }
214}
215
216impl DerefMut for dyn VMStore + '_ {
217 fn deref_mut(&mut self) -> &mut Self::Target {
218 self.store_opaque_mut()
219 }
220}
221
222#[derive(Copy, Clone)]
237#[repr(transparent)]
238struct VMStoreRawPtr(NonNull<dyn VMStore>);
239
240unsafe impl Send for VMStoreRawPtr {}
243unsafe impl Sync for VMStoreRawPtr {}
244
245#[derive(Clone)]
259pub enum ModuleRuntimeInfo {
260 Module(crate::Module),
261 Bare(Box<BareModuleInfo>),
262}
263
264#[derive(Clone)]
269pub struct BareModuleInfo {
270 module: Arc<wasmtime_environ::Module>,
271 one_signature: Option<VMSharedTypeIndex>,
272 offsets: VMOffsets<HostPtr>,
273}
274
275impl ModuleRuntimeInfo {
276 pub(crate) fn bare(module: Arc<wasmtime_environ::Module>) -> Self {
277 ModuleRuntimeInfo::bare_maybe_imported_func(module, None)
278 }
279
280 pub(crate) fn bare_maybe_imported_func(
281 module: Arc<wasmtime_environ::Module>,
282 one_signature: Option<VMSharedTypeIndex>,
283 ) -> Self {
284 ModuleRuntimeInfo::Bare(Box::new(BareModuleInfo {
285 offsets: VMOffsets::new(HostPtr, &module),
286 module,
287 one_signature,
288 }))
289 }
290
291 pub(crate) fn env_module(&self) -> &Arc<wasmtime_environ::Module> {
293 match self {
294 ModuleRuntimeInfo::Module(m) => m.env_module(),
295 ModuleRuntimeInfo::Bare(b) => &b.module,
296 }
297 }
298
299 #[cfg(feature = "gc")]
302 fn engine_type_index(&self, module_index: ModuleInternedTypeIndex) -> VMSharedTypeIndex {
303 match self {
304 ModuleRuntimeInfo::Module(m) => m
305 .code_object()
306 .signatures()
307 .shared_type(module_index)
308 .expect("bad module-level interned type index"),
309 ModuleRuntimeInfo::Bare(_) => unreachable!(),
310 }
311 }
312
313 fn function(&self, index: DefinedFuncIndex) -> NonNull<VMWasmCallFunction> {
315 let module = match self {
316 ModuleRuntimeInfo::Module(m) => m,
317 ModuleRuntimeInfo::Bare(_) => unreachable!(),
318 };
319 let ptr = module
320 .compiled_module()
321 .finished_function(index)
322 .as_ptr()
323 .cast::<VMWasmCallFunction>()
324 .cast_mut();
325 NonNull::new(ptr).unwrap()
326 }
327
328 fn array_to_wasm_trampoline(
334 &self,
335 index: DefinedFuncIndex,
336 ) -> Option<NonNull<VMArrayCallFunction>> {
337 let m = match self {
338 ModuleRuntimeInfo::Module(m) => m,
339 ModuleRuntimeInfo::Bare(_) => unreachable!(),
340 };
341 let ptr = NonNull::from(m.compiled_module().array_to_wasm_trampoline(index)?);
342 Some(ptr.cast())
343 }
344
345 fn memory_image(
348 &self,
349 memory: DefinedMemoryIndex,
350 ) -> anyhow::Result<Option<&Arc<MemoryImage>>> {
351 match self {
352 ModuleRuntimeInfo::Module(m) => {
353 let images = m.memory_images()?;
354 Ok(images.and_then(|images| images.get_memory_image(memory)))
355 }
356 ModuleRuntimeInfo::Bare(_) => Ok(None),
357 }
358 }
359
360 #[cfg(feature = "pooling-allocator")]
364 fn unique_id(&self) -> Option<CompiledModuleId> {
365 match self {
366 ModuleRuntimeInfo::Module(m) => Some(m.id()),
367 ModuleRuntimeInfo::Bare(_) => None,
368 }
369 }
370
371 fn wasm_data(&self) -> &[u8] {
373 match self {
374 ModuleRuntimeInfo::Module(m) => m.compiled_module().code_memory().wasm_data(),
375 ModuleRuntimeInfo::Bare(_) => &[],
376 }
377 }
378
379 fn type_ids(&self) -> &[VMSharedTypeIndex] {
382 match self {
383 ModuleRuntimeInfo::Module(m) => m
384 .code_object()
385 .signatures()
386 .as_module_map()
387 .values()
388 .as_slice(),
389 ModuleRuntimeInfo::Bare(b) => match &b.one_signature {
390 Some(s) => core::slice::from_ref(s),
391 None => &[],
392 },
393 }
394 }
395
396 pub(crate) fn offsets(&self) -> &VMOffsets<HostPtr> {
398 match self {
399 ModuleRuntimeInfo::Module(m) => m.offsets(),
400 ModuleRuntimeInfo::Bare(b) => &b.offsets,
401 }
402 }
403}
404
405#[cfg(has_virtual_memory)]
407pub fn host_page_size() -> usize {
408 static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
409
410 return match PAGE_SIZE.load(Ordering::Relaxed) {
411 0 => {
412 let size = sys::vm::get_page_size();
413 assert!(size != 0);
414 PAGE_SIZE.store(size, Ordering::Relaxed);
415 size
416 }
417 n => n,
418 };
419}
420
421#[derive(Copy, Clone, PartialEq, Eq, Debug)]
423pub enum WaitResult {
424 Ok = 0,
427 Mismatch = 1,
430 TimedOut = 2,
433}
434
435#[derive(Debug)]
437pub struct WasmFault {
438 pub memory_size: usize,
440 pub wasm_address: u64,
442}
443
444impl fmt::Display for WasmFault {
445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446 write!(
447 f,
448 "memory fault at wasm address 0x{:x} in linear memory of size 0x{:x}",
449 self.wasm_address, self.memory_size,
450 )
451 }
452}