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::*;
93#[cfg(feature = "component-model")]
94pub use crate::runtime::vm::vmcontext::VMTableDefinition;
95pub use crate::runtime::vm::vmcontext::{
96 VMArrayCallFunction, VMArrayCallHostFuncContext, VMContext, VMFuncRef, VMFunctionBody,
97 VMFunctionImport, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport,
98 VMOpaqueContext, VMStoreContext, VMTable, VMTagImport, VMWasmCallFunction, ValRaw,
99};
100pub use send_sync_ptr::SendSyncPtr;
101
102mod module_id;
103pub use module_id::CompiledModuleId;
104
105#[cfg(has_virtual_memory)]
106mod byte_count;
107#[cfg(has_virtual_memory)]
108mod cow;
109#[cfg(not(has_virtual_memory))]
110mod cow_disabled;
111#[cfg(has_virtual_memory)]
112mod mmap;
113
114#[cfg(feature = "async")]
115mod async_yield;
116#[cfg(feature = "async")]
117pub use crate::runtime::vm::async_yield::*;
118
119#[cfg(feature = "gc-null")]
120mod send_sync_unsafe_cell;
121#[cfg(feature = "gc-null")]
122pub use send_sync_unsafe_cell::SendSyncUnsafeCell;
123
124cfg_if::cfg_if! {
125 if #[cfg(has_virtual_memory)] {
126 pub use crate::runtime::vm::byte_count::*;
127 pub use crate::runtime::vm::mmap::{Mmap, MmapOffset};
128 pub use self::cow::{MemoryImage, MemoryImageSlot, ModuleMemoryImages};
129 } else {
130 pub use self::cow_disabled::{MemoryImage, MemoryImageSlot, ModuleMemoryImages};
131 }
132}
133
134pub unsafe trait VMStore {
147 fn store_opaque(&self) -> &StoreOpaque;
149
150 fn store_opaque_mut(&mut self) -> &mut StoreOpaque;
152
153 fn memory_growing(
156 &mut self,
157 current: usize,
158 desired: usize,
159 maximum: Option<usize>,
160 ) -> Result<bool, Error>;
161
162 fn memory_grow_failed(&mut self, error: Error) -> Result<()>;
167
168 fn table_growing(
171 &mut self,
172 current: usize,
173 desired: usize,
174 maximum: Option<usize>,
175 ) -> Result<bool, Error>;
176
177 fn table_grow_failed(&mut self, error: Error) -> Result<()>;
182
183 fn out_of_gas(&mut self) -> Result<(), Error>;
187
188 #[cfg(target_has_atomic = "64")]
192 fn new_epoch(&mut self) -> Result<u64, Error>;
193
194 fn maybe_async_gc(&mut self, root: Option<VMGcRef>) -> Result<Option<VMGcRef>>;
204
205 #[cfg(feature = "component-model")]
207 fn component_calls(&mut self) -> &mut component::CallContexts;
208
209 #[cfg(feature = "component-model-async")]
210 fn component_async_store(
211 &mut self,
212 ) -> &mut dyn crate::runtime::component::VMComponentAsyncStore;
213}
214
215impl Deref for dyn VMStore + '_ {
216 type Target = StoreOpaque;
217
218 fn deref(&self) -> &Self::Target {
219 self.store_opaque()
220 }
221}
222
223impl DerefMut for dyn VMStore + '_ {
224 fn deref_mut(&mut self) -> &mut Self::Target {
225 self.store_opaque_mut()
226 }
227}
228
229#[derive(Copy, Clone)]
244#[repr(transparent)]
245struct VMStoreRawPtr(pub NonNull<dyn VMStore>);
246
247unsafe impl Send for VMStoreRawPtr {}
250unsafe impl Sync for VMStoreRawPtr {}
251
252#[derive(Clone)]
266pub enum ModuleRuntimeInfo {
267 Module(crate::Module),
268 Bare(Box<BareModuleInfo>),
269}
270
271#[derive(Clone)]
276pub struct BareModuleInfo {
277 module: Arc<wasmtime_environ::Module>,
278 one_signature: Option<VMSharedTypeIndex>,
279 offsets: VMOffsets<HostPtr>,
280}
281
282impl ModuleRuntimeInfo {
283 pub(crate) fn bare(module: Arc<wasmtime_environ::Module>) -> Self {
284 ModuleRuntimeInfo::bare_maybe_imported_func(module, None)
285 }
286
287 pub(crate) fn bare_maybe_imported_func(
288 module: Arc<wasmtime_environ::Module>,
289 one_signature: Option<VMSharedTypeIndex>,
290 ) -> Self {
291 ModuleRuntimeInfo::Bare(Box::new(BareModuleInfo {
292 offsets: VMOffsets::new(HostPtr, &module),
293 module,
294 one_signature,
295 }))
296 }
297
298 pub(crate) fn env_module(&self) -> &Arc<wasmtime_environ::Module> {
300 match self {
301 ModuleRuntimeInfo::Module(m) => m.env_module(),
302 ModuleRuntimeInfo::Bare(b) => &b.module,
303 }
304 }
305
306 #[cfg(feature = "gc")]
309 fn engine_type_index(&self, module_index: ModuleInternedTypeIndex) -> VMSharedTypeIndex {
310 match self {
311 ModuleRuntimeInfo::Module(m) => m
312 .code_object()
313 .signatures()
314 .shared_type(module_index)
315 .expect("bad module-level interned type index"),
316 ModuleRuntimeInfo::Bare(_) => unreachable!(),
317 }
318 }
319
320 fn function(&self, index: DefinedFuncIndex) -> NonNull<VMWasmCallFunction> {
322 let module = match self {
323 ModuleRuntimeInfo::Module(m) => m,
324 ModuleRuntimeInfo::Bare(_) => unreachable!(),
325 };
326 let ptr = module
327 .compiled_module()
328 .finished_function(index)
329 .as_ptr()
330 .cast::<VMWasmCallFunction>()
331 .cast_mut();
332 NonNull::new(ptr).unwrap()
333 }
334
335 fn array_to_wasm_trampoline(
341 &self,
342 index: DefinedFuncIndex,
343 ) -> Option<NonNull<VMArrayCallFunction>> {
344 let m = match self {
345 ModuleRuntimeInfo::Module(m) => m,
346 ModuleRuntimeInfo::Bare(_) => unreachable!(),
347 };
348 let ptr = NonNull::from(m.compiled_module().array_to_wasm_trampoline(index)?);
349 Some(ptr.cast())
350 }
351
352 fn memory_image(
355 &self,
356 memory: DefinedMemoryIndex,
357 ) -> anyhow::Result<Option<&Arc<MemoryImage>>> {
358 match self {
359 ModuleRuntimeInfo::Module(m) => {
360 let images = m.memory_images()?;
361 Ok(images.and_then(|images| images.get_memory_image(memory)))
362 }
363 ModuleRuntimeInfo::Bare(_) => Ok(None),
364 }
365 }
366
367 #[cfg(feature = "pooling-allocator")]
371 fn unique_id(&self) -> Option<CompiledModuleId> {
372 match self {
373 ModuleRuntimeInfo::Module(m) => Some(m.id()),
374 ModuleRuntimeInfo::Bare(_) => None,
375 }
376 }
377
378 fn wasm_data(&self) -> &[u8] {
380 match self {
381 ModuleRuntimeInfo::Module(m) => m.compiled_module().code_memory().wasm_data(),
382 ModuleRuntimeInfo::Bare(_) => &[],
383 }
384 }
385
386 fn type_ids(&self) -> &[VMSharedTypeIndex] {
389 match self {
390 ModuleRuntimeInfo::Module(m) => m
391 .code_object()
392 .signatures()
393 .as_module_map()
394 .values()
395 .as_slice(),
396 ModuleRuntimeInfo::Bare(b) => match &b.one_signature {
397 Some(s) => core::slice::from_ref(s),
398 None => &[],
399 },
400 }
401 }
402
403 pub(crate) fn offsets(&self) -> &VMOffsets<HostPtr> {
405 match self {
406 ModuleRuntimeInfo::Module(m) => m.offsets(),
407 ModuleRuntimeInfo::Bare(b) => &b.offsets,
408 }
409 }
410}
411
412#[cfg(has_virtual_memory)]
414pub fn host_page_size() -> usize {
415 static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
416
417 return match PAGE_SIZE.load(Ordering::Relaxed) {
418 0 => {
419 let size = sys::vm::get_page_size();
420 assert!(size != 0);
421 PAGE_SIZE.store(size, Ordering::Relaxed);
422 size
423 }
424 n => n,
425 };
426}
427
428#[derive(Copy, Clone, PartialEq, Eq, Debug)]
430pub enum WaitResult {
431 Ok = 0,
434 Mismatch = 1,
437 TimedOut = 2,
440}
441
442#[derive(Debug)]
444pub struct WasmFault {
445 pub memory_size: usize,
447 pub wasm_address: u64,
449}
450
451impl fmt::Display for WasmFault {
452 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
453 write!(
454 f,
455 "memory fault at wasm address 0x{:x} in linear memory of size 0x{:x}",
456 self.wasm_address, self.memory_size,
457 )
458 }
459}