#![deny(missing_docs)]
#![warn(clippy::cast_sign_loss)]
use anyhow::{Error, Result};
use std::fmt;
use std::ptr::NonNull;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use std::sync::Arc;
use wasmtime_environ::{
DefinedFuncIndex, DefinedMemoryIndex, HostPtr, ModuleInternedTypeIndex, VMOffsets,
};
mod arch;
mod async_yield;
#[cfg(feature = "component-model")]
pub mod component;
mod export;
mod gc;
mod imports;
mod instance;
mod memory;
mod mmap;
mod mmap_vec;
mod send_sync_ptr;
mod store_box;
mod sys;
mod table;
mod traphandlers;
mod vmcontext;
mod threads;
pub use self::threads::*;
#[cfg(feature = "debug-builtins")]
pub mod debug_builtins;
pub mod libcalls;
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::{
GcHeapAllocationIndex, Instance, InstanceAllocationRequest, InstanceAllocator,
InstanceAllocatorImpl, InstanceHandle, MemoryAllocationIndex, OnDemandInstanceAllocator,
StorePtr, TableAllocationIndex,
};
#[cfg(feature = "pooling-allocator")]
pub use crate::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::{
VMArrayCallFunction, VMArrayCallHostFuncContext, VMContext, VMFuncRef, VMFunctionBody,
VMFunctionImport, VMGlobalDefinition, VMGlobalImport, VMInvokeArgument, VMMemoryDefinition,
VMMemoryImport, VMNativeCallFunction, VMNativeCallHostFuncContext, VMOpaqueContext,
VMRuntimeLimits, VMSharedTypeIndex, VMTableDefinition, VMTableImport, VMWasmCallFunction,
ValRaw,
};
pub use send_sync_ptr::SendSyncPtr;
mod module_id;
pub use module_id::{CompiledModuleId, CompiledModuleIdAllocator};
mod cow;
pub use crate::cow::{MemoryImage, MemoryImageSlot, ModuleMemoryImages};
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub unsafe trait Store {
fn vmruntime_limits(&self) -> *mut VMRuntimeLimits;
fn epoch_ptr(&self) -> *const AtomicU64;
fn gc_store(&mut self) -> &mut GcStore {
self.maybe_gc_store()
.expect("attempt to access the GC store before it has been allocated")
}
fn maybe_gc_store(&mut self) -> Option<&mut GcStore>;
fn memory_growing(
&mut self,
current: usize,
desired: usize,
maximum: Option<usize>,
) -> Result<bool, Error>;
fn memory_grow_failed(&mut self, error: Error) -> Result<()>;
fn table_growing(
&mut self,
current: u32,
desired: u32,
maximum: Option<u32>,
) -> Result<bool, Error>;
fn table_grow_failed(&mut self, error: Error) -> Result<()>;
fn out_of_gas(&mut self) -> Result<(), Error>;
fn new_epoch(&mut self) -> Result<u64, Error>;
fn gc(&mut self, root: Option<VMGcRef>) -> Result<Option<VMGcRef>>;
#[cfg(feature = "component-model")]
fn component_calls(&mut self) -> &mut component::CallContexts;
}
pub trait ModuleRuntimeInfo: Send + Sync + 'static {
fn module(&self) -> &Arc<wasmtime_environ::Module>;
fn engine_type_index(&self, module_index: ModuleInternedTypeIndex) -> VMSharedTypeIndex;
fn function(&self, index: DefinedFuncIndex) -> NonNull<VMWasmCallFunction>;
fn native_to_wasm_trampoline(
&self,
index: DefinedFuncIndex,
) -> Option<NonNull<VMNativeCallFunction>>;
fn array_to_wasm_trampoline(&self, index: DefinedFuncIndex) -> Option<VMArrayCallFunction>;
fn wasm_to_native_trampoline(
&self,
signature: VMSharedTypeIndex,
) -> Option<NonNull<VMWasmCallFunction>>;
fn memory_image(&self, memory: DefinedMemoryIndex)
-> anyhow::Result<Option<&Arc<MemoryImage>>>;
fn unique_id(&self) -> Option<CompiledModuleId>;
fn wasm_data(&self) -> &[u8];
fn type_ids(&self) -> &[VMSharedTypeIndex];
fn offsets(&self) -> &VMOffsets<HostPtr>;
}
pub fn page_size() -> usize {
static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
return match PAGE_SIZE.load(Ordering::Relaxed) {
0 => {
let size = sys::vm::get_page_size();
assert!(size != 0);
PAGE_SIZE.store(size, Ordering::Relaxed);
size
}
n => n,
};
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum WaitResult {
Ok = 0,
Mismatch = 1,
TimedOut = 2,
}
#[derive(Debug)]
pub struct WasmFault {
pub memory_size: usize,
pub wasm_address: u64,
}
impl fmt::Display for WasmFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"memory fault at wasm address 0x{:x} in linear memory of size 0x{:x}",
self.wasm_address, self.memory_size,
)
}
}