172004aadSNick Fitzgerald //! An `Instance` contains all the runtime state used by execution of a 272004aadSNick Fitzgerald //! wasm module (except its callstack and register state). An 372004aadSNick Fitzgerald //! `InstanceHandle` is a reference-counting handle for an `Instance`. 472004aadSNick Fitzgerald 5aef5eeb5SAlex Crichton use crate::OpaqueRootScope; 699ecf728SChris Fallin use crate::code::ModuleWithCode; 799ecf728SChris Fallin use crate::module::ModuleRegistry; 84233014bSAlex Crichton use crate::prelude::*; 972004aadSNick Fitzgerald use crate::runtime::vm::const_expr::{ConstEvalContext, ConstExprEvaluator}; 101fcd0933SAlex Crichton use crate::runtime::vm::export::{Export, ExportMemory}; 1172004aadSNick Fitzgerald use crate::runtime::vm::memory::{Memory, RuntimeMemoryCreator}; 12aef5eeb5SAlex Crichton use crate::runtime::vm::table::{Table, TableElementType}; 1372004aadSNick Fitzgerald use crate::runtime::vm::vmcontext::{ 1472004aadSNick Fitzgerald VMBuiltinFunctionsArray, VMContext, VMFuncRef, VMFunctionImport, VMGlobalDefinition, 1546306693SAlex Crichton VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMOpaqueContext, VMStoreContext, 1646306693SAlex Crichton VMTableDefinition, VMTableImport, VMTagDefinition, VMTagImport, 1772004aadSNick Fitzgerald }; 1872004aadSNick Fitzgerald use crate::runtime::vm::{ 1982941262SAlex Crichton GcStore, HostResult, Imports, ModuleRuntimeInfo, SendSyncPtr, VMGlobalKind, VMStore, 2082941262SAlex Crichton VMStoreRawPtr, VmPtr, VmSafe, WasmFault, catch_unwind_and_record_trap, 2172004aadSNick Fitzgerald }; 22cc8d04f4SAlex Crichton use crate::store::{ 23cc8d04f4SAlex Crichton Asyncness, InstanceId, StoreId, StoreInstanceId, StoreOpaque, StoreResourceLimiter, 24cc8d04f4SAlex Crichton }; 2599ecf728SChris Fallin use crate::vm::VMWasmCallFunction; 2681a89169SAlex Crichton use alloc::sync::Arc; 2781a89169SAlex Crichton use core::alloc::Layout; 287e28c254SAlex Crichton use core::marker; 2981a89169SAlex Crichton use core::ops::Range; 30aad93a48SAlex Crichton use core::pin::Pin; 3181a89169SAlex Crichton use core::ptr::NonNull; 3210eda1cfSAlex Crichton #[cfg(target_has_atomic = "64")] 3381a89169SAlex Crichton use core::sync::atomic::AtomicU64; 3481a89169SAlex Crichton use core::{mem, ptr}; 35cb235ecfSNick Fitzgerald #[cfg(feature = "gc")] 36cb235ecfSNick Fitzgerald use wasmtime_environ::ModuleInternedTypeIndex; 37a465eabfSNick Fitzgerald use wasmtime_environ::error::OutOfMemory; 3872004aadSNick Fitzgerald use wasmtime_environ::{ 3990ac295eSAlex Crichton DataIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, DefinedTagIndex, 40*9c44a9b4SNick Fitzgerald ElemIndex, EntityIndex, EntityRef, FuncIndex, GlobalIndex, HostPtr, MemoryIndex, PtrSize, 41*9c44a9b4SNick Fitzgerald TableIndex, TableInitialValue, TableSegmentElements, TagIndex, Trap, VMCONTEXT_MAGIC, 42a465eabfSNick Fitzgerald VMOffsets, VMSharedTypeIndex, packed_option::ReservedValue, 4372004aadSNick Fitzgerald }; 4472004aadSNick Fitzgerald #[cfg(feature = "wmemcheck")] 4572004aadSNick Fitzgerald use wasmtime_wmemcheck::Wmemcheck; 4672004aadSNick Fitzgerald 4772004aadSNick Fitzgerald mod allocator; 4872004aadSNick Fitzgerald pub use allocator::*; 4972004aadSNick Fitzgerald 5072004aadSNick Fitzgerald /// A type that roughly corresponds to a WebAssembly instance, but is also used 5172004aadSNick Fitzgerald /// for host-defined objects. 5272004aadSNick Fitzgerald /// 5372004aadSNick Fitzgerald /// Instances here can correspond to actual instantiated modules, but it's also 5472004aadSNick Fitzgerald /// used ubiquitously for host-defined objects. For example creating a 5572004aadSNick Fitzgerald /// host-defined memory will have a `module` that looks like it exports a single 5672004aadSNick Fitzgerald /// memory (and similar for other constructs). 5772004aadSNick Fitzgerald /// 5872004aadSNick Fitzgerald /// This `Instance` type is used as a ubiquitous representation for WebAssembly 5972004aadSNick Fitzgerald /// values, whether or not they were created on the host or through a module. 60aad93a48SAlex Crichton /// 61aad93a48SAlex Crichton /// # Ownership 62aad93a48SAlex Crichton /// 63aad93a48SAlex Crichton /// This structure is never allocated directly but is instead managed through 64aad93a48SAlex Crichton /// an `InstanceHandle`. This structure ends with a `VMContext` which has a 65aad93a48SAlex Crichton /// dynamic size corresponding to the `module` configured within. Memory 66aad93a48SAlex Crichton /// management of this structure is always done through `InstanceHandle` as the 67aad93a48SAlex Crichton /// sole owner of an instance. 68aad93a48SAlex Crichton /// 69aad93a48SAlex Crichton /// # `Instance` and `Pin` 70aad93a48SAlex Crichton /// 71aad93a48SAlex Crichton /// Given an instance it is accompanied with trailing memory for the 72aad93a48SAlex Crichton /// appropriate `VMContext`. The `Instance` also holds `runtime_info` and other 73aad93a48SAlex Crichton /// information pointing to relevant offsets for the `VMContext`. Thus it is 74aad93a48SAlex Crichton /// not sound to mutate `runtime_info` after an instance is created. More 75aad93a48SAlex Crichton /// generally it's also not safe to "swap" instances, for example given two 76aad93a48SAlex Crichton /// `&mut Instance` values it's not sound to swap them as then the `VMContext` 77aad93a48SAlex Crichton /// values are inaccurately described. 78aad93a48SAlex Crichton /// 79aad93a48SAlex Crichton /// To encapsulate this guarantee this type is only ever mutated through Rust's 80aad93a48SAlex Crichton /// `Pin` type. All mutable methods here take `self: Pin<&mut Self>` which 81aad93a48SAlex Crichton /// statically disallows safe access to `&mut Instance`. There are assorted 82aad93a48SAlex Crichton /// "projection methods" to go from `Pin<&mut Instance>` to `&mut T` for 83aad93a48SAlex Crichton /// individual fields, for example `memories_mut`. More methods can be added as 84aad93a48SAlex Crichton /// necessary or methods may also be added to project multiple fields at a time 85aad93a48SAlex Crichton /// if necessary to. The precise ergonomics around getting mutable access to 86aad93a48SAlex Crichton /// some fields (but notably not `runtime_info`) is probably going to evolve 87aad93a48SAlex Crichton /// over time. 88aad93a48SAlex Crichton /// 89aad93a48SAlex Crichton /// Note that is is not sound to basically ever pass around `&mut Instance`. 90aad93a48SAlex Crichton /// That should always instead be `Pin<&mut Instance>`. All usage of 91aad93a48SAlex Crichton /// `Pin::new_unchecked` should be here in this module in just a few `unsafe` 92aad93a48SAlex Crichton /// locations and it's recommended to use existing helpers if you can. 9372004aadSNick Fitzgerald #[repr(C)] // ensure that the vmctx field is last. 9472004aadSNick Fitzgerald pub struct Instance { 95ed20d93dSAlex Crichton /// The index, within a `Store` that this instance lives at 96ed20d93dSAlex Crichton id: InstanceId, 97ed20d93dSAlex Crichton 9872004aadSNick Fitzgerald /// The runtime info (corresponding to the "compiled module" 9972004aadSNick Fitzgerald /// abstraction in higher layers) that is retained and needed for 10072004aadSNick Fitzgerald /// lazy initialization. This provides access to the underlying 10172004aadSNick Fitzgerald /// Wasm module entities, the compiled JIT code, metadata about 10272004aadSNick Fitzgerald /// functions, lazy initialization state, etc. 103f1797bb1SNick Fitzgerald // 104f1797bb1SNick Fitzgerald // SAFETY: this field cannot be overwritten after an instance is created. It 105f1797bb1SNick Fitzgerald // must contain this exact same value for the entire lifetime of this 106f1797bb1SNick Fitzgerald // instance. This enables borrowing the info's `Module` and this instance at 107f1797bb1SNick Fitzgerald // the same time (instance mutably, module not). Additionally it enables 108f1797bb1SNick Fitzgerald // borrowing a store mutably at the same time as a contained instance. 1092835a34bSAlex Crichton runtime_info: ModuleRuntimeInfo, 11072004aadSNick Fitzgerald 11172004aadSNick Fitzgerald /// WebAssembly linear memory data. 11272004aadSNick Fitzgerald /// 11372004aadSNick Fitzgerald /// This is where all runtime information about defined linear memories in 11472004aadSNick Fitzgerald /// this module lives. 11572004aadSNick Fitzgerald /// 11672004aadSNick Fitzgerald /// The `MemoryAllocationIndex` was given from our `InstanceAllocator` and 11772004aadSNick Fitzgerald /// must be given back to the instance allocator when deallocating each 11872004aadSNick Fitzgerald /// memory. 119*9c44a9b4SNick Fitzgerald memories: TryPrimaryMap<DefinedMemoryIndex, (MemoryAllocationIndex, Memory)>, 12072004aadSNick Fitzgerald 12172004aadSNick Fitzgerald /// WebAssembly table data. 12272004aadSNick Fitzgerald /// 12372004aadSNick Fitzgerald /// Like memories, this is only for defined tables in the module and 12472004aadSNick Fitzgerald /// contains all of their runtime state. 12572004aadSNick Fitzgerald /// 12672004aadSNick Fitzgerald /// The `TableAllocationIndex` was given from our `InstanceAllocator` and 12772004aadSNick Fitzgerald /// must be given back to the instance allocator when deallocating each 12872004aadSNick Fitzgerald /// table. 129*9c44a9b4SNick Fitzgerald tables: TryPrimaryMap<DefinedTableIndex, (TableAllocationIndex, Table)>, 13072004aadSNick Fitzgerald 13172004aadSNick Fitzgerald /// Stores the dropped passive element segments in this instantiation by index. 13272004aadSNick Fitzgerald /// If the index is present in the set, the segment has been dropped. 1331c1843daSNick Fitzgerald dropped_elements: TryEntitySet<ElemIndex>, 13472004aadSNick Fitzgerald 13572004aadSNick Fitzgerald /// Stores the dropped passive data segments in this instantiation by index. 13672004aadSNick Fitzgerald /// If the index is present in the set, the segment has been dropped. 1371c1843daSNick Fitzgerald dropped_data: TryEntitySet<DataIndex>, 13872004aadSNick Fitzgerald 13972004aadSNick Fitzgerald // TODO: add support for multiple memories; `wmemcheck_state` corresponds to 14072004aadSNick Fitzgerald // memory 0. 14172004aadSNick Fitzgerald #[cfg(feature = "wmemcheck")] 14272004aadSNick Fitzgerald pub(crate) wmemcheck_state: Option<Wmemcheck>, 14372004aadSNick Fitzgerald 144c3559d4aSAlex Crichton /// Self-pointer back to `Store<T>` and its functions. Not present for 145c3559d4aSAlex Crichton /// the brief time that `Store<T>` is itself being created. Also not 146c3559d4aSAlex Crichton /// present for some niche uses that are disconnected from stores (e.g. 147c3559d4aSAlex Crichton /// cross-thread stuff used in `InstancePre`) 148c3559d4aSAlex Crichton store: Option<VMStoreRawPtr>, 149c3559d4aSAlex Crichton 15072004aadSNick Fitzgerald /// Additional context used by compiled wasm code. This field is last, and 15172004aadSNick Fitzgerald /// represents a dynamically-sized array that extends beyond the nominal 15272004aadSNick Fitzgerald /// end of the struct (similar to a flexible array member). 1537e28c254SAlex Crichton vmctx: OwnedVMContext<VMContext>, 15472004aadSNick Fitzgerald } 15572004aadSNick Fitzgerald 15672004aadSNick Fitzgerald impl Instance { 15772004aadSNick Fitzgerald /// Create an instance at the given memory address. 15872004aadSNick Fitzgerald /// 15972004aadSNick Fitzgerald /// It is assumed the memory was properly aligned and the 16072004aadSNick Fitzgerald /// allocation was `alloc_size` in bytes. 16188079b4fSAlex Crichton /// 16288079b4fSAlex Crichton /// # Safety 16388079b4fSAlex Crichton /// 16488079b4fSAlex Crichton /// The `req.imports` field must be appropriately sized/typed for the module 16588079b4fSAlex Crichton /// being allocated according to `req.runtime_info`. Additionally `memories` 16688079b4fSAlex Crichton /// and `tables` must have been allocated for `req.store`. new( req: InstanceAllocationRequest, memories: TryPrimaryMap<DefinedMemoryIndex, (MemoryAllocationIndex, Memory)>, tables: TryPrimaryMap<DefinedTableIndex, (TableAllocationIndex, Table)>, ) -> Result<InstanceHandle, OutOfMemory>16788079b4fSAlex Crichton unsafe fn new( 16872004aadSNick Fitzgerald req: InstanceAllocationRequest, 169*9c44a9b4SNick Fitzgerald memories: TryPrimaryMap<DefinedMemoryIndex, (MemoryAllocationIndex, Memory)>, 170*9c44a9b4SNick Fitzgerald tables: TryPrimaryMap<DefinedTableIndex, (TableAllocationIndex, Table)>, 171a465eabfSNick Fitzgerald ) -> Result<InstanceHandle, OutOfMemory> { 1722bdae8b6SNick Fitzgerald let module = req.runtime_info.env_module(); 17358ce6b8bSNick Fitzgerald let memory_tys = &module.memories; 1741c1843daSNick Fitzgerald let dropped_elements = TryEntitySet::with_capacity(module.passive_elements.len())?; 1751c1843daSNick Fitzgerald let dropped_data = TryEntitySet::with_capacity(module.passive_data_map.len())?; 17672004aadSNick Fitzgerald 17758ce6b8bSNick Fitzgerald #[cfg(feature = "wmemcheck")] 17858ce6b8bSNick Fitzgerald let wmemcheck_state = if req.store.engine().config().wmemcheck { 17958ce6b8bSNick Fitzgerald let size = memory_tys 18058ce6b8bSNick Fitzgerald .iter() 18158ce6b8bSNick Fitzgerald .next() 18258ce6b8bSNick Fitzgerald .map(|memory| memory.1.limits.min) 18358ce6b8bSNick Fitzgerald .unwrap_or(0) 18458ce6b8bSNick Fitzgerald * 64 18558ce6b8bSNick Fitzgerald * 1024; 18658ce6b8bSNick Fitzgerald Some(Wmemcheck::new(size.try_into().unwrap())) 18758ce6b8bSNick Fitzgerald } else { 18858ce6b8bSNick Fitzgerald None 18958ce6b8bSNick Fitzgerald }; 19072004aadSNick Fitzgerald #[cfg(not(feature = "wmemcheck"))] 1912a7f0653SAlex Crichton let _ = memory_tys; 19272004aadSNick Fitzgerald 1937e28c254SAlex Crichton let mut ret = OwnedInstance::new(Instance { 194ed20d93dSAlex Crichton id: req.id, 19572004aadSNick Fitzgerald runtime_info: req.runtime_info.clone(), 19672004aadSNick Fitzgerald memories, 19772004aadSNick Fitzgerald tables, 19872004aadSNick Fitzgerald dropped_elements, 19972004aadSNick Fitzgerald dropped_data, 20072004aadSNick Fitzgerald #[cfg(feature = "wmemcheck")] 20158ce6b8bSNick Fitzgerald wmemcheck_state, 202c3559d4aSAlex Crichton store: None, 2037e28c254SAlex Crichton vmctx: OwnedVMContext::new(), 204a465eabfSNick Fitzgerald })?; 20572004aadSNick Fitzgerald 2067e28c254SAlex Crichton // SAFETY: this vmctx was allocated with the same layout above, so it 2077e28c254SAlex Crichton // should be safe to initialize with the same values here. 2087e28c254SAlex Crichton unsafe { 209f1797bb1SNick Fitzgerald ret.get_mut().initialize_vmctx(req.store, req.imports); 2107e28c254SAlex Crichton } 211a465eabfSNick Fitzgerald Ok(ret) 21272004aadSNick Fitzgerald } 21372004aadSNick Fitzgerald 2144e8ab840SAlex Crichton /// Converts a raw `VMContext` pointer into a raw `Instance` pointer. 2154e8ab840SAlex Crichton /// 2164e8ab840SAlex Crichton /// # Safety 2174e8ab840SAlex Crichton /// 2184e8ab840SAlex Crichton /// Calling this function safely requires that `vmctx` is a valid allocation 2194e8ab840SAlex Crichton /// of a `VMContext` which is derived from `Instance::new`. To safely 2204e8ab840SAlex Crichton /// convert the returned raw pointer into a safe instance pointer callers 2214e8ab840SAlex Crichton /// will also want to uphold guarantees such as: 2224e8ab840SAlex Crichton /// 2234e8ab840SAlex Crichton /// * The instance should not be in use elsewhere. For example you can't 2244e8ab840SAlex Crichton /// call this function twice, turn both raw pointers into safe pointers, 2254e8ab840SAlex Crichton /// and then use both safe pointers. 2264e8ab840SAlex Crichton /// * There should be no other active mutable borrow to any other instance 2274e8ab840SAlex Crichton /// within the same store. Note that this is not restricted to just this 2284e8ab840SAlex Crichton /// instance pointer, but to all instances in a store. Instances can 2294e8ab840SAlex Crichton /// safely traverse to other instances "laterally" meaning that a mutable 2304e8ab840SAlex Crichton /// borrow on one is a mutable borrow on all. 2314e8ab840SAlex Crichton /// * There should be no active mutable borrow on the store accessible at 2324e8ab840SAlex Crichton /// the same time the instance is turned. Instances are owned by a store 2334e8ab840SAlex Crichton /// and a store can be used to acquire a safe instance borrow at any time. 2344e8ab840SAlex Crichton /// * The lifetime of the usage of the instance should not be unnecessarily 2354e8ab840SAlex Crichton /// long, for example it cannot be `'static`. 2364e8ab840SAlex Crichton /// 2374e8ab840SAlex Crichton /// Other entrypoints exist for converting from a raw `VMContext` to a safe 2384e8ab840SAlex Crichton /// pointer such as: 2394e8ab840SAlex Crichton /// 2404e8ab840SAlex Crichton /// * `Instance::enter_host_from_wasm` 2414e8ab840SAlex Crichton /// * `Instance::sibling_vmctx{,_mut}` 2424e8ab840SAlex Crichton /// 2434e8ab840SAlex Crichton /// These place further restrictions on the API signature to satisfy some of 2444e8ab840SAlex Crichton /// the above points. 2454e8ab840SAlex Crichton #[inline] from_vmctx(vmctx: NonNull<VMContext>) -> NonNull<Instance>2464e8ab840SAlex Crichton pub(crate) unsafe fn from_vmctx(vmctx: NonNull<VMContext>) -> NonNull<Instance> { 2474e8ab840SAlex Crichton // SAFETY: The validity of `byte_sub` relies on `vmctx` being a valid 2484e8ab840SAlex Crichton // allocation. 2494e8ab840SAlex Crichton unsafe { 2504e8ab840SAlex Crichton vmctx 2514e8ab840SAlex Crichton .byte_sub(mem::size_of::<Instance>()) 2524e8ab840SAlex Crichton .cast::<Instance>() 2534e8ab840SAlex Crichton } 2544e8ab840SAlex Crichton } 2554e8ab840SAlex Crichton 25682941262SAlex Crichton /// Encapsulated entrypoint to the host from WebAssembly, converting a raw 257900370bcSAlex Crichton /// `VMContext` pointer into a `VMStore` plus an `InstanceId`. 25882941262SAlex Crichton /// 25982941262SAlex Crichton /// This is an entrypoint for core wasm entering back into the host. This is 26082941262SAlex Crichton /// used for both host functions and libcalls for example. This will execute 26182941262SAlex Crichton /// the closure `f` with safer Internal types than a raw `VMContext` 26282941262SAlex Crichton /// pointer. 26382941262SAlex Crichton /// 26482941262SAlex Crichton /// The closure `f` will have its errors caught, handled, and translated to 26582941262SAlex Crichton /// an ABI-safe return value to give back to wasm. This includes both normal 26682941262SAlex Crichton /// errors such as traps as well as panics. 26782941262SAlex Crichton /// 26882941262SAlex Crichton /// # Safety 26982941262SAlex Crichton /// 27082941262SAlex Crichton /// Callers must ensure that `vmctx` is a valid allocation and is safe to 27182941262SAlex Crichton /// dereference at this time. That's generally only true when it's a 27282941262SAlex Crichton /// wasm-provided value and this is the first function called after entering 27382941262SAlex Crichton /// the host. Otherwise this could unsafely alias the store with a mutable 27482941262SAlex Crichton /// pointer, for example. 27582941262SAlex Crichton #[inline] enter_host_from_wasm<R>( vmctx: NonNull<VMContext>, f: impl FnOnce(&mut dyn VMStore, InstanceId) -> R, ) -> R::Abi where R: HostResult,27682941262SAlex Crichton pub(crate) unsafe fn enter_host_from_wasm<R>( 27782941262SAlex Crichton vmctx: NonNull<VMContext>, 278900370bcSAlex Crichton f: impl FnOnce(&mut dyn VMStore, InstanceId) -> R, 27982941262SAlex Crichton ) -> R::Abi 28082941262SAlex Crichton where 28182941262SAlex Crichton R: HostResult, 28282941262SAlex Crichton { 2834e8ab840SAlex Crichton // SAFETY: It's a contract of this function that `vmctx` is a valid 2844e8ab840SAlex Crichton // pointer with neither the store nor other instances actively in use 2854e8ab840SAlex Crichton // when this is called, so it should be safe to acquire a mutable 2864e8ab840SAlex Crichton // pointer to the store and read the instance pointer. 28782941262SAlex Crichton let (store, instance) = unsafe { 2884e8ab840SAlex Crichton let instance = Instance::from_vmctx(vmctx); 2894e8ab840SAlex Crichton let instance = instance.as_ref(); 29082941262SAlex Crichton let store = &mut *instance.store.unwrap().0.as_ptr(); 291900370bcSAlex Crichton (store, instance.id) 29282941262SAlex Crichton }; 29382941262SAlex Crichton 29482941262SAlex Crichton // Thread the `store` and `instance` through panic/trap infrastructure 29582941262SAlex Crichton // back into `f`. 29682941262SAlex Crichton catch_unwind_and_record_trap(store, |store| f(store, instance)) 29782941262SAlex Crichton } 29882941262SAlex Crichton 299f021346eSAlex Crichton /// Converts the provided `*mut VMContext` to an `Instance` pointer and 300f021346eSAlex Crichton /// returns it with the same lifetime as `self`. 30172004aadSNick Fitzgerald /// 302f021346eSAlex Crichton /// This function can be used when traversing a `VMContext` to reach into 303f021346eSAlex Crichton /// the context needed for imports, optionally. 3042b832281SAlex Crichton /// 3052b832281SAlex Crichton /// # Safety 3062b832281SAlex Crichton /// 307f021346eSAlex Crichton /// This function requires that the `vmctx` pointer is indeed valid and 308f021346eSAlex Crichton /// from the store that `self` belongs to. 309f021346eSAlex Crichton #[inline] sibling_vmctx<'a>(&'a self, vmctx: NonNull<VMContext>) -> &'a Instance310f021346eSAlex Crichton unsafe fn sibling_vmctx<'a>(&'a self, vmctx: NonNull<VMContext>) -> &'a Instance { 311b052dee0SAlex Crichton // SAFETY: it's a contract of this function itself that `vmctx` is a 3124e8ab840SAlex Crichton // valid pointer. Additionally with `self` being a 3134e8ab840SAlex Crichton let ptr = unsafe { Instance::from_vmctx(vmctx) }; 314b052dee0SAlex Crichton // SAFETY: it's a contract of this function itself that `vmctx` is a 315b052dee0SAlex Crichton // valid pointer to dereference. Additionally the lifetime of the return 316b052dee0SAlex Crichton // value is constrained to be the same as `self` to avoid granting a 317b052dee0SAlex Crichton // too-long lifetime. 318b052dee0SAlex Crichton unsafe { ptr.as_ref() } 319f021346eSAlex Crichton } 320f021346eSAlex Crichton 321f021346eSAlex Crichton /// Same as [`Self::sibling_vmctx`], but the mutable version. 322f021346eSAlex Crichton /// 323f021346eSAlex Crichton /// # Safety 324f021346eSAlex Crichton /// 325f021346eSAlex Crichton /// This function requires that the `vmctx` pointer is indeed valid and 326f021346eSAlex Crichton /// from the store that `self` belongs to. 3272278bd20SNick Fitzgerald /// 3282278bd20SNick Fitzgerald /// (Note that it is *NOT* required that `vmctx` be distinct from this 3292278bd20SNick Fitzgerald /// instance's `vmctx`, or that usage of the resulting instance is limited 3302278bd20SNick Fitzgerald /// to its defined items! The returned borrow has the same lifetime as 3312278bd20SNick Fitzgerald /// `self`, which means that this instance cannot be used while the 3322278bd20SNick Fitzgerald /// resulting instance is in use, and we therefore do not need to worry 3332278bd20SNick Fitzgerald /// about mutable aliasing between this instance and the resulting 3342278bd20SNick Fitzgerald /// instance.) 335f021346eSAlex Crichton #[inline] sibling_vmctx_mut<'a>( self: Pin<&'a mut Self>, vmctx: NonNull<VMContext>, ) -> Pin<&'a mut Instance>336f021346eSAlex Crichton unsafe fn sibling_vmctx_mut<'a>( 337f021346eSAlex Crichton self: Pin<&'a mut Self>, 338f021346eSAlex Crichton vmctx: NonNull<VMContext>, 339f021346eSAlex Crichton ) -> Pin<&'a mut Instance> { 340b052dee0SAlex Crichton // SAFETY: it's a contract of this function itself that `vmctx` is a 341b052dee0SAlex Crichton // valid pointer such that this pointer arithmetic is valid. 3424e8ab840SAlex Crichton let mut ptr = unsafe { Instance::from_vmctx(vmctx) }; 343b052dee0SAlex Crichton 344b052dee0SAlex Crichton // SAFETY: it's a contract of this function itself that `vmctx` is a 345b052dee0SAlex Crichton // valid pointer to dereference. Additionally the lifetime of the return 346b052dee0SAlex Crichton // value is constrained to be the same as `self` to avoid granting a 347b052dee0SAlex Crichton // too-long lifetime. Finally mutable references to an instance are 348b052dee0SAlex Crichton // always through `Pin`, so it's safe to create a pin-pointer here. 349b052dee0SAlex Crichton unsafe { Pin::new_unchecked(ptr.as_mut()) } 3502b832281SAlex Crichton } 3512b832281SAlex Crichton env_module(&self) -> &Arc<wasmtime_environ::Module>352c74a7b74SNick Fitzgerald pub(crate) fn env_module(&self) -> &Arc<wasmtime_environ::Module> { 3532bdae8b6SNick Fitzgerald self.runtime_info.env_module() 35472004aadSNick Fitzgerald } 35572004aadSNick Fitzgerald runtime_module(&self) -> Option<&crate::Module>356c74a7b74SNick Fitzgerald pub(crate) fn runtime_module(&self) -> Option<&crate::Module> { 357c74a7b74SNick Fitzgerald match &self.runtime_info { 358c74a7b74SNick Fitzgerald ModuleRuntimeInfo::Module(m) => Some(m), 359c74a7b74SNick Fitzgerald ModuleRuntimeInfo::Bare(_) => None, 360c74a7b74SNick Fitzgerald } 361c74a7b74SNick Fitzgerald } 362c74a7b74SNick Fitzgerald 36372004aadSNick Fitzgerald /// Translate a module-level interned type index into an engine-level 36472004aadSNick Fitzgerald /// interned type index. 365cb235ecfSNick Fitzgerald #[cfg(feature = "gc")] engine_type_index(&self, module_index: ModuleInternedTypeIndex) -> VMSharedTypeIndex36672004aadSNick Fitzgerald pub fn engine_type_index(&self, module_index: ModuleInternedTypeIndex) -> VMSharedTypeIndex { 36772004aadSNick Fitzgerald self.runtime_info.engine_type_index(module_index) 36872004aadSNick Fitzgerald } 36972004aadSNick Fitzgerald 37072004aadSNick Fitzgerald #[inline] offsets(&self) -> &VMOffsets<HostPtr>37172004aadSNick Fitzgerald fn offsets(&self) -> &VMOffsets<HostPtr> { 37272004aadSNick Fitzgerald self.runtime_info.offsets() 37372004aadSNick Fitzgerald } 37472004aadSNick Fitzgerald 37572004aadSNick Fitzgerald /// Return the indexed `VMFunctionImport`. imported_function(&self, index: FuncIndex) -> &VMFunctionImport37672004aadSNick Fitzgerald fn imported_function(&self, index: FuncIndex) -> &VMFunctionImport { 377f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset(self.offsets().vmctx_vmfunction_import(index)) } 37872004aadSNick Fitzgerald } 37972004aadSNick Fitzgerald 38046306693SAlex Crichton /// Return the index `VMTableImport`. imported_table(&self, index: TableIndex) -> &VMTableImport38146306693SAlex Crichton fn imported_table(&self, index: TableIndex) -> &VMTableImport { 382f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset(self.offsets().vmctx_vmtable_import(index)) } 38372004aadSNick Fitzgerald } 38472004aadSNick Fitzgerald 38572004aadSNick Fitzgerald /// Return the indexed `VMMemoryImport`. imported_memory(&self, index: MemoryIndex) -> &VMMemoryImport38672004aadSNick Fitzgerald fn imported_memory(&self, index: MemoryIndex) -> &VMMemoryImport { 387f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset(self.offsets().vmctx_vmmemory_import(index)) } 38872004aadSNick Fitzgerald } 38972004aadSNick Fitzgerald 39072004aadSNick Fitzgerald /// Return the indexed `VMGlobalImport`. imported_global(&self, index: GlobalIndex) -> &VMGlobalImport39172004aadSNick Fitzgerald fn imported_global(&self, index: GlobalIndex) -> &VMGlobalImport { 392f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset(self.offsets().vmctx_vmglobal_import(index)) } 39372004aadSNick Fitzgerald } 39472004aadSNick Fitzgerald 3950b4c754aSDaniel Hillerström /// Return the indexed `VMTagImport`. imported_tag(&self, index: TagIndex) -> &VMTagImport3960b4c754aSDaniel Hillerström fn imported_tag(&self, index: TagIndex) -> &VMTagImport { 397f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset(self.offsets().vmctx_vmtag_import(index)) } 3980b4c754aSDaniel Hillerström } 3990b4c754aSDaniel Hillerström 4000b4c754aSDaniel Hillerström /// Return the indexed `VMTagDefinition`. tag_ptr(&self, index: DefinedTagIndex) -> NonNull<VMTagDefinition>401d6265b21SAlex Crichton pub fn tag_ptr(&self, index: DefinedTagIndex) -> NonNull<VMTagDefinition> { 402f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset_raw(self.offsets().vmctx_vmtag_definition(index)) } 4030b4c754aSDaniel Hillerström } 4040b4c754aSDaniel Hillerström 40572004aadSNick Fitzgerald /// Return the indexed `VMTableDefinition`. table(&self, index: DefinedTableIndex) -> VMTableDefinition406a30e7299SAlex Crichton pub fn table(&self, index: DefinedTableIndex) -> VMTableDefinition { 407b86b9682SAlex Crichton unsafe { self.table_ptr(index).read() } 40872004aadSNick Fitzgerald } 40972004aadSNick Fitzgerald 41072004aadSNick Fitzgerald /// Updates the value for a defined table to `VMTableDefinition`. set_table(self: Pin<&mut Self>, index: DefinedTableIndex, table: VMTableDefinition)411aad93a48SAlex Crichton fn set_table(self: Pin<&mut Self>, index: DefinedTableIndex, table: VMTableDefinition) { 41272004aadSNick Fitzgerald unsafe { 413b86b9682SAlex Crichton self.table_ptr(index).write(table); 41472004aadSNick Fitzgerald } 41572004aadSNick Fitzgerald } 41672004aadSNick Fitzgerald 417a30e7299SAlex Crichton /// Return a pointer to the `index`'th table within this instance, stored 418a30e7299SAlex Crichton /// in vmctx memory. table_ptr(&self, index: DefinedTableIndex) -> NonNull<VMTableDefinition>419a30e7299SAlex Crichton pub fn table_ptr(&self, index: DefinedTableIndex) -> NonNull<VMTableDefinition> { 420f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset_raw(self.offsets().vmctx_vmtable_definition(index)) } 42172004aadSNick Fitzgerald } 42272004aadSNick Fitzgerald 42372004aadSNick Fitzgerald /// Get a locally defined or imported memory. get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition42472004aadSNick Fitzgerald pub(crate) fn get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition { 4252bdae8b6SNick Fitzgerald if let Some(defined_index) = self.env_module().defined_memory_index(index) { 42672004aadSNick Fitzgerald self.memory(defined_index) 42772004aadSNick Fitzgerald } else { 42872004aadSNick Fitzgerald let import = self.imported_memory(index); 429b86b9682SAlex Crichton unsafe { VMMemoryDefinition::load(import.from.as_ptr()) } 43072004aadSNick Fitzgerald } 43172004aadSNick Fitzgerald } 43272004aadSNick Fitzgerald 4330e9a691dSAlex Crichton /// Return the indexed `VMMemoryDefinition`, loaded from vmctx memory 4340e9a691dSAlex Crichton /// already. 4354b518271SAlex Crichton #[inline] memory(&self, index: DefinedMemoryIndex) -> VMMemoryDefinition4360e9a691dSAlex Crichton pub fn memory(&self, index: DefinedMemoryIndex) -> VMMemoryDefinition { 437b86b9682SAlex Crichton unsafe { VMMemoryDefinition::load(self.memory_ptr(index).as_ptr()) } 43872004aadSNick Fitzgerald } 43972004aadSNick Fitzgerald 44072004aadSNick Fitzgerald /// Set the indexed memory to `VMMemoryDefinition`. set_memory(&self, index: DefinedMemoryIndex, mem: VMMemoryDefinition)44172004aadSNick Fitzgerald fn set_memory(&self, index: DefinedMemoryIndex, mem: VMMemoryDefinition) { 44272004aadSNick Fitzgerald unsafe { 443b86b9682SAlex Crichton self.memory_ptr(index).write(mem); 44472004aadSNick Fitzgerald } 44572004aadSNick Fitzgerald } 44672004aadSNick Fitzgerald 4470e9a691dSAlex Crichton /// Return the address of the specified memory at `index` within this vmctx. 4480e9a691dSAlex Crichton /// 4490e9a691dSAlex Crichton /// Note that the returned pointer resides in wasm-code-readable-memory in 4500e9a691dSAlex Crichton /// the vmctx. 4514b518271SAlex Crichton #[inline] memory_ptr(&self, index: DefinedMemoryIndex) -> NonNull<VMMemoryDefinition>4520e9a691dSAlex Crichton pub fn memory_ptr(&self, index: DefinedMemoryIndex) -> NonNull<VMMemoryDefinition> { 453f1111b91SAlex Crichton unsafe { 454f1111b91SAlex Crichton self.vmctx_plus_offset::<VmPtr<_>>(self.offsets().vmctx_vmmemory_pointer(index)) 455f1111b91SAlex Crichton .as_non_null() 456f1111b91SAlex Crichton } 45772004aadSNick Fitzgerald } 45872004aadSNick Fitzgerald 45972004aadSNick Fitzgerald /// Return the indexed `VMGlobalDefinition`. global_ptr(&self, index: DefinedGlobalIndex) -> NonNull<VMGlobalDefinition>460c4fd2f7bSAlex Crichton pub fn global_ptr(&self, index: DefinedGlobalIndex) -> NonNull<VMGlobalDefinition> { 461f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset_raw(self.offsets().vmctx_vmglobal_definition(index)) } 46272004aadSNick Fitzgerald } 46372004aadSNick Fitzgerald 46472004aadSNick Fitzgerald /// Get all globals within this instance. 46572004aadSNick Fitzgerald /// 46672004aadSNick Fitzgerald /// Returns both import and defined globals. 46772004aadSNick Fitzgerald /// 46872004aadSNick Fitzgerald /// Returns both exported and non-exported globals. 46972004aadSNick Fitzgerald /// 47072004aadSNick Fitzgerald /// Gives access to the full globals space. all_globals( &self, store: StoreId, ) -> impl ExactSizeIterator<Item = (GlobalIndex, crate::Global)> + '_4712b832281SAlex Crichton pub fn all_globals( 4722b832281SAlex Crichton &self, 4732b832281SAlex Crichton store: StoreId, 4742b832281SAlex Crichton ) -> impl ExactSizeIterator<Item = (GlobalIndex, crate::Global)> + '_ { 4752b832281SAlex Crichton let module = self.env_module(); 476c4fd2f7bSAlex Crichton module 477c4fd2f7bSAlex Crichton .globals 478c4fd2f7bSAlex Crichton .keys() 4792b832281SAlex Crichton .map(move |idx| (idx, self.get_exported_global(store, idx))) 48072004aadSNick Fitzgerald } 48172004aadSNick Fitzgerald 48272004aadSNick Fitzgerald /// Get the globals defined in this instance (not imported). defined_globals( &self, store: StoreId, ) -> impl ExactSizeIterator<Item = (DefinedGlobalIndex, crate::Global)> + '_483aad93a48SAlex Crichton pub fn defined_globals( 484aad93a48SAlex Crichton &self, 4852b832281SAlex Crichton store: StoreId, 4862b832281SAlex Crichton ) -> impl ExactSizeIterator<Item = (DefinedGlobalIndex, crate::Global)> + '_ { 4872b832281SAlex Crichton let module = self.env_module(); 4882b832281SAlex Crichton self.all_globals(store) 48972004aadSNick Fitzgerald .skip(module.num_imported_globals) 4902b832281SAlex Crichton .map(move |(i, global)| (module.defined_global_index(i).unwrap(), global)) 49172004aadSNick Fitzgerald } 49272004aadSNick Fitzgerald 49372004aadSNick Fitzgerald /// Return a pointer to the interrupts structure 49472004aadSNick Fitzgerald #[inline] vm_store_context(&self) -> NonNull<Option<VmPtr<VMStoreContext>>>495aad93a48SAlex Crichton pub fn vm_store_context(&self) -> NonNull<Option<VmPtr<VMStoreContext>>> { 496f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset_raw(self.offsets().ptr.vmctx_store_context()) } 49772004aadSNick Fitzgerald } 49872004aadSNick Fitzgerald 49972004aadSNick Fitzgerald /// Return a pointer to the global epoch counter used by this instance. 50010eda1cfSAlex Crichton #[cfg(target_has_atomic = "64")] epoch_ptr(self: Pin<&mut Self>) -> &mut Option<VmPtr<AtomicU64>>501aad93a48SAlex Crichton pub fn epoch_ptr(self: Pin<&mut Self>) -> &mut Option<VmPtr<AtomicU64>> { 502aad93a48SAlex Crichton let offset = self.offsets().ptr.vmctx_epoch_ptr(); 503aad93a48SAlex Crichton unsafe { self.vmctx_plus_offset_mut(offset) } 50472004aadSNick Fitzgerald } 50572004aadSNick Fitzgerald 50672004aadSNick Fitzgerald /// Return a pointer to the collector-specific heap data. gc_heap_data(self: Pin<&mut Self>) -> &mut Option<VmPtr<u8>>507aad93a48SAlex Crichton pub fn gc_heap_data(self: Pin<&mut Self>) -> &mut Option<VmPtr<u8>> { 508aad93a48SAlex Crichton let offset = self.offsets().ptr.vmctx_gc_heap_data(); 509aad93a48SAlex Crichton unsafe { self.vmctx_plus_offset_mut(offset) } 51072004aadSNick Fitzgerald } 51172004aadSNick Fitzgerald set_store(mut self: Pin<&mut Self>, store: &StoreOpaque)512e1f50aadSAlex Crichton pub(crate) unsafe fn set_store(mut self: Pin<&mut Self>, store: &StoreOpaque) { 513b052dee0SAlex Crichton // FIXME: should be more targeted ideally with the `unsafe` than just 514b052dee0SAlex Crichton // throwing this entire function in a large `unsafe` block. 515b052dee0SAlex Crichton unsafe { 516e1f50aadSAlex Crichton *self.as_mut().store_mut() = Some(VMStoreRawPtr(store.traitobj())); 517c2732814SNick Fitzgerald self.vm_store_context() 518c2732814SNick Fitzgerald .write(Some(store.vm_store_context_ptr().into())); 51910eda1cfSAlex Crichton #[cfg(target_has_atomic = "64")] 520f1111b91SAlex Crichton { 521aad93a48SAlex Crichton *self.as_mut().epoch_ptr() = 522aad93a48SAlex Crichton Some(NonNull::from(store.engine().epoch_counter()).into()); 523f1111b91SAlex Crichton } 524a4700cb7SNick Fitzgerald 525a4700cb7SNick Fitzgerald if self.env_module().needs_gc_heap { 526c6dddeafSAlex Crichton self.as_mut().set_gc_heap(Some(store.unwrap_gc_store())); 527a4700cb7SNick Fitzgerald } else { 528aad93a48SAlex Crichton self.as_mut().set_gc_heap(None); 529a4700cb7SNick Fitzgerald } 53072004aadSNick Fitzgerald } 531b052dee0SAlex Crichton } 53272004aadSNick Fitzgerald set_gc_heap(self: Pin<&mut Self>, gc_store: Option<&GcStore>)533aad93a48SAlex Crichton unsafe fn set_gc_heap(self: Pin<&mut Self>, gc_store: Option<&GcStore>) { 53472004aadSNick Fitzgerald if let Some(gc_store) = gc_store { 535b052dee0SAlex Crichton *self.gc_heap_data() = Some(unsafe { gc_store.gc_heap.vmctx_gc_heap_data().into() }); 53672004aadSNick Fitzgerald } else { 537f1111b91SAlex Crichton *self.gc_heap_data() = None; 53872004aadSNick Fitzgerald } 53972004aadSNick Fitzgerald } 54072004aadSNick Fitzgerald 54172004aadSNick Fitzgerald /// Return a reference to the vmctx used by compiled wasm code. 54272004aadSNick Fitzgerald #[inline] vmctx(&self) -> NonNull<VMContext>543b86b9682SAlex Crichton pub fn vmctx(&self) -> NonNull<VMContext> { 5447e28c254SAlex Crichton InstanceLayout::vmctx(self) 54572004aadSNick Fitzgerald } 54672004aadSNick Fitzgerald 547e012eedaSAlex Crichton /// Lookup a function by index. 548e012eedaSAlex Crichton /// 549e012eedaSAlex Crichton /// # Panics 550e012eedaSAlex Crichton /// 551e012eedaSAlex Crichton /// Panics if `index` is out of bounds for this instance. 5522b832281SAlex Crichton /// 5532b832281SAlex Crichton /// # Safety 5542b832281SAlex Crichton /// 5552b832281SAlex Crichton /// The `store` parameter must be the store that owns this instance and the 5562b832281SAlex Crichton /// functions that this instance can reference. get_exported_func( self: Pin<&mut Self>, registry: &ModuleRegistry, store: StoreId, index: FuncIndex, ) -> crate::Func5572b832281SAlex Crichton pub unsafe fn get_exported_func( 5582b832281SAlex Crichton self: Pin<&mut Self>, 55999ecf728SChris Fallin registry: &ModuleRegistry, 5602b832281SAlex Crichton store: StoreId, 5612b832281SAlex Crichton index: FuncIndex, 5622b832281SAlex Crichton ) -> crate::Func { 56399ecf728SChris Fallin let func_ref = self.get_func_ref(registry, index).unwrap(); 5642b832281SAlex Crichton 5652b832281SAlex Crichton // SAFETY: the validity of `func_ref` is guaranteed by the validity of 5662b832281SAlex Crichton // `self`, and the contract that `store` must own `func_ref` is a 5672b832281SAlex Crichton // contract of this function itself. 5682b832281SAlex Crichton unsafe { crate::Func::from_vm_func_ref(store, func_ref) } 56972004aadSNick Fitzgerald } 57072004aadSNick Fitzgerald 571aad93a48SAlex Crichton /// Lookup a table by index. 572aad93a48SAlex Crichton /// 573aad93a48SAlex Crichton /// # Panics 574aad93a48SAlex Crichton /// 575aad93a48SAlex Crichton /// Panics if `index` is out of bounds for this instance. get_exported_table(&self, store: StoreId, index: TableIndex) -> crate::Table5762b832281SAlex Crichton pub fn get_exported_table(&self, store: StoreId, index: TableIndex) -> crate::Table { 5772b832281SAlex Crichton let (id, def_index) = if let Some(def_index) = self.env_module().defined_table_index(index) 5782b832281SAlex Crichton { 5792b832281SAlex Crichton (self.id, def_index) 58072004aadSNick Fitzgerald } else { 58172004aadSNick Fitzgerald let import = self.imported_table(index); 5822b832281SAlex Crichton // SAFETY: validity of this `Instance` guarantees validity of the 5832b832281SAlex Crichton // `vmctx` pointer being read here to find the transitive 5842b832281SAlex Crichton // `InstanceId` that the import is associated with. 585f021346eSAlex Crichton let id = unsafe { self.sibling_vmctx(import.vmctx.as_non_null()).id }; 5862b832281SAlex Crichton (id, import.index) 58772004aadSNick Fitzgerald }; 5882b832281SAlex Crichton crate::Table::from_raw(StoreInstanceId::new(store, id), def_index) 58972004aadSNick Fitzgerald } 59072004aadSNick Fitzgerald 591aad93a48SAlex Crichton /// Lookup a memory by index. 592aad93a48SAlex Crichton /// 593aad93a48SAlex Crichton /// # Panics 594aad93a48SAlex Crichton /// 595aad93a48SAlex Crichton /// Panics if `index` is out-of-bounds for this instance. 5961fcd0933SAlex Crichton #[cfg_attr( 5971fcd0933SAlex Crichton not(feature = "threads"), 5981fcd0933SAlex Crichton expect(unused_variables, reason = "definitions cfg'd to dummy",) 5991fcd0933SAlex Crichton )] get_exported_memory(&self, store: StoreId, index: MemoryIndex) -> ExportMemory6001fcd0933SAlex Crichton pub fn get_exported_memory(&self, store: StoreId, index: MemoryIndex) -> ExportMemory { 6011fcd0933SAlex Crichton let module = self.env_module(); 6021fcd0933SAlex Crichton if module.memories[index].shared { 6031fcd0933SAlex Crichton let (memory, import) = 6041fcd0933SAlex Crichton if let Some(def_index) = self.env_module().defined_memory_index(index) { 6051fcd0933SAlex Crichton ( 6061fcd0933SAlex Crichton self.get_defined_memory(def_index), 6071fcd0933SAlex Crichton self.get_defined_memory_vmimport(def_index), 6081fcd0933SAlex Crichton ) 6091fcd0933SAlex Crichton } else { 6101fcd0933SAlex Crichton let import = self.imported_memory(index); 6111fcd0933SAlex Crichton // SAFETY: validity of this `Instance` guarantees validity of 6121fcd0933SAlex Crichton // the `vmctx` pointer being read here to find the transitive 6131fcd0933SAlex Crichton // `InstanceId` that the import is associated with. 6141fcd0933SAlex Crichton let instance = unsafe { self.sibling_vmctx(import.vmctx.as_non_null()) }; 6151fcd0933SAlex Crichton (instance.get_defined_memory(import.index), *import) 6161fcd0933SAlex Crichton }; 6171fcd0933SAlex Crichton 6181fcd0933SAlex Crichton let vm = memory.as_shared_memory().unwrap().clone(); 6191fcd0933SAlex Crichton ExportMemory::Shared(vm, import) 6201fcd0933SAlex Crichton } else { 6211fcd0933SAlex Crichton let (id, def_index) = 6221fcd0933SAlex Crichton if let Some(def_index) = self.env_module().defined_memory_index(index) { 6232b832281SAlex Crichton (self.id, def_index) 62472004aadSNick Fitzgerald } else { 62572004aadSNick Fitzgerald let import = self.imported_memory(index); 6262b832281SAlex Crichton // SAFETY: validity of this `Instance` guarantees validity of the 6272b832281SAlex Crichton // `vmctx` pointer being read here to find the transitive 6282b832281SAlex Crichton // `InstanceId` that the import is associated with. 629f021346eSAlex Crichton let id = unsafe { self.sibling_vmctx(import.vmctx.as_non_null()).id }; 6302b832281SAlex Crichton (id, import.index) 63172004aadSNick Fitzgerald }; 6321fcd0933SAlex Crichton 6331fcd0933SAlex Crichton // SAFETY: `from_raw` requires that the memory is not shared, which 6341fcd0933SAlex Crichton // was tested above in this if/else. 6351fcd0933SAlex Crichton let store_id = StoreInstanceId::new(store, id); 6361fcd0933SAlex Crichton ExportMemory::Unshared(unsafe { crate::Memory::from_raw(store_id, def_index) }) 6371fcd0933SAlex Crichton } 63872004aadSNick Fitzgerald } 63972004aadSNick Fitzgerald 640aef5eeb5SAlex Crichton /// Lookup a global by index. 641aef5eeb5SAlex Crichton /// 642aef5eeb5SAlex Crichton /// # Panics 643aef5eeb5SAlex Crichton /// 644aef5eeb5SAlex Crichton /// Panics if `index` is out-of-bounds for this instance. get_exported_global(&self, store: StoreId, index: GlobalIndex) -> crate::Global645aef5eeb5SAlex Crichton pub(crate) fn get_exported_global(&self, store: StoreId, index: GlobalIndex) -> crate::Global { 6462b832281SAlex Crichton // If this global is defined within this instance, then that's easy to 6472b832281SAlex Crichton // calculate the `Global`. 648c4fd2f7bSAlex Crichton if let Some(def_index) = self.env_module().defined_global_index(index) { 6492b832281SAlex Crichton let instance = StoreInstanceId::new(store, self.id); 6502b832281SAlex Crichton return crate::Global::from_core(instance, def_index); 651c4fd2f7bSAlex Crichton } 6522b832281SAlex Crichton 6532b832281SAlex Crichton // For imported globals it's required to match on the `kind` to 6542b832281SAlex Crichton // determine which `Global` constructor is going to be invoked. 6552b832281SAlex Crichton let import = self.imported_global(index); 6562b832281SAlex Crichton match import.kind { 6572b832281SAlex Crichton VMGlobalKind::Host(index) => crate::Global::from_host(store, index), 6582b832281SAlex Crichton VMGlobalKind::Instance(index) => { 6592b832281SAlex Crichton // SAFETY: validity of this `&Instance` means validity of its 6602b832281SAlex Crichton // imports meaning we can read the id of the vmctx within. 6612b832281SAlex Crichton let id = unsafe { 6622b832281SAlex Crichton let vmctx = VMContext::from_opaque(import.vmctx.unwrap().as_non_null()); 663f021346eSAlex Crichton self.sibling_vmctx(vmctx).id 6642b832281SAlex Crichton }; 6652b832281SAlex Crichton crate::Global::from_core(StoreInstanceId::new(store, id), index) 6662b832281SAlex Crichton } 6672b832281SAlex Crichton #[cfg(feature = "component-model")] 6682b832281SAlex Crichton VMGlobalKind::ComponentFlags(index) => { 6692b832281SAlex Crichton // SAFETY: validity of this `&Instance` means validity of its 6702b832281SAlex Crichton // imports meaning we can read the id of the vmctx within. 6712b832281SAlex Crichton let id = unsafe { 6722b832281SAlex Crichton let vmctx = super::component::VMComponentContext::from_opaque( 6732b832281SAlex Crichton import.vmctx.unwrap().as_non_null(), 6742b832281SAlex Crichton ); 6752b832281SAlex Crichton super::component::ComponentInstance::vmctx_instance_id(vmctx) 6762b832281SAlex Crichton }; 6772b832281SAlex Crichton crate::Global::from_component_flags( 6782b832281SAlex Crichton crate::component::store::StoreComponentInstanceId::new(store, id), 6792b832281SAlex Crichton index, 6802b832281SAlex Crichton ) 6812b832281SAlex Crichton } 682fae9e6afSJoel Dice #[cfg(feature = "component-model")] 683fae9e6afSJoel Dice VMGlobalKind::TaskMayBlock => { 684fae9e6afSJoel Dice // SAFETY: validity of this `&Instance` means validity of its 685fae9e6afSJoel Dice // imports meaning we can read the id of the vmctx within. 686fae9e6afSJoel Dice let id = unsafe { 687fae9e6afSJoel Dice let vmctx = super::component::VMComponentContext::from_opaque( 688fae9e6afSJoel Dice import.vmctx.unwrap().as_non_null(), 689fae9e6afSJoel Dice ); 690fae9e6afSJoel Dice super::component::ComponentInstance::vmctx_instance_id(vmctx) 691fae9e6afSJoel Dice }; 692fae9e6afSJoel Dice crate::Global::from_task_may_block( 693fae9e6afSJoel Dice crate::component::store::StoreComponentInstanceId::new(store, id), 694fae9e6afSJoel Dice ) 695fae9e6afSJoel Dice } 69672004aadSNick Fitzgerald } 69772004aadSNick Fitzgerald } 69872004aadSNick Fitzgerald 699eaa4632eSChris Fallin /// Get an exported tag by index. 700eaa4632eSChris Fallin /// 701eaa4632eSChris Fallin /// # Panics 702eaa4632eSChris Fallin /// 703eaa4632eSChris Fallin /// Panics if the index is out-of-range. get_exported_tag(&self, store: StoreId, index: TagIndex) -> crate::Tag704eaa4632eSChris Fallin pub fn get_exported_tag(&self, store: StoreId, index: TagIndex) -> crate::Tag { 7052b832281SAlex Crichton let (id, def_index) = if let Some(def_index) = self.env_module().defined_tag_index(index) { 7062b832281SAlex Crichton (self.id, def_index) 7070b4c754aSDaniel Hillerström } else { 708598562bdSAlex Crichton let import = self.imported_tag(index); 7092b832281SAlex Crichton // SAFETY: validity of this `Instance` guarantees validity of the 7102b832281SAlex Crichton // `vmctx` pointer being read here to find the transitive 7112b832281SAlex Crichton // `InstanceId` that the import is associated with. 712f021346eSAlex Crichton let id = unsafe { self.sibling_vmctx(import.vmctx.as_non_null()).id }; 7132b832281SAlex Crichton (id, import.index) 714598562bdSAlex Crichton }; 7152b832281SAlex Crichton crate::Tag::from_raw(StoreInstanceId::new(store, id), def_index) 7160b4c754aSDaniel Hillerström } 7170b4c754aSDaniel Hillerström 71872004aadSNick Fitzgerald /// Grow memory by the specified amount of pages. 71972004aadSNick Fitzgerald /// 72072004aadSNick Fitzgerald /// Returns `None` if memory can't be grown by the specified amount 72172004aadSNick Fitzgerald /// of pages. Returns `Some` with the old size in bytes if growth was 72272004aadSNick Fitzgerald /// successful. memory_grow( mut self: Pin<&mut Self>, limiter: Option<&mut StoreResourceLimiter<'_>>, idx: DefinedMemoryIndex, delta: u64, ) -> Result<Option<usize>, Error>723f881ab24SAlex Crichton pub(crate) async fn memory_grow( 724aad93a48SAlex Crichton mut self: Pin<&mut Self>, 725f881ab24SAlex Crichton limiter: Option<&mut StoreResourceLimiter<'_>>, 72672004aadSNick Fitzgerald idx: DefinedMemoryIndex, 72772004aadSNick Fitzgerald delta: u64, 72872004aadSNick Fitzgerald ) -> Result<Option<usize>, Error> { 729aad93a48SAlex Crichton let memory = &mut self.as_mut().memories_mut()[idx].1; 73072004aadSNick Fitzgerald 731f881ab24SAlex Crichton // SAFETY: this is the safe wrapper around `Memory::grow` because it 732f881ab24SAlex Crichton // automatically updates the `VMMemoryDefinition` in this instance after 733f881ab24SAlex Crichton // a growth operation below. 734f881ab24SAlex Crichton let result = unsafe { memory.grow(delta, limiter).await }; 73572004aadSNick Fitzgerald 73672004aadSNick Fitzgerald // Update the state used by a non-shared Wasm memory in case the base 73772004aadSNick Fitzgerald // pointer and/or the length changed. 73872004aadSNick Fitzgerald if memory.as_shared_memory().is_none() { 73972004aadSNick Fitzgerald let vmmemory = memory.vmmemory(); 74072004aadSNick Fitzgerald self.set_memory(idx, vmmemory); 74172004aadSNick Fitzgerald } 74272004aadSNick Fitzgerald 74372004aadSNick Fitzgerald result 74472004aadSNick Fitzgerald } 74572004aadSNick Fitzgerald table_element_type( self: Pin<&mut Self>, table_index: TableIndex, ) -> TableElementType746aad93a48SAlex Crichton pub(crate) fn table_element_type( 747aad93a48SAlex Crichton self: Pin<&mut Self>, 748aad93a48SAlex Crichton table_index: TableIndex, 749aad93a48SAlex Crichton ) -> TableElementType { 750f021346eSAlex Crichton self.get_table(table_index).element_type() 75172004aadSNick Fitzgerald } 75272004aadSNick Fitzgerald 753aef5eeb5SAlex Crichton /// Performs a grow operation on the `table_index` specified using `grow`. 75472004aadSNick Fitzgerald /// 755aef5eeb5SAlex Crichton /// This will handle updating the VMTableDefinition internally as necessary. defined_table_grow( mut self: Pin<&mut Self>, table_index: DefinedTableIndex, grow: impl AsyncFnOnce(&mut Table) -> Result<Option<usize>>, ) -> Result<Option<usize>>7565f7cf53eSAlex Crichton pub(crate) async fn defined_table_grow( 757aad93a48SAlex Crichton mut self: Pin<&mut Self>, 75872004aadSNick Fitzgerald table_index: DefinedTableIndex, 7595f7cf53eSAlex Crichton grow: impl AsyncFnOnce(&mut Table) -> Result<Option<usize>>, 760aef5eeb5SAlex Crichton ) -> Result<Option<usize>> { 761aef5eeb5SAlex Crichton let table = self.as_mut().get_defined_table(table_index); 7625f7cf53eSAlex Crichton let result = grow(table).await; 763aad93a48SAlex Crichton let element = table.vmtable(); 76472004aadSNick Fitzgerald self.set_table(table_index, element); 76572004aadSNick Fitzgerald result 76672004aadSNick Fitzgerald } 76772004aadSNick Fitzgerald alloc_layout(offsets: &VMOffsets<HostPtr>) -> Layout76872004aadSNick Fitzgerald fn alloc_layout(offsets: &VMOffsets<HostPtr>) -> Layout { 76972004aadSNick Fitzgerald let size = mem::size_of::<Self>() 77072004aadSNick Fitzgerald .checked_add(usize::try_from(offsets.size_of_vmctx()).unwrap()) 77172004aadSNick Fitzgerald .unwrap(); 77272004aadSNick Fitzgerald let align = mem::align_of::<Self>(); 77372004aadSNick Fitzgerald Layout::from_size_align(size, align).unwrap() 77472004aadSNick Fitzgerald } 77572004aadSNick Fitzgerald type_ids_array(&self) -> NonNull<VmPtr<VMSharedTypeIndex>>776aad93a48SAlex Crichton fn type_ids_array(&self) -> NonNull<VmPtr<VMSharedTypeIndex>> { 777f1111b91SAlex Crichton unsafe { self.vmctx_plus_offset_raw(self.offsets().ptr.vmctx_type_ids_array()) } 778b86b9682SAlex Crichton } 779b86b9682SAlex Crichton 78072004aadSNick Fitzgerald /// Construct a new VMFuncRef for the given function 78172004aadSNick Fitzgerald /// (imported or defined in this module) and store into the given 78272004aadSNick Fitzgerald /// location. Used during lazy initialization. 78372004aadSNick Fitzgerald /// 78472004aadSNick Fitzgerald /// Note that our current lazy-init scheme actually calls this every 78572004aadSNick Fitzgerald /// time the funcref pointer is fetched; this turns out to be better 78672004aadSNick Fitzgerald /// than tracking state related to whether it's been initialized 78772004aadSNick Fitzgerald /// before, because resetting that state on (re)instantiation is 78872004aadSNick Fitzgerald /// very expensive if there are many funcrefs. 789078bc37bSAlex Crichton /// 790078bc37bSAlex Crichton /// # Safety 791078bc37bSAlex Crichton /// 792078bc37bSAlex Crichton /// This functions requires that `into` is a valid pointer. construct_func_ref( self: Pin<&mut Self>, registry: &ModuleRegistry, index: FuncIndex, type_index: VMSharedTypeIndex, into: *mut VMFuncRef, )793078bc37bSAlex Crichton unsafe fn construct_func_ref( 794078bc37bSAlex Crichton self: Pin<&mut Self>, 79599ecf728SChris Fallin registry: &ModuleRegistry, 79672004aadSNick Fitzgerald index: FuncIndex, 797cb235ecfSNick Fitzgerald type_index: VMSharedTypeIndex, 79872004aadSNick Fitzgerald into: *mut VMFuncRef, 79972004aadSNick Fitzgerald ) { 80099ecf728SChris Fallin let module_with_code = ModuleWithCode::in_store( 80199ecf728SChris Fallin registry, 80299ecf728SChris Fallin self.runtime_module() 80399ecf728SChris Fallin .expect("funcref impossible in fake module"), 80499ecf728SChris Fallin ) 80599ecf728SChris Fallin .expect("module not in store"); 80699ecf728SChris Fallin 8072bdae8b6SNick Fitzgerald let func_ref = if let Some(def_index) = self.env_module().defined_func_index(index) { 80872004aadSNick Fitzgerald VMFuncRef { 80999ecf728SChris Fallin array_call: NonNull::from( 81099ecf728SChris Fallin module_with_code 81172004aadSNick Fitzgerald .array_to_wasm_trampoline(def_index) 81299ecf728SChris Fallin .expect("should have array-to-Wasm trampoline for escaping function"), 81399ecf728SChris Fallin ) 81499ecf728SChris Fallin .cast() 815b86b9682SAlex Crichton .into(), 81699ecf728SChris Fallin wasm_call: Some( 81799ecf728SChris Fallin NonNull::new( 81899ecf728SChris Fallin module_with_code 81999ecf728SChris Fallin .finished_function(def_index) 82099ecf728SChris Fallin .as_ptr() 82199ecf728SChris Fallin .cast::<VMWasmCallFunction>() 82299ecf728SChris Fallin .cast_mut(), 82399ecf728SChris Fallin ) 82499ecf728SChris Fallin .unwrap() 82599ecf728SChris Fallin .into(), 82699ecf728SChris Fallin ), 827b86b9682SAlex Crichton vmctx: VMOpaqueContext::from_vmcontext(self.vmctx()).into(), 82872004aadSNick Fitzgerald type_index, 82972004aadSNick Fitzgerald } 83072004aadSNick Fitzgerald } else { 83172004aadSNick Fitzgerald let import = self.imported_function(index); 83272004aadSNick Fitzgerald VMFuncRef { 83372004aadSNick Fitzgerald array_call: import.array_call, 83472004aadSNick Fitzgerald wasm_call: Some(import.wasm_call), 83572004aadSNick Fitzgerald vmctx: import.vmctx, 83672004aadSNick Fitzgerald type_index, 83772004aadSNick Fitzgerald } 83872004aadSNick Fitzgerald }; 83972004aadSNick Fitzgerald 840078bc37bSAlex Crichton // SAFETY: the unsafe contract here is forwarded to callers of this 841078bc37bSAlex Crichton // function. 84272004aadSNick Fitzgerald unsafe { 84381a89169SAlex Crichton ptr::write(into, func_ref); 84472004aadSNick Fitzgerald } 84572004aadSNick Fitzgerald } 84672004aadSNick Fitzgerald 84772004aadSNick Fitzgerald /// Get a `&VMFuncRef` for the given `FuncIndex`. 84872004aadSNick Fitzgerald /// 84972004aadSNick Fitzgerald /// Returns `None` if the index is the reserved index value. 85072004aadSNick Fitzgerald /// 85172004aadSNick Fitzgerald /// The returned reference is a stable reference that won't be moved and can 85272004aadSNick Fitzgerald /// be passed into JIT code. get_func_ref( self: Pin<&mut Self>, registry: &ModuleRegistry, index: FuncIndex, ) -> Option<NonNull<VMFuncRef>>853078bc37bSAlex Crichton pub(crate) fn get_func_ref( 854078bc37bSAlex Crichton self: Pin<&mut Self>, 85599ecf728SChris Fallin registry: &ModuleRegistry, 856078bc37bSAlex Crichton index: FuncIndex, 857078bc37bSAlex Crichton ) -> Option<NonNull<VMFuncRef>> { 85872004aadSNick Fitzgerald if index == FuncIndex::reserved_value() { 85972004aadSNick Fitzgerald return None; 86072004aadSNick Fitzgerald } 86172004aadSNick Fitzgerald 86272004aadSNick Fitzgerald // For now, we eagerly initialize an funcref struct in-place 86372004aadSNick Fitzgerald // whenever asked for a reference to it. This is mostly 86472004aadSNick Fitzgerald // fine, because in practice each funcref is unlikely to be 86572004aadSNick Fitzgerald // requested more than a few times: once-ish for funcref 86672004aadSNick Fitzgerald // tables used for call_indirect (the usual compilation 86772004aadSNick Fitzgerald // strategy places each function in the table at most once), 86872004aadSNick Fitzgerald // and once or a few times when fetching exports via API. 86972004aadSNick Fitzgerald // Note that for any case driven by table accesses, the lazy 87072004aadSNick Fitzgerald // table init behaves like a higher-level cache layer that 87172004aadSNick Fitzgerald // protects this initialization from happening multiple 87272004aadSNick Fitzgerald // times, via that particular table at least. 87372004aadSNick Fitzgerald // 87472004aadSNick Fitzgerald // When `ref.func` becomes more commonly used or if we 87572004aadSNick Fitzgerald // otherwise see a use-case where this becomes a hotpath, 87672004aadSNick Fitzgerald // we can reconsider by using some state to track 87772004aadSNick Fitzgerald // "uninitialized" explicitly, for example by zeroing the 87872004aadSNick Fitzgerald // funcrefs (perhaps together with other 87972004aadSNick Fitzgerald // zeroed-at-instantiate-time state) or using a separate 88072004aadSNick Fitzgerald // is-initialized bitmap. 88172004aadSNick Fitzgerald // 88272004aadSNick Fitzgerald // We arrived at this design because zeroing memory is 88372004aadSNick Fitzgerald // expensive, so it's better for instantiation performance 88472004aadSNick Fitzgerald // if we don't have to track "is-initialized" state at 88572004aadSNick Fitzgerald // all! 8862bdae8b6SNick Fitzgerald let func = &self.env_module().functions[index]; 887cb235ecfSNick Fitzgerald let sig = func.signature.unwrap_engine_type_index(); 888078bc37bSAlex Crichton 889078bc37bSAlex Crichton // SAFETY: the offset calculated here should be correct with 890078bc37bSAlex Crichton // `self.offsets` 891078bc37bSAlex Crichton let func_ref = unsafe { 892078bc37bSAlex Crichton self.vmctx_plus_offset_raw::<VMFuncRef>(self.offsets().vmctx_func_ref(func.func_ref)) 893078bc37bSAlex Crichton }; 894078bc37bSAlex Crichton 895078bc37bSAlex Crichton // SAFETY: the `func_ref` ptr should be valid as it's within our 896078bc37bSAlex Crichton // `VMContext` area. 897078bc37bSAlex Crichton unsafe { 89899ecf728SChris Fallin self.construct_func_ref(registry, index, sig, func_ref.as_ptr()); 899078bc37bSAlex Crichton } 90072004aadSNick Fitzgerald 901b86b9682SAlex Crichton Some(func_ref) 90272004aadSNick Fitzgerald } 90372004aadSNick Fitzgerald 904ec3b2d22SNick Fitzgerald /// Get the passive elements segment at the given index. 905ec3b2d22SNick Fitzgerald /// 906ec3b2d22SNick Fitzgerald /// Returns an empty segment if the index is out of bounds or if the segment 907ec3b2d22SNick Fitzgerald /// has been dropped. 908ec3b2d22SNick Fitzgerald /// 909ec3b2d22SNick Fitzgerald /// The `storage` parameter should always be `None`; it is a bit of a hack 910ec3b2d22SNick Fitzgerald /// to work around lifetime issues. passive_element_segment<'a>( &self, storage: &'a mut Option<(Arc<wasmtime_environ::Module>, TableSegmentElements)>, elem_index: ElemIndex, ) -> &'a TableSegmentElements911ec3b2d22SNick Fitzgerald pub(crate) fn passive_element_segment<'a>( 912ec3b2d22SNick Fitzgerald &self, 913ec3b2d22SNick Fitzgerald storage: &'a mut Option<(Arc<wasmtime_environ::Module>, TableSegmentElements)>, 914ec3b2d22SNick Fitzgerald elem_index: ElemIndex, 915ec3b2d22SNick Fitzgerald ) -> &'a TableSegmentElements { 916ec3b2d22SNick Fitzgerald debug_assert!(storage.is_none()); 917ec3b2d22SNick Fitzgerald *storage = Some(( 918ec3b2d22SNick Fitzgerald // TODO: this `clone()` shouldn't be necessary but is used for now to 919ec3b2d22SNick Fitzgerald // inform `rustc` that the lifetime of the elements here are 920ec3b2d22SNick Fitzgerald // disconnected from the lifetime of `self`. 921ec3b2d22SNick Fitzgerald self.env_module().clone(), 922ec3b2d22SNick Fitzgerald // NB: fall back to an expressions-based list of elements which 923ec3b2d22SNick Fitzgerald // doesn't have static type information (as opposed to 924ec3b2d22SNick Fitzgerald // `TableSegmentElements::Functions`) since we don't know what type 925ec3b2d22SNick Fitzgerald // is needed in the caller's context. Let the type be inferred by 926ec3b2d22SNick Fitzgerald // how they use the segment. 927ec3b2d22SNick Fitzgerald TableSegmentElements::Expressions(Box::new([])), 928ec3b2d22SNick Fitzgerald )); 929ec3b2d22SNick Fitzgerald let (module, empty) = storage.as_ref().unwrap(); 930ec3b2d22SNick Fitzgerald 931ec3b2d22SNick Fitzgerald match module.passive_elements_map.get(&elem_index) { 932ec3b2d22SNick Fitzgerald Some(index) if !self.dropped_elements.contains(elem_index) => { 933ec3b2d22SNick Fitzgerald &module.passive_elements[*index] 934ec3b2d22SNick Fitzgerald } 935ec3b2d22SNick Fitzgerald _ => empty, 936ec3b2d22SNick Fitzgerald } 937ec3b2d22SNick Fitzgerald } 938ec3b2d22SNick Fitzgerald 93972004aadSNick Fitzgerald /// The `table.init` operation: initializes a portion of a table with a 94072004aadSNick Fitzgerald /// passive element. 94172004aadSNick Fitzgerald /// 94272004aadSNick Fitzgerald /// # Errors 94372004aadSNick Fitzgerald /// 94472004aadSNick Fitzgerald /// Returns a `Trap` error when the range within the table is out of bounds 94572004aadSNick Fitzgerald /// or the range within the passive element is out of bounds. table_init( store: &mut StoreOpaque, limiter: Option<&mut StoreResourceLimiter<'_>>, asyncness: Asyncness, instance: InstanceId, table_index: TableIndex, elem_index: ElemIndex, dst: u64, src: u64, len: u64, ) -> Result<()>946d1397130SAlex Crichton pub(crate) async fn table_init( 9478818b251SNick Fitzgerald store: &mut StoreOpaque, 948155ea7fcSAlex Crichton limiter: Option<&mut StoreResourceLimiter<'_>>, 949cc8d04f4SAlex Crichton asyncness: Asyncness, 950900370bcSAlex Crichton instance: InstanceId, 95172004aadSNick Fitzgerald table_index: TableIndex, 95272004aadSNick Fitzgerald elem_index: ElemIndex, 953df69b9a7SLinwei Shang dst: u64, 954df69b9a7SLinwei Shang src: u64, 955df69b9a7SLinwei Shang len: u64, 95679419198SAlex Crichton ) -> Result<()> { 957ec3b2d22SNick Fitzgerald let mut storage = None; 958900370bcSAlex Crichton let elements = store 959900370bcSAlex Crichton .instance(instance) 960900370bcSAlex Crichton .passive_element_segment(&mut storage, elem_index); 96172004aadSNick Fitzgerald let mut const_evaluator = ConstExprEvaluator::default(); 962aad93a48SAlex Crichton Self::table_init_segment( 9638818b251SNick Fitzgerald store, 964155ea7fcSAlex Crichton limiter, 965cc8d04f4SAlex Crichton asyncness, 966900370bcSAlex Crichton instance, 9678818b251SNick Fitzgerald &mut const_evaluator, 9688818b251SNick Fitzgerald table_index, 9698818b251SNick Fitzgerald elements, 9708818b251SNick Fitzgerald dst, 9718818b251SNick Fitzgerald src, 9728818b251SNick Fitzgerald len, 9738818b251SNick Fitzgerald ) 974d1397130SAlex Crichton .await 97572004aadSNick Fitzgerald } 97672004aadSNick Fitzgerald table_init_segment( store: &mut StoreOpaque, mut limiter: Option<&mut StoreResourceLimiter<'_>>, asyncness: Asyncness, elements_instance_id: InstanceId, const_evaluator: &mut ConstExprEvaluator, table_index: TableIndex, elements: &TableSegmentElements, dst: u64, src: u64, len: u64, ) -> Result<()>977d1397130SAlex Crichton pub(crate) async fn table_init_segment( 9788818b251SNick Fitzgerald store: &mut StoreOpaque, 979155ea7fcSAlex Crichton mut limiter: Option<&mut StoreResourceLimiter<'_>>, 980cc8d04f4SAlex Crichton asyncness: Asyncness, 981f021346eSAlex Crichton elements_instance_id: InstanceId, 98272004aadSNick Fitzgerald const_evaluator: &mut ConstExprEvaluator, 98372004aadSNick Fitzgerald table_index: TableIndex, 98472004aadSNick Fitzgerald elements: &TableSegmentElements, 985df69b9a7SLinwei Shang dst: u64, 986df69b9a7SLinwei Shang src: u64, 987df69b9a7SLinwei Shang len: u64, 98879419198SAlex Crichton ) -> Result<()> { 98972004aadSNick Fitzgerald // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-table-init 99072004aadSNick Fitzgerald 991aef5eeb5SAlex Crichton let store_id = store.id(); 992f021346eSAlex Crichton let elements_instance = store.instance_mut(elements_instance_id); 993aef5eeb5SAlex Crichton let table = elements_instance.get_exported_table(store_id, table_index); 994aef5eeb5SAlex Crichton let table_size = table._size(store); 995aef5eeb5SAlex Crichton 996aef5eeb5SAlex Crichton // Perform a bounds check on the table being written to. This is done by 997aef5eeb5SAlex Crichton // ensuring that `dst + len <= table.size()` via checked arithmetic. 998aef5eeb5SAlex Crichton // 999aef5eeb5SAlex Crichton // Note that the bounds check for the element segment happens below when 1000aef5eeb5SAlex Crichton // the original segment is sliced via `src` and `len`. 1001aef5eeb5SAlex Crichton table_size 1002aef5eeb5SAlex Crichton .checked_sub(dst) 1003aef5eeb5SAlex Crichton .and_then(|i| i.checked_sub(len)) 1004aef5eeb5SAlex Crichton .ok_or(Trap::TableOutOfBounds)?; 1005f021346eSAlex Crichton 100672004aadSNick Fitzgerald let src = usize::try_from(src).map_err(|_| Trap::TableOutOfBounds)?; 100772004aadSNick Fitzgerald let len = usize::try_from(len).map_err(|_| Trap::TableOutOfBounds)?; 1008f021346eSAlex Crichton 1009aef5eeb5SAlex Crichton let positions = dst..dst + u64::try_from(len).unwrap(); 101072004aadSNick Fitzgerald match elements { 101172004aadSNick Fitzgerald TableSegmentElements::Functions(funcs) => { 101272004aadSNick Fitzgerald let elements = funcs 101372004aadSNick Fitzgerald .get(src..) 101472004aadSNick Fitzgerald .and_then(|s| s.get(..len)) 101572004aadSNick Fitzgerald .ok_or(Trap::TableOutOfBounds)?; 1016aef5eeb5SAlex Crichton for (i, func_idx) in positions.zip(elements) { 101799ecf728SChris Fallin let (instance, registry) = 101899ecf728SChris Fallin store.instance_and_module_registry_mut(elements_instance_id); 1019aef5eeb5SAlex Crichton // SAFETY: the `store_id` passed to `get_exported_func` is 1020aef5eeb5SAlex Crichton // indeed the store that owns the function. 102199ecf728SChris Fallin let func = unsafe { instance.get_exported_func(registry, store_id, *func_idx) }; 1022aef5eeb5SAlex Crichton table.set_(store, i, func.into()).unwrap(); 1023aef5eeb5SAlex Crichton } 102472004aadSNick Fitzgerald } 102572004aadSNick Fitzgerald TableSegmentElements::Expressions(exprs) => { 1026aef5eeb5SAlex Crichton let mut store = OpaqueRootScope::new(store); 102772004aadSNick Fitzgerald let exprs = exprs 102872004aadSNick Fitzgerald .get(src..) 102972004aadSNick Fitzgerald .and_then(|s| s.get(..len)) 103072004aadSNick Fitzgerald .ok_or(Trap::TableOutOfBounds)?; 1031cc8d04f4SAlex Crichton let mut context = ConstEvalContext::new(elements_instance_id, asyncness); 1032aef5eeb5SAlex Crichton for (i, expr) in positions.zip(exprs) { 1033d1397130SAlex Crichton let element = const_evaluator 1034155ea7fcSAlex Crichton .eval(&mut store, limiter.as_deref_mut(), &mut context, expr) 103579419198SAlex Crichton .await?; 1036aef5eeb5SAlex Crichton table.set_(&mut store, i, element.ref_().unwrap()).unwrap(); 103772004aadSNick Fitzgerald } 103872004aadSNick Fitzgerald } 103972004aadSNick Fitzgerald } 104072004aadSNick Fitzgerald 104172004aadSNick Fitzgerald Ok(()) 104272004aadSNick Fitzgerald } 104372004aadSNick Fitzgerald 104472004aadSNick Fitzgerald /// Drop an element. elem_drop( self: Pin<&mut Self>, elem_index: ElemIndex, ) -> Result<(), OutOfMemory>1045a465eabfSNick Fitzgerald pub(crate) fn elem_drop( 1046a465eabfSNick Fitzgerald self: Pin<&mut Self>, 1047a465eabfSNick Fitzgerald elem_index: ElemIndex, 1048a465eabfSNick Fitzgerald ) -> Result<(), OutOfMemory> { 104972004aadSNick Fitzgerald // https://webassembly.github.io/reference-types/core/exec/instructions.html#exec-elem-drop 105072004aadSNick Fitzgerald 1051a465eabfSNick Fitzgerald self.dropped_elements_mut().insert(elem_index)?; 105272004aadSNick Fitzgerald 105372004aadSNick Fitzgerald // Note that we don't check that we actually removed a segment because 105472004aadSNick Fitzgerald // dropping a non-passive segment is a no-op (not a trap). 1055a465eabfSNick Fitzgerald 1056a465eabfSNick Fitzgerald Ok(()) 105772004aadSNick Fitzgerald } 105872004aadSNick Fitzgerald 105972004aadSNick Fitzgerald /// Get a locally-defined memory. get_defined_memory_mut(self: Pin<&mut Self>, index: DefinedMemoryIndex) -> &mut Memory10602b832281SAlex Crichton pub fn get_defined_memory_mut(self: Pin<&mut Self>, index: DefinedMemoryIndex) -> &mut Memory { 1061ab76f64bSAlex Crichton &mut self.memories_mut()[index].1 106272004aadSNick Fitzgerald } 106372004aadSNick Fitzgerald 10642b832281SAlex Crichton /// Get a locally-defined memory. get_defined_memory(&self, index: DefinedMemoryIndex) -> &Memory10652b832281SAlex Crichton pub fn get_defined_memory(&self, index: DefinedMemoryIndex) -> &Memory { 10662b832281SAlex Crichton &self.memories[index].1 10672b832281SAlex Crichton } 10682b832281SAlex Crichton get_defined_memory_vmimport(&self, index: DefinedMemoryIndex) -> VMMemoryImport10691fcd0933SAlex Crichton pub fn get_defined_memory_vmimport(&self, index: DefinedMemoryIndex) -> VMMemoryImport { 10701fcd0933SAlex Crichton crate::runtime::vm::VMMemoryImport { 10711fcd0933SAlex Crichton from: self.memory_ptr(index).into(), 10721fcd0933SAlex Crichton vmctx: self.vmctx().into(), 10731fcd0933SAlex Crichton index, 10741fcd0933SAlex Crichton } 10751fcd0933SAlex Crichton } 10761fcd0933SAlex Crichton 107772004aadSNick Fitzgerald /// Do a `memory.copy` 107872004aadSNick Fitzgerald /// 107972004aadSNick Fitzgerald /// # Errors 108072004aadSNick Fitzgerald /// 108172004aadSNick Fitzgerald /// Returns a `Trap` error when the source or destination ranges are out of 108272004aadSNick Fitzgerald /// bounds. memory_copy( self: Pin<&mut Self>, dst_index: MemoryIndex, dst: u64, src_index: MemoryIndex, src: u64, len: u64, ) -> Result<(), Trap>108372004aadSNick Fitzgerald pub(crate) fn memory_copy( 1084aad93a48SAlex Crichton self: Pin<&mut Self>, 108572004aadSNick Fitzgerald dst_index: MemoryIndex, 108672004aadSNick Fitzgerald dst: u64, 108772004aadSNick Fitzgerald src_index: MemoryIndex, 108872004aadSNick Fitzgerald src: u64, 108972004aadSNick Fitzgerald len: u64, 109072004aadSNick Fitzgerald ) -> Result<(), Trap> { 109172004aadSNick Fitzgerald // https://webassembly.github.io/reference-types/core/exec/instructions.html#exec-memory-copy 109272004aadSNick Fitzgerald 109372004aadSNick Fitzgerald let src_mem = self.get_memory(src_index); 109472004aadSNick Fitzgerald let dst_mem = self.get_memory(dst_index); 109572004aadSNick Fitzgerald 109672004aadSNick Fitzgerald let src = self.validate_inbounds(src_mem.current_length(), src, len)?; 109772004aadSNick Fitzgerald let dst = self.validate_inbounds(dst_mem.current_length(), dst, len)?; 10980bce0968SAlex Crichton let len = usize::try_from(len).unwrap(); 109972004aadSNick Fitzgerald 110072004aadSNick Fitzgerald // Bounds and casts are checked above, by this point we know that 110172004aadSNick Fitzgerald // everything is safe. 110272004aadSNick Fitzgerald unsafe { 1103b86b9682SAlex Crichton let dst = dst_mem.base.as_ptr().add(dst); 1104b86b9682SAlex Crichton let src = src_mem.base.as_ptr().add(src); 110572004aadSNick Fitzgerald // FIXME audit whether this is safe in the presence of shared memory 110672004aadSNick Fitzgerald // (https://github.com/bytecodealliance/wasmtime/issues/4203). 11070bce0968SAlex Crichton ptr::copy(src, dst, len); 110872004aadSNick Fitzgerald } 110972004aadSNick Fitzgerald 111072004aadSNick Fitzgerald Ok(()) 111172004aadSNick Fitzgerald } 111272004aadSNick Fitzgerald validate_inbounds(&self, max: usize, ptr: u64, len: u64) -> Result<usize, Trap>111372004aadSNick Fitzgerald fn validate_inbounds(&self, max: usize, ptr: u64, len: u64) -> Result<usize, Trap> { 111472004aadSNick Fitzgerald let oob = || Trap::MemoryOutOfBounds; 111572004aadSNick Fitzgerald let end = ptr 111672004aadSNick Fitzgerald .checked_add(len) 111772004aadSNick Fitzgerald .and_then(|i| usize::try_from(i).ok()) 111872004aadSNick Fitzgerald .ok_or_else(oob)?; 111972004aadSNick Fitzgerald if end > max { 112072004aadSNick Fitzgerald Err(oob()) 112172004aadSNick Fitzgerald } else { 11220bce0968SAlex Crichton Ok(ptr.try_into().unwrap()) 112372004aadSNick Fitzgerald } 112472004aadSNick Fitzgerald } 112572004aadSNick Fitzgerald 112672004aadSNick Fitzgerald /// Perform the `memory.fill` operation on a locally defined memory. 112772004aadSNick Fitzgerald /// 112872004aadSNick Fitzgerald /// # Errors 112972004aadSNick Fitzgerald /// 113072004aadSNick Fitzgerald /// Returns a `Trap` error if the memory range is out of bounds. memory_fill( self: Pin<&mut Self>, memory_index: DefinedMemoryIndex, dst: u64, val: u8, len: u64, ) -> Result<(), Trap>113172004aadSNick Fitzgerald pub(crate) fn memory_fill( 1132aad93a48SAlex Crichton self: Pin<&mut Self>, 1133ab76f64bSAlex Crichton memory_index: DefinedMemoryIndex, 113472004aadSNick Fitzgerald dst: u64, 113572004aadSNick Fitzgerald val: u8, 113672004aadSNick Fitzgerald len: u64, 113772004aadSNick Fitzgerald ) -> Result<(), Trap> { 1138ab76f64bSAlex Crichton let memory_index = self.env_module().memory_index(memory_index); 113972004aadSNick Fitzgerald let memory = self.get_memory(memory_index); 114072004aadSNick Fitzgerald let dst = self.validate_inbounds(memory.current_length(), dst, len)?; 11410bce0968SAlex Crichton let len = usize::try_from(len).unwrap(); 114272004aadSNick Fitzgerald 114372004aadSNick Fitzgerald // Bounds and casts are checked above, by this point we know that 114472004aadSNick Fitzgerald // everything is safe. 114572004aadSNick Fitzgerald unsafe { 1146b86b9682SAlex Crichton let dst = memory.base.as_ptr().add(dst); 114772004aadSNick Fitzgerald // FIXME audit whether this is safe in the presence of shared memory 114872004aadSNick Fitzgerald // (https://github.com/bytecodealliance/wasmtime/issues/4203). 11490bce0968SAlex Crichton ptr::write_bytes(dst, val, len); 115072004aadSNick Fitzgerald } 115172004aadSNick Fitzgerald 115272004aadSNick Fitzgerald Ok(()) 115372004aadSNick Fitzgerald } 115472004aadSNick Fitzgerald 1155ec3b2d22SNick Fitzgerald /// Get the internal storage range of a particular Wasm data segment. wasm_data_range(&self, index: DataIndex) -> Range<u32>1156ec3b2d22SNick Fitzgerald pub(crate) fn wasm_data_range(&self, index: DataIndex) -> Range<u32> { 1157ec3b2d22SNick Fitzgerald match self.env_module().passive_data_map.get(&index) { 1158ec3b2d22SNick Fitzgerald Some(range) if !self.dropped_data.contains(index) => range.clone(), 1159ec3b2d22SNick Fitzgerald _ => 0..0, 1160ec3b2d22SNick Fitzgerald } 1161ec3b2d22SNick Fitzgerald } 1162ec3b2d22SNick Fitzgerald 1163ec3b2d22SNick Fitzgerald /// Given an internal storage range of a Wasm data segment (or subset of a 1164ec3b2d22SNick Fitzgerald /// Wasm data segment), get the data's raw bytes. wasm_data(&self, range: Range<u32>) -> &[u8]1165ec3b2d22SNick Fitzgerald pub(crate) fn wasm_data(&self, range: Range<u32>) -> &[u8] { 1166ec3b2d22SNick Fitzgerald let start = usize::try_from(range.start).unwrap(); 1167ec3b2d22SNick Fitzgerald let end = usize::try_from(range.end).unwrap(); 1168ec3b2d22SNick Fitzgerald &self.runtime_info.wasm_data()[start..end] 1169ec3b2d22SNick Fitzgerald } 1170ec3b2d22SNick Fitzgerald 117172004aadSNick Fitzgerald /// Performs the `memory.init` operation. 117272004aadSNick Fitzgerald /// 117372004aadSNick Fitzgerald /// # Errors 117472004aadSNick Fitzgerald /// 117572004aadSNick Fitzgerald /// Returns a `Trap` error if the destination range is out of this module's 117672004aadSNick Fitzgerald /// memory's bounds or if the source range is outside the data segment's 117772004aadSNick Fitzgerald /// bounds. memory_init( self: Pin<&mut Self>, memory_index: MemoryIndex, data_index: DataIndex, dst: u64, src: u32, len: u32, ) -> Result<(), Trap>117872004aadSNick Fitzgerald pub(crate) fn memory_init( 1179aad93a48SAlex Crichton self: Pin<&mut Self>, 118072004aadSNick Fitzgerald memory_index: MemoryIndex, 118172004aadSNick Fitzgerald data_index: DataIndex, 118272004aadSNick Fitzgerald dst: u64, 118372004aadSNick Fitzgerald src: u32, 118472004aadSNick Fitzgerald len: u32, 118572004aadSNick Fitzgerald ) -> Result<(), Trap> { 1186ec3b2d22SNick Fitzgerald let range = self.wasm_data_range(data_index); 118772004aadSNick Fitzgerald self.memory_init_segment(memory_index, range, dst, src, len) 118872004aadSNick Fitzgerald } 118972004aadSNick Fitzgerald memory_init_segment( self: Pin<&mut Self>, memory_index: MemoryIndex, range: Range<u32>, dst: u64, src: u32, len: u32, ) -> Result<(), Trap>119072004aadSNick Fitzgerald pub(crate) fn memory_init_segment( 1191aad93a48SAlex Crichton self: Pin<&mut Self>, 119272004aadSNick Fitzgerald memory_index: MemoryIndex, 119372004aadSNick Fitzgerald range: Range<u32>, 119472004aadSNick Fitzgerald dst: u64, 119572004aadSNick Fitzgerald src: u32, 119672004aadSNick Fitzgerald len: u32, 119772004aadSNick Fitzgerald ) -> Result<(), Trap> { 119872004aadSNick Fitzgerald // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-memory-init 119972004aadSNick Fitzgerald 120072004aadSNick Fitzgerald let memory = self.get_memory(memory_index); 120172004aadSNick Fitzgerald let data = self.wasm_data(range); 120272004aadSNick Fitzgerald let dst = self.validate_inbounds(memory.current_length(), dst, len.into())?; 120372004aadSNick Fitzgerald let src = self.validate_inbounds(data.len(), src.into(), len.into())?; 120472004aadSNick Fitzgerald let len = len as usize; 120572004aadSNick Fitzgerald 120672004aadSNick Fitzgerald unsafe { 120772004aadSNick Fitzgerald let src_start = data.as_ptr().add(src); 1208b86b9682SAlex Crichton let dst_start = memory.base.as_ptr().add(dst); 120972004aadSNick Fitzgerald // FIXME audit whether this is safe in the presence of shared memory 121072004aadSNick Fitzgerald // (https://github.com/bytecodealliance/wasmtime/issues/4203). 121172004aadSNick Fitzgerald ptr::copy_nonoverlapping(src_start, dst_start, len); 121272004aadSNick Fitzgerald } 121372004aadSNick Fitzgerald 121472004aadSNick Fitzgerald Ok(()) 121572004aadSNick Fitzgerald } 121672004aadSNick Fitzgerald 121772004aadSNick Fitzgerald /// Drop the given data segment, truncating its length to zero. data_drop( self: Pin<&mut Self>, data_index: DataIndex, ) -> Result<(), OutOfMemory>1218a465eabfSNick Fitzgerald pub(crate) fn data_drop( 1219a465eabfSNick Fitzgerald self: Pin<&mut Self>, 1220a465eabfSNick Fitzgerald data_index: DataIndex, 1221a465eabfSNick Fitzgerald ) -> Result<(), OutOfMemory> { 1222a465eabfSNick Fitzgerald self.dropped_data_mut().insert(data_index)?; 122372004aadSNick Fitzgerald 122472004aadSNick Fitzgerald // Note that we don't check that we actually removed a segment because 122572004aadSNick Fitzgerald // dropping a non-passive segment is a no-op (not a trap). 1226a465eabfSNick Fitzgerald 1227a465eabfSNick Fitzgerald Ok(()) 122872004aadSNick Fitzgerald } 122972004aadSNick Fitzgerald 123072004aadSNick Fitzgerald /// Get a table by index regardless of whether it is locally-defined 123172004aadSNick Fitzgerald /// or an imported, foreign table. Ensure that the given range of 123272004aadSNick Fitzgerald /// elements in the table is lazily initialized. We define this 123372004aadSNick Fitzgerald /// operation all-in-one for safety, to ensure the lazy-init 123472004aadSNick Fitzgerald /// happens. 123572004aadSNick Fitzgerald /// 123672004aadSNick Fitzgerald /// Takes an `Iterator` for the index-range to lazy-initialize, 123772004aadSNick Fitzgerald /// for flexibility. This can be a range, single item, or empty 123872004aadSNick Fitzgerald /// sequence, for example. The iterator should return indices in 123972004aadSNick Fitzgerald /// increasing order, so that the break-at-out-of-bounds behavior 124072004aadSNick Fitzgerald /// works correctly. get_table_with_lazy_init( self: Pin<&mut Self>, registry: &ModuleRegistry, table_index: TableIndex, range: impl Iterator<Item = u64>, ) -> &mut Table124172004aadSNick Fitzgerald pub(crate) fn get_table_with_lazy_init( 1242aad93a48SAlex Crichton self: Pin<&mut Self>, 124399ecf728SChris Fallin registry: &ModuleRegistry, 124472004aadSNick Fitzgerald table_index: TableIndex, 1245df69b9a7SLinwei Shang range: impl Iterator<Item = u64>, 1246f021346eSAlex Crichton ) -> &mut Table { 1247f021346eSAlex Crichton let (idx, instance) = self.defined_table_index_and_instance(table_index); 124899ecf728SChris Fallin instance.get_defined_table_with_lazy_init(registry, idx, range) 124972004aadSNick Fitzgerald } 125072004aadSNick Fitzgerald 125172004aadSNick Fitzgerald /// Gets the raw runtime table data structure owned by this instance 125272004aadSNick Fitzgerald /// given the provided `idx`. 125372004aadSNick Fitzgerald /// 125472004aadSNick Fitzgerald /// The `range` specified is eagerly initialized for funcref tables. get_defined_table_with_lazy_init( mut self: Pin<&mut Self>, registry: &ModuleRegistry, idx: DefinedTableIndex, range: impl IntoIterator<Item = u64>, ) -> &mut Table125572004aadSNick Fitzgerald pub fn get_defined_table_with_lazy_init( 1256aad93a48SAlex Crichton mut self: Pin<&mut Self>, 125799ecf728SChris Fallin registry: &ModuleRegistry, 125872004aadSNick Fitzgerald idx: DefinedTableIndex, 1259aef5eeb5SAlex Crichton range: impl IntoIterator<Item = u64>, 1260ddfebe77SAlex Crichton ) -> &mut Table { 126172004aadSNick Fitzgerald let elt_ty = self.tables[idx].1.element_type(); 126272004aadSNick Fitzgerald 126372004aadSNick Fitzgerald if elt_ty == TableElementType::Func { 126472004aadSNick Fitzgerald for i in range { 1265aef5eeb5SAlex Crichton match self.tables[idx].1.get_func_maybe_init(i) { 1266aef5eeb5SAlex Crichton // Uninitialized table element. 1267aef5eeb5SAlex Crichton Ok(None) => {} 1268aef5eeb5SAlex Crichton // Initialized table element, move on to the next. 1269aef5eeb5SAlex Crichton Ok(Some(_)) => continue, 127072004aadSNick Fitzgerald // Out-of-bounds; caller will handle by likely 127172004aadSNick Fitzgerald // throwing a trap. No work to do to lazy-init 127272004aadSNick Fitzgerald // beyond the end. 1273aef5eeb5SAlex Crichton Err(_) => break, 127472004aadSNick Fitzgerald }; 127572004aadSNick Fitzgerald 127672004aadSNick Fitzgerald // The table element `i` is uninitialized and is now being 127772004aadSNick Fitzgerald // initialized. This must imply that a `precompiled` list of 127872004aadSNick Fitzgerald // function indices is available for this table. The precompiled 127972004aadSNick Fitzgerald // list is extracted and then it is consulted with `i` to 128072004aadSNick Fitzgerald // determine the function that is going to be initialized. Note 128172004aadSNick Fitzgerald // that `i` may be outside the limits of the static 128272004aadSNick Fitzgerald // initialization so it's a fallible `get` instead of an index. 12832bdae8b6SNick Fitzgerald let module = self.env_module(); 128472004aadSNick Fitzgerald let precomputed = match &module.table_initialization.initial_values[idx] { 128572004aadSNick Fitzgerald TableInitialValue::Null { precomputed } => precomputed, 128672004aadSNick Fitzgerald TableInitialValue::Expr(_) => unreachable!(), 128772004aadSNick Fitzgerald }; 1288df69b9a7SLinwei Shang // Panicking here helps catch bugs rather than silently truncating by accident. 1289df69b9a7SLinwei Shang let func_index = precomputed.get(usize::try_from(i).unwrap()).cloned(); 129099ecf728SChris Fallin let func_ref = func_index 129199ecf728SChris Fallin .and_then(|func_index| self.as_mut().get_func_ref(registry, func_index)); 1292aad93a48SAlex Crichton self.as_mut().tables_mut()[idx] 129372004aadSNick Fitzgerald .1 1294aef5eeb5SAlex Crichton .set_func(i, func_ref) 129572004aadSNick Fitzgerald .expect("Table type should match and index should be in-bounds"); 129672004aadSNick Fitzgerald } 129772004aadSNick Fitzgerald } 129872004aadSNick Fitzgerald 1299ddfebe77SAlex Crichton self.get_defined_table(idx) 130072004aadSNick Fitzgerald } 130172004aadSNick Fitzgerald 130272004aadSNick Fitzgerald /// Get a table by index regardless of whether it is locally-defined or an 130372004aadSNick Fitzgerald /// imported, foreign table. get_table(self: Pin<&mut Self>, table_index: TableIndex) -> &mut Table1304f021346eSAlex Crichton pub(crate) fn get_table(self: Pin<&mut Self>, table_index: TableIndex) -> &mut Table { 1305f021346eSAlex Crichton let (idx, instance) = self.defined_table_index_and_instance(table_index); 1306f021346eSAlex Crichton instance.get_defined_table(idx) 130772004aadSNick Fitzgerald } 130872004aadSNick Fitzgerald 130972004aadSNick Fitzgerald /// Get a locally-defined table. get_defined_table(self: Pin<&mut Self>, index: DefinedTableIndex) -> &mut Table13109f81f226SAlex Crichton pub(crate) fn get_defined_table(self: Pin<&mut Self>, index: DefinedTableIndex) -> &mut Table { 13119f81f226SAlex Crichton &mut self.tables_mut()[index].1 131272004aadSNick Fitzgerald } 131372004aadSNick Fitzgerald defined_table_index_and_instance<'a>( self: Pin<&'a mut Self>, index: TableIndex, ) -> (DefinedTableIndex, Pin<&'a mut Instance>)1314f021346eSAlex Crichton pub(crate) fn defined_table_index_and_instance<'a>( 1315f021346eSAlex Crichton self: Pin<&'a mut Self>, 131672004aadSNick Fitzgerald index: TableIndex, 1317f021346eSAlex Crichton ) -> (DefinedTableIndex, Pin<&'a mut Instance>) { 13182bdae8b6SNick Fitzgerald if let Some(defined_table_index) = self.env_module().defined_table_index(index) { 1319f021346eSAlex Crichton (defined_table_index, self) 132072004aadSNick Fitzgerald } else { 132172004aadSNick Fitzgerald let import = self.imported_table(index); 1322f021346eSAlex Crichton let index = import.index; 1323f021346eSAlex Crichton let vmctx = import.vmctx.as_non_null(); 1324f021346eSAlex Crichton // SAFETY: the validity of `self` means that the reachable instances 1325f021346eSAlex Crichton // should also all be owned by the same store and fully initialized, 1326f021346eSAlex Crichton // so it's safe to laterally move from a mutable borrow of this 1327f021346eSAlex Crichton // instance to a mutable borrow of a sibling instance. 1328f021346eSAlex Crichton let foreign_instance = unsafe { self.sibling_vmctx_mut(vmctx) }; 1329f021346eSAlex Crichton (index, foreign_instance) 133072004aadSNick Fitzgerald } 133172004aadSNick Fitzgerald } 133272004aadSNick Fitzgerald 1333f1797bb1SNick Fitzgerald /// Same as `self.runtime_info.env_module()` but additionally returns the 1334f1797bb1SNick Fitzgerald /// `Pin<&mut Self>` with the same original lifetime. module_and_self(self: Pin<&mut Self>) -> (&wasmtime_environ::Module, Pin<&mut Self>)1335f1797bb1SNick Fitzgerald pub fn module_and_self(self: Pin<&mut Self>) -> (&wasmtime_environ::Module, Pin<&mut Self>) { 1336f1797bb1SNick Fitzgerald // SAFETY: this function is projecting both `&Module` and the same 1337f1797bb1SNick Fitzgerald // pointer both connected to the same lifetime. This is safe because 1338f1797bb1SNick Fitzgerald // it's a contract of `Pin<&mut Self>` that the `runtime_info` field is 1339f1797bb1SNick Fitzgerald // never written, meaning it's effectively unsafe to have `&mut Module` 1340f1797bb1SNick Fitzgerald // projected from `Pin<&mut Self>`. Consequently it's safe to have a 1341f1797bb1SNick Fitzgerald // read-only view of the field while still retaining mutable access to 1342f1797bb1SNick Fitzgerald // all other fields. 1343f1797bb1SNick Fitzgerald let module = self.runtime_info.env_module(); 1344f1797bb1SNick Fitzgerald let module = &raw const *module; 1345f1797bb1SNick Fitzgerald let module = unsafe { &*module }; 1346f1797bb1SNick Fitzgerald (module, self) 1347f1797bb1SNick Fitzgerald } 1348f1797bb1SNick Fitzgerald 134972004aadSNick Fitzgerald /// Initialize the VMContext data associated with this Instance. 135072004aadSNick Fitzgerald /// 135172004aadSNick Fitzgerald /// The `VMContext` memory is assumed to be uninitialized; any field 135272004aadSNick Fitzgerald /// that we need in a certain state will be explicitly written by this 135372004aadSNick Fitzgerald /// function. initialize_vmctx(self: Pin<&mut Self>, store: &StoreOpaque, imports: Imports)1354f1797bb1SNick Fitzgerald unsafe fn initialize_vmctx(self: Pin<&mut Self>, store: &StoreOpaque, imports: Imports) { 1355f1797bb1SNick Fitzgerald let (module, mut instance) = self.module_and_self(); 135672004aadSNick Fitzgerald 1357b052dee0SAlex Crichton // SAFETY: the type of the magic field is indeed `u32` and this function 1358b052dee0SAlex Crichton // is initializing its value. 1359b052dee0SAlex Crichton unsafe { 1360f1797bb1SNick Fitzgerald let offsets = instance.runtime_info.offsets(); 1361f1797bb1SNick Fitzgerald instance 1362f1797bb1SNick Fitzgerald .vmctx_plus_offset_raw::<u32>(offsets.ptr.vmctx_magic()) 1363b86b9682SAlex Crichton .write(VMCONTEXT_MAGIC); 1364b052dee0SAlex Crichton } 1365b052dee0SAlex Crichton 1366b052dee0SAlex Crichton // SAFETY: it's up to the caller to provide a valid store pointer here. 1367b052dee0SAlex Crichton unsafe { 1368f1797bb1SNick Fitzgerald instance.as_mut().set_store(store); 1369b052dee0SAlex Crichton } 137072004aadSNick Fitzgerald 137172004aadSNick Fitzgerald // Initialize shared types 1372b052dee0SAlex Crichton // 1373b052dee0SAlex Crichton // SAFETY: validity of the vmctx means it should be safe to write to it 1374b052dee0SAlex Crichton // here. 1375b052dee0SAlex Crichton unsafe { 1376f1797bb1SNick Fitzgerald let types = NonNull::from(instance.runtime_info.type_ids()); 1377f1797bb1SNick Fitzgerald instance.type_ids_array().write(types.cast().into()); 1378b052dee0SAlex Crichton } 137972004aadSNick Fitzgerald 138072004aadSNick Fitzgerald // Initialize the built-in functions 1381b052dee0SAlex Crichton // 1382b052dee0SAlex Crichton // SAFETY: the type of the builtin functions field is indeed a pointer 1383b052dee0SAlex Crichton // and the pointer being filled in here, plus the vmctx is valid to 1384b052dee0SAlex Crichton // write to during initialization. 1385b052dee0SAlex Crichton unsafe { 13865544100fSAlex Crichton static BUILTINS: VMBuiltinFunctionsArray = VMBuiltinFunctionsArray::INIT; 13875544100fSAlex Crichton let ptr = BUILTINS.expose_provenance(); 1388f1797bb1SNick Fitzgerald let offsets = instance.runtime_info.offsets(); 1389f1797bb1SNick Fitzgerald instance 1390f1797bb1SNick Fitzgerald .vmctx_plus_offset_raw(offsets.ptr.vmctx_builtin_functions()) 1391b86b9682SAlex Crichton .write(VmPtr::from(ptr)); 1392b052dee0SAlex Crichton } 139372004aadSNick Fitzgerald 139472004aadSNick Fitzgerald // Initialize the imports 1395b052dee0SAlex Crichton // 1396b052dee0SAlex Crichton // SAFETY: the vmctx is safe to initialize during this function and 1397b052dee0SAlex Crichton // validity of each item itself is a contract the caller must uphold. 139872004aadSNick Fitzgerald debug_assert_eq!(imports.functions.len(), module.num_imported_funcs); 1399b052dee0SAlex Crichton unsafe { 1400f1797bb1SNick Fitzgerald let offsets = instance.runtime_info.offsets(); 140172004aadSNick Fitzgerald ptr::copy_nonoverlapping( 140272004aadSNick Fitzgerald imports.functions.as_ptr(), 1403f1797bb1SNick Fitzgerald instance 1404f1797bb1SNick Fitzgerald .vmctx_plus_offset_raw(offsets.vmctx_imported_functions_begin()) 1405b86b9682SAlex Crichton .as_ptr(), 140672004aadSNick Fitzgerald imports.functions.len(), 140772004aadSNick Fitzgerald ); 140872004aadSNick Fitzgerald debug_assert_eq!(imports.tables.len(), module.num_imported_tables); 140972004aadSNick Fitzgerald ptr::copy_nonoverlapping( 141072004aadSNick Fitzgerald imports.tables.as_ptr(), 1411f1797bb1SNick Fitzgerald instance 1412f1797bb1SNick Fitzgerald .vmctx_plus_offset_raw(offsets.vmctx_imported_tables_begin()) 1413b86b9682SAlex Crichton .as_ptr(), 141472004aadSNick Fitzgerald imports.tables.len(), 141572004aadSNick Fitzgerald ); 141672004aadSNick Fitzgerald debug_assert_eq!(imports.memories.len(), module.num_imported_memories); 141772004aadSNick Fitzgerald ptr::copy_nonoverlapping( 141872004aadSNick Fitzgerald imports.memories.as_ptr(), 1419f1797bb1SNick Fitzgerald instance 1420f1797bb1SNick Fitzgerald .vmctx_plus_offset_raw(offsets.vmctx_imported_memories_begin()) 1421b86b9682SAlex Crichton .as_ptr(), 142272004aadSNick Fitzgerald imports.memories.len(), 142372004aadSNick Fitzgerald ); 142472004aadSNick Fitzgerald debug_assert_eq!(imports.globals.len(), module.num_imported_globals); 142572004aadSNick Fitzgerald ptr::copy_nonoverlapping( 142672004aadSNick Fitzgerald imports.globals.as_ptr(), 1427f1797bb1SNick Fitzgerald instance 1428f1797bb1SNick Fitzgerald .vmctx_plus_offset_raw(offsets.vmctx_imported_globals_begin()) 1429b86b9682SAlex Crichton .as_ptr(), 143072004aadSNick Fitzgerald imports.globals.len(), 143172004aadSNick Fitzgerald ); 14320b4c754aSDaniel Hillerström debug_assert_eq!(imports.tags.len(), module.num_imported_tags); 14330b4c754aSDaniel Hillerström ptr::copy_nonoverlapping( 14340b4c754aSDaniel Hillerström imports.tags.as_ptr(), 1435f1797bb1SNick Fitzgerald instance 1436f1797bb1SNick Fitzgerald .vmctx_plus_offset_raw(offsets.vmctx_imported_tags_begin()) 14370b4c754aSDaniel Hillerström .as_ptr(), 14380b4c754aSDaniel Hillerström imports.tags.len(), 14390b4c754aSDaniel Hillerström ); 1440b052dee0SAlex Crichton } 14410b4c754aSDaniel Hillerström 144272004aadSNick Fitzgerald // N.B.: there is no need to initialize the funcrefs array because we 144372004aadSNick Fitzgerald // eagerly construct each element in it whenever asked for a reference 144472004aadSNick Fitzgerald // to that element. In other words, there is no state needed to track 144572004aadSNick Fitzgerald // the lazy-init, so we don't need to initialize any state now. 144672004aadSNick Fitzgerald 144772004aadSNick Fitzgerald // Initialize the defined tables 1448b052dee0SAlex Crichton // 1449b052dee0SAlex Crichton // SAFETY: it's safe to initialize these tables during initialization 1450b052dee0SAlex Crichton // here and the various types of pointers and such here should all be 1451b052dee0SAlex Crichton // valid. 1452b052dee0SAlex Crichton unsafe { 1453f1797bb1SNick Fitzgerald let offsets = instance.runtime_info.offsets(); 1454f1797bb1SNick Fitzgerald let mut ptr = instance.vmctx_plus_offset_raw(offsets.vmctx_tables_begin()); 1455f1797bb1SNick Fitzgerald let tables = instance.as_mut().tables_mut(); 14567a49e44fSAlex Crichton for i in 0..module.num_defined_tables() { 1457aad93a48SAlex Crichton ptr.write(tables[DefinedTableIndex::new(i)].1.vmtable()); 145872004aadSNick Fitzgerald ptr = ptr.add(1); 145972004aadSNick Fitzgerald } 1460b052dee0SAlex Crichton } 146172004aadSNick Fitzgerald 146272004aadSNick Fitzgerald // Initialize the defined memories. This fills in both the 146372004aadSNick Fitzgerald // `defined_memories` table and the `owned_memories` table at the same 146472004aadSNick Fitzgerald // time. Entries in `defined_memories` hold a pointer to a definition 146572004aadSNick Fitzgerald // (all memories) whereas the `owned_memories` hold the actual 146672004aadSNick Fitzgerald // definitions of memories owned (not shared) in the module. 1467b052dee0SAlex Crichton // 1468b052dee0SAlex Crichton // SAFETY: it's safe to initialize these memories during initialization 1469b052dee0SAlex Crichton // here and the various types of pointers and such here should all be 1470b052dee0SAlex Crichton // valid. 1471b052dee0SAlex Crichton unsafe { 1472f1797bb1SNick Fitzgerald let offsets = instance.runtime_info.offsets(); 1473f1797bb1SNick Fitzgerald let mut ptr = instance.vmctx_plus_offset_raw(offsets.vmctx_memories_begin()); 1474f1797bb1SNick Fitzgerald let mut owned_ptr = 1475f1797bb1SNick Fitzgerald instance.vmctx_plus_offset_raw(offsets.vmctx_owned_memories_begin()); 1476f1797bb1SNick Fitzgerald let memories = instance.as_mut().memories_mut(); 14772a7f0653SAlex Crichton for i in 0..module.num_defined_memories() { 147872004aadSNick Fitzgerald let defined_memory_index = DefinedMemoryIndex::new(i); 147972004aadSNick Fitzgerald let memory_index = module.memory_index(defined_memory_index); 14802a7f0653SAlex Crichton if module.memories[memory_index].shared { 1481aad93a48SAlex Crichton let def_ptr = memories[defined_memory_index] 148272004aadSNick Fitzgerald .1 148372004aadSNick Fitzgerald .as_shared_memory() 148472004aadSNick Fitzgerald .unwrap() 148572004aadSNick Fitzgerald .vmmemory_ptr(); 1486b86b9682SAlex Crichton ptr.write(VmPtr::from(def_ptr)); 148772004aadSNick Fitzgerald } else { 1488aad93a48SAlex Crichton owned_ptr.write(memories[defined_memory_index].1.vmmemory()); 1489b86b9682SAlex Crichton ptr.write(VmPtr::from(owned_ptr)); 149072004aadSNick Fitzgerald owned_ptr = owned_ptr.add(1); 149172004aadSNick Fitzgerald } 149272004aadSNick Fitzgerald ptr = ptr.add(1); 149372004aadSNick Fitzgerald } 1494b052dee0SAlex Crichton } 149572004aadSNick Fitzgerald 1496818966f3SNick Fitzgerald // Zero-initialize the globals so that nothing is uninitialized memory 1497818966f3SNick Fitzgerald // after this function returns. The globals are actually initialized 1498818966f3SNick Fitzgerald // with their const expression initializers after the instance is fully 1499818966f3SNick Fitzgerald // allocated. 1500b052dee0SAlex Crichton // 1501b052dee0SAlex Crichton // SAFETY: it's safe to initialize globals during initialization 1502b052dee0SAlex Crichton // here. Note that while the value being written is not valid for all 1503b052dee0SAlex Crichton // types of globals it's initializing the memory to zero instead of 1504b052dee0SAlex Crichton // being in an undefined state. So it's still unsafe to access globals 1505b052dee0SAlex Crichton // after this, but if it's read then it'd hopefully crash faster than 1506b052dee0SAlex Crichton // leaving this undefined. 1507b052dee0SAlex Crichton unsafe { 1508818966f3SNick Fitzgerald for (index, _init) in module.global_initializers.iter() { 1509f1797bb1SNick Fitzgerald instance.global_ptr(index).write(VMGlobalDefinition::new()); 151072004aadSNick Fitzgerald } 1511b052dee0SAlex Crichton } 15120b4c754aSDaniel Hillerström 15130b4c754aSDaniel Hillerström // Initialize the defined tags 1514b052dee0SAlex Crichton // 1515b052dee0SAlex Crichton // SAFETY: it's safe to initialize these tags during initialization 1516b052dee0SAlex Crichton // here and the various types of pointers and such here should all be 1517b052dee0SAlex Crichton // valid. 1518b052dee0SAlex Crichton unsafe { 1519f1797bb1SNick Fitzgerald let offsets = instance.runtime_info.offsets(); 1520f1797bb1SNick Fitzgerald let mut ptr = instance.vmctx_plus_offset_raw(offsets.vmctx_tags_begin()); 15210b4c754aSDaniel Hillerström for i in 0..module.num_defined_tags() { 15220b4c754aSDaniel Hillerström let defined_index = DefinedTagIndex::new(i); 15230b4c754aSDaniel Hillerström let tag_index = module.tag_index(defined_index); 15240b4c754aSDaniel Hillerström let tag = module.tags[tag_index]; 15250b4c754aSDaniel Hillerström ptr.write(VMTagDefinition::new( 15260b4c754aSDaniel Hillerström tag.signature.unwrap_engine_type_index(), 15270b4c754aSDaniel Hillerström )); 15280b4c754aSDaniel Hillerström ptr = ptr.add(1); 15290b4c754aSDaniel Hillerström } 153072004aadSNick Fitzgerald } 1531b052dee0SAlex Crichton } 153272004aadSNick Fitzgerald 1533aad93a48SAlex Crichton /// Attempts to convert from the host `addr` specified to a WebAssembly 1534aad93a48SAlex Crichton /// based address recorded in `WasmFault`. 1535aad93a48SAlex Crichton /// 1536aad93a48SAlex Crichton /// This method will check all linear memories that this instance contains 1537aad93a48SAlex Crichton /// to see if any of them contain `addr`. If one does then `Some` is 1538aad93a48SAlex Crichton /// returned with metadata about the wasm fault. Otherwise `None` is 1539aad93a48SAlex Crichton /// returned and `addr` doesn't belong to this instance. wasm_fault(&self, addr: usize) -> Option<WasmFault>1540aad93a48SAlex Crichton pub fn wasm_fault(&self, addr: usize) -> Option<WasmFault> { 154172004aadSNick Fitzgerald let mut fault = None; 154272004aadSNick Fitzgerald for (_, (_, memory)) in self.memories.iter() { 154372004aadSNick Fitzgerald let accessible = memory.wasm_accessible(); 154472004aadSNick Fitzgerald if accessible.start <= addr && addr < accessible.end { 154572004aadSNick Fitzgerald // All linear memories should be disjoint so assert that no 154672004aadSNick Fitzgerald // prior fault has been found. 154772004aadSNick Fitzgerald assert!(fault.is_none()); 154872004aadSNick Fitzgerald fault = Some(WasmFault { 154972004aadSNick Fitzgerald memory_size: memory.byte_size(), 155072004aadSNick Fitzgerald wasm_address: u64::try_from(addr - accessible.start).unwrap(), 155172004aadSNick Fitzgerald }); 155272004aadSNick Fitzgerald } 155372004aadSNick Fitzgerald } 155472004aadSNick Fitzgerald fault 155572004aadSNick Fitzgerald } 15560e9a691dSAlex Crichton 15570e9a691dSAlex Crichton /// Returns the id, within this instance's store, that it's assigned. id(&self) -> InstanceId15580e9a691dSAlex Crichton pub fn id(&self) -> InstanceId { 15590e9a691dSAlex Crichton self.id 15600e9a691dSAlex Crichton } 1561e012eedaSAlex Crichton 1562e012eedaSAlex Crichton /// Get all memories within this instance. 1563e012eedaSAlex Crichton /// 1564e012eedaSAlex Crichton /// Returns both import and defined memories. 1565e012eedaSAlex Crichton /// 1566e012eedaSAlex Crichton /// Returns both exported and non-exported memories. 1567e012eedaSAlex Crichton /// 1568e012eedaSAlex Crichton /// Gives access to the full memories space. all_memories( &self, store: StoreId, ) -> impl ExactSizeIterator<Item = (MemoryIndex, ExportMemory)> + '_15692b832281SAlex Crichton pub fn all_memories( 15702b832281SAlex Crichton &self, 15712b832281SAlex Crichton store: StoreId, 15721fcd0933SAlex Crichton ) -> impl ExactSizeIterator<Item = (MemoryIndex, ExportMemory)> + '_ { 15732b832281SAlex Crichton self.env_module() 15742b832281SAlex Crichton .memories 15752b832281SAlex Crichton .iter() 15762b832281SAlex Crichton .map(move |(i, _)| (i, self.get_exported_memory(store, i))) 1577e012eedaSAlex Crichton } 1578e012eedaSAlex Crichton 1579e012eedaSAlex Crichton /// Return the memories defined in this instance (not imported). defined_memories<'a>( &'a self, store: StoreId, ) -> impl ExactSizeIterator<Item = ExportMemory> + 'a15802b832281SAlex Crichton pub fn defined_memories<'a>( 15812b832281SAlex Crichton &'a self, 15822b832281SAlex Crichton store: StoreId, 15831fcd0933SAlex Crichton ) -> impl ExactSizeIterator<Item = ExportMemory> + 'a { 1584e012eedaSAlex Crichton let num_imported = self.env_module().num_imported_memories; 15852b832281SAlex Crichton self.all_memories(store) 1586e012eedaSAlex Crichton .skip(num_imported) 1587e012eedaSAlex Crichton .map(|(_i, memory)| memory) 1588e012eedaSAlex Crichton } 1589e012eedaSAlex Crichton 1590e012eedaSAlex Crichton /// Lookup an item with the given index. 1591e012eedaSAlex Crichton /// 1592e012eedaSAlex Crichton /// # Panics 1593e012eedaSAlex Crichton /// 1594e012eedaSAlex Crichton /// Panics if `export` is not valid for this instance. 15952b832281SAlex Crichton /// 15962b832281SAlex Crichton /// # Safety 15972b832281SAlex Crichton /// 15982b832281SAlex Crichton /// This function requires that `store` is the correct store which owns this 15992b832281SAlex Crichton /// instance. get_export_by_index_mut( self: Pin<&mut Self>, registry: &ModuleRegistry, store: StoreId, export: EntityIndex, ) -> Export16002b832281SAlex Crichton pub unsafe fn get_export_by_index_mut( 16012b832281SAlex Crichton self: Pin<&mut Self>, 160299ecf728SChris Fallin registry: &ModuleRegistry, 16032b832281SAlex Crichton store: StoreId, 16042b832281SAlex Crichton export: EntityIndex, 16052b832281SAlex Crichton ) -> Export { 1606e012eedaSAlex Crichton match export { 16072b832281SAlex Crichton // SAFETY: the contract of `store` owning the this instance is a 16082b832281SAlex Crichton // safety requirement of this function itself. 16092b832281SAlex Crichton EntityIndex::Function(i) => { 161099ecf728SChris Fallin Export::Function(unsafe { self.get_exported_func(registry, store, i) }) 16112b832281SAlex Crichton } 16122b832281SAlex Crichton EntityIndex::Global(i) => Export::Global(self.get_exported_global(store, i)), 16132b832281SAlex Crichton EntityIndex::Table(i) => Export::Table(self.get_exported_table(store, i)), 16141fcd0933SAlex Crichton EntityIndex::Memory(i) => match self.get_exported_memory(store, i) { 16151fcd0933SAlex Crichton ExportMemory::Unshared(m) => Export::Memory(m), 16161fcd0933SAlex Crichton ExportMemory::Shared(m, i) => Export::SharedMemory(m, i), 16172b832281SAlex Crichton }, 16182b832281SAlex Crichton EntityIndex::Tag(i) => Export::Tag(self.get_exported_tag(store, i)), 1619e012eedaSAlex Crichton } 1620e012eedaSAlex Crichton } 1621aad93a48SAlex Crichton store_mut(self: Pin<&mut Self>) -> &mut Option<VMStoreRawPtr>1622aad93a48SAlex Crichton fn store_mut(self: Pin<&mut Self>) -> &mut Option<VMStoreRawPtr> { 1623aad93a48SAlex Crichton // SAFETY: this is a pin-projection to get a mutable reference to an 1624aad93a48SAlex Crichton // internal field and is safe so long as the `&mut Self` temporarily 1625aad93a48SAlex Crichton // created is not overwritten, which it isn't here. 1626aad93a48SAlex Crichton unsafe { &mut self.get_unchecked_mut().store } 1627aad93a48SAlex Crichton } 1628aad93a48SAlex Crichton dropped_elements_mut(self: Pin<&mut Self>) -> &mut TryEntitySet<ElemIndex>16291c1843daSNick Fitzgerald fn dropped_elements_mut(self: Pin<&mut Self>) -> &mut TryEntitySet<ElemIndex> { 1630aad93a48SAlex Crichton // SAFETY: see `store_mut` above. 1631aad93a48SAlex Crichton unsafe { &mut self.get_unchecked_mut().dropped_elements } 1632aad93a48SAlex Crichton } 1633aad93a48SAlex Crichton dropped_data_mut(self: Pin<&mut Self>) -> &mut TryEntitySet<DataIndex>16341c1843daSNick Fitzgerald fn dropped_data_mut(self: Pin<&mut Self>) -> &mut TryEntitySet<DataIndex> { 1635aad93a48SAlex Crichton // SAFETY: see `store_mut` above. 1636aad93a48SAlex Crichton unsafe { &mut self.get_unchecked_mut().dropped_data } 1637aad93a48SAlex Crichton } 1638aad93a48SAlex Crichton memories_mut( self: Pin<&mut Self>, ) -> &mut TryPrimaryMap<DefinedMemoryIndex, (MemoryAllocationIndex, Memory)>1639aad93a48SAlex Crichton fn memories_mut( 1640aad93a48SAlex Crichton self: Pin<&mut Self>, 1641*9c44a9b4SNick Fitzgerald ) -> &mut TryPrimaryMap<DefinedMemoryIndex, (MemoryAllocationIndex, Memory)> { 1642aad93a48SAlex Crichton // SAFETY: see `store_mut` above. 1643aad93a48SAlex Crichton unsafe { &mut self.get_unchecked_mut().memories } 1644aad93a48SAlex Crichton } 1645aad93a48SAlex Crichton tables_mut( self: Pin<&mut Self>, ) -> &mut TryPrimaryMap<DefinedTableIndex, (TableAllocationIndex, Table)>1646f021346eSAlex Crichton pub(crate) fn tables_mut( 1647aad93a48SAlex Crichton self: Pin<&mut Self>, 1648*9c44a9b4SNick Fitzgerald ) -> &mut TryPrimaryMap<DefinedTableIndex, (TableAllocationIndex, Table)> { 1649aad93a48SAlex Crichton // SAFETY: see `store_mut` above. 1650aad93a48SAlex Crichton unsafe { &mut self.get_unchecked_mut().tables } 1651aad93a48SAlex Crichton } 1652aad93a48SAlex Crichton 1653aad93a48SAlex Crichton #[cfg(feature = "wmemcheck")] wmemcheck_state_mut(self: Pin<&mut Self>) -> &mut Option<Wmemcheck>1654aad93a48SAlex Crichton pub(super) fn wmemcheck_state_mut(self: Pin<&mut Self>) -> &mut Option<Wmemcheck> { 1655aad93a48SAlex Crichton // SAFETY: see `store_mut` above. 1656aad93a48SAlex Crichton unsafe { &mut self.get_unchecked_mut().wmemcheck_state } 1657aad93a48SAlex Crichton } 165872004aadSNick Fitzgerald } 165972004aadSNick Fitzgerald 16607e28c254SAlex Crichton // SAFETY: `layout` should describe this accurately and `OwnedVMContext` is the 16617e28c254SAlex Crichton // last field of `ComponentInstance`. 16627e28c254SAlex Crichton unsafe impl InstanceLayout for Instance { 16637e28c254SAlex Crichton const INIT_ZEROED: bool = false; 16647e28c254SAlex Crichton type VMContext = VMContext; 16657e28c254SAlex Crichton layout(&self) -> Layout16667e28c254SAlex Crichton fn layout(&self) -> Layout { 16677e28c254SAlex Crichton Self::alloc_layout(self.runtime_info.offsets()) 16687e28c254SAlex Crichton } 16697e28c254SAlex Crichton owned_vmctx(&self) -> &OwnedVMContext<VMContext>16707e28c254SAlex Crichton fn owned_vmctx(&self) -> &OwnedVMContext<VMContext> { 16717e28c254SAlex Crichton &self.vmctx 16727e28c254SAlex Crichton } 16737e28c254SAlex Crichton owned_vmctx_mut(&mut self) -> &mut OwnedVMContext<VMContext>16747e28c254SAlex Crichton fn owned_vmctx_mut(&mut self) -> &mut OwnedVMContext<VMContext> { 16757e28c254SAlex Crichton &mut self.vmctx 16767e28c254SAlex Crichton } 16777e28c254SAlex Crichton } 16787e28c254SAlex Crichton 16797e28c254SAlex Crichton pub type InstanceHandle = OwnedInstance<Instance>; 16807e28c254SAlex Crichton 168172004aadSNick Fitzgerald /// A handle holding an `Instance` of a WebAssembly module. 1682aad93a48SAlex Crichton /// 1683aad93a48SAlex Crichton /// This structure is an owning handle of the `instance` contained internally. 1684aad93a48SAlex Crichton /// When this value goes out of scope it will deallocate the `Instance` and all 1685aad93a48SAlex Crichton /// memory associated with it. 1686aad93a48SAlex Crichton /// 1687aad93a48SAlex Crichton /// Note that this lives within a `StoreOpaque` on a list of instances that a 1688aad93a48SAlex Crichton /// store is keeping alive. 168972004aadSNick Fitzgerald #[derive(Debug)] 16907e28c254SAlex Crichton #[repr(transparent)] // guarantee this is a zero-cost wrapper 16917e28c254SAlex Crichton pub struct OwnedInstance<T: InstanceLayout> { 1692aad93a48SAlex Crichton /// The raw pointer to the instance that was allocated. 1693aad93a48SAlex Crichton /// 1694aad93a48SAlex Crichton /// Note that this is not equivalent to `Box<Instance>` because the 1695aad93a48SAlex Crichton /// allocation here has a `VMContext` trailing after it. Thus the custom 1696aad93a48SAlex Crichton /// destructor to invoke the `dealloc` function with the appropriate 1697aad93a48SAlex Crichton /// layout. 16987e28c254SAlex Crichton instance: SendSyncPtr<T>, 16997e28c254SAlex Crichton _marker: marker::PhantomData<Box<(T, OwnedVMContext<T::VMContext>)>>, 170072004aadSNick Fitzgerald } 170172004aadSNick Fitzgerald 17027e28c254SAlex Crichton /// Structure that must be placed at the end of a type implementing 17037e28c254SAlex Crichton /// `InstanceLayout`. 17047e28c254SAlex Crichton #[repr(align(16))] // match the alignment of VMContext 17057e28c254SAlex Crichton pub struct OwnedVMContext<T> { 17067e28c254SAlex Crichton /// A pointer to the `vmctx` field at the end of the `structure`. 17077e28c254SAlex Crichton /// 17087e28c254SAlex Crichton /// If you're looking at this a reasonable question would be "why do we need 17097e28c254SAlex Crichton /// a pointer to ourselves?" because after all the pointer's value is 17107e28c254SAlex Crichton /// trivially derivable from any `&Instance` pointer. The rationale for this 17117e28c254SAlex Crichton /// field's existence is subtle, but it's required for correctness. The 17127e28c254SAlex Crichton /// short version is "this makes miri happy". 17137e28c254SAlex Crichton /// 17147e28c254SAlex Crichton /// The long version of why this field exists is that the rules that MIRI 17157e28c254SAlex Crichton /// uses to ensure pointers are used correctly have various conditions on 17167e28c254SAlex Crichton /// them depend on how pointers are used. More specifically if `*mut T` is 1717ab78bd82SHo Kim /// derived from `&mut T`, then that invalidates all prior pointers derived 17187e28c254SAlex Crichton /// from the `&mut T`. This means that while we liberally want to re-acquire 17197e28c254SAlex Crichton /// a `*mut VMContext` throughout the implementation of `Instance` the 17207e28c254SAlex Crichton /// trivial way, a function `fn vmctx(Pin<&mut Instance>) -> *mut VMContext` 17217e28c254SAlex Crichton /// would effectively invalidate all prior `*mut VMContext` pointers 17227e28c254SAlex Crichton /// acquired. The purpose of this field is to serve as a sort of 17237e28c254SAlex Crichton /// source-of-truth for where `*mut VMContext` pointers come from. 17247e28c254SAlex Crichton /// 17257e28c254SAlex Crichton /// This field is initialized when the `Instance` is created with the 17267e28c254SAlex Crichton /// original allocation's pointer. That means that the provenance of this 17277e28c254SAlex Crichton /// pointer contains the entire allocation (both instance and `VMContext`). 17287e28c254SAlex Crichton /// This provenance bit is then "carried through" where `fn vmctx` will base 17297e28c254SAlex Crichton /// all returned pointers on this pointer itself. This provides the means of 17307e28c254SAlex Crichton /// never invalidating this pointer throughout MIRI and additionally being 17317e28c254SAlex Crichton /// able to still temporarily have `Pin<&mut Instance>` methods and such. 17327e28c254SAlex Crichton /// 17337e28c254SAlex Crichton /// It's important to note, though, that this is not here purely for MIRI. 17347e28c254SAlex Crichton /// The careful construction of the `fn vmctx` method has ramifications on 17357e28c254SAlex Crichton /// the LLVM IR generated, for example. A historical CVE on Wasmtime, 17367e28c254SAlex Crichton /// GHSA-ch89-5g45-qwc7, was caused due to relying on undefined behavior. By 17377e28c254SAlex Crichton /// deriving VMContext pointers from this pointer it specifically hints to 17387e28c254SAlex Crichton /// LLVM that trickery is afoot and it properly informs `noalias` and such 17397e28c254SAlex Crichton /// annotations and analysis. More-or-less this pointer is actually loaded 17407e28c254SAlex Crichton /// in LLVM IR which helps defeat otherwise present aliasing optimizations, 17417e28c254SAlex Crichton /// which we want, since writes to this should basically never be optimized 17427e28c254SAlex Crichton /// out. 17437e28c254SAlex Crichton /// 17447e28c254SAlex Crichton /// As a final note it's worth pointing out that the machine code generated 17457e28c254SAlex Crichton /// for accessing `fn vmctx` is still as one would expect. This member isn't 17467e28c254SAlex Crichton /// actually ever loaded at runtime (or at least shouldn't be). Perhaps in 17477e28c254SAlex Crichton /// the future if the memory consumption of this field is a problem we could 17487e28c254SAlex Crichton /// shrink it slightly, but for now one extra pointer per wasm instance 17497e28c254SAlex Crichton /// seems not too bad. 17507e28c254SAlex Crichton vmctx_self_reference: SendSyncPtr<T>, 17517e28c254SAlex Crichton 17527e28c254SAlex Crichton /// This field ensures that going from `Pin<&mut T>` to `&mut T` is not a 17537e28c254SAlex Crichton /// safe operation. 17547e28c254SAlex Crichton _marker: core::marker::PhantomPinned, 17557e28c254SAlex Crichton } 17567e28c254SAlex Crichton 17577e28c254SAlex Crichton impl<T> OwnedVMContext<T> { 17587e28c254SAlex Crichton /// Creates a new blank vmctx to place at the end of an instance. new() -> OwnedVMContext<T>17597e28c254SAlex Crichton pub fn new() -> OwnedVMContext<T> { 17607e28c254SAlex Crichton OwnedVMContext { 17617e28c254SAlex Crichton vmctx_self_reference: SendSyncPtr::new(NonNull::dangling()), 17627e28c254SAlex Crichton _marker: core::marker::PhantomPinned, 17637e28c254SAlex Crichton } 17647e28c254SAlex Crichton } 17657e28c254SAlex Crichton } 17667e28c254SAlex Crichton 17677e28c254SAlex Crichton /// Helper trait to plumb both core instances and component instances into 17687e28c254SAlex Crichton /// `OwnedInstance` below. 17697e28c254SAlex Crichton /// 17707e28c254SAlex Crichton /// # Safety 17717e28c254SAlex Crichton /// 17727e28c254SAlex Crichton /// This trait requires `layout` to correctly describe `Self` and appropriately 17737e28c254SAlex Crichton /// allocate space for `Self::VMContext` afterwards. Additionally the field 17747e28c254SAlex Crichton /// returned by `owned_vmctx()` must be the last field in the structure. 17757e28c254SAlex Crichton pub unsafe trait InstanceLayout { 17767e28c254SAlex Crichton /// Whether or not to allocate this instance with `alloc_zeroed` or `alloc`. 17777e28c254SAlex Crichton const INIT_ZEROED: bool; 17787e28c254SAlex Crichton 17797e28c254SAlex Crichton /// The trailing `VMContext` type at the end of this instance. 17807e28c254SAlex Crichton type VMContext; 17817e28c254SAlex Crichton 17827e28c254SAlex Crichton /// The memory layout to use to allocate and deallocate this instance. layout(&self) -> Layout17837e28c254SAlex Crichton fn layout(&self) -> Layout; 17847e28c254SAlex Crichton owned_vmctx(&self) -> &OwnedVMContext<Self::VMContext>17857e28c254SAlex Crichton fn owned_vmctx(&self) -> &OwnedVMContext<Self::VMContext>; owned_vmctx_mut(&mut self) -> &mut OwnedVMContext<Self::VMContext>17867e28c254SAlex Crichton fn owned_vmctx_mut(&mut self) -> &mut OwnedVMContext<Self::VMContext>; 17877e28c254SAlex Crichton 17887e28c254SAlex Crichton /// Returns the `vmctx_self_reference` set above. 17897e28c254SAlex Crichton #[inline] vmctx(&self) -> NonNull<Self::VMContext>17907e28c254SAlex Crichton fn vmctx(&self) -> NonNull<Self::VMContext> { 17917e28c254SAlex Crichton // The definition of this method is subtle but intentional. The goal 17927e28c254SAlex Crichton // here is that effectively this should return `&mut self.vmctx`, but 17937e28c254SAlex Crichton // it's not quite so simple. Some more documentation is available on the 17947e28c254SAlex Crichton // `vmctx_self_reference` field, but the general idea is that we're 17957e28c254SAlex Crichton // creating a pointer to return with proper provenance. Provenance is 17967e28c254SAlex Crichton // still in the works in Rust at the time of this writing but the load 17977e28c254SAlex Crichton // of the `self.vmctx_self_reference` field is important here as it 17987e28c254SAlex Crichton // affects how LLVM thinks about aliasing with respect to the returned 17997e28c254SAlex Crichton // pointer. 18007e28c254SAlex Crichton // 18017e28c254SAlex Crichton // The intention of this method is to codegen to machine code as `&mut 18027e28c254SAlex Crichton // self.vmctx`, however. While it doesn't show up like this in LLVM IR 18037e28c254SAlex Crichton // (there's an actual load of the field) it does look like that by the 18047e28c254SAlex Crichton // time the backend runs. (that's magic to me, the backend removing 18057e28c254SAlex Crichton // loads...) 18067e28c254SAlex Crichton let owned_vmctx = self.owned_vmctx(); 18077e28c254SAlex Crichton let owned_vmctx_raw = NonNull::from(owned_vmctx); 18087e28c254SAlex Crichton // SAFETY: it's part of the contract of `InstanceLayout` and the usage 18097e28c254SAlex Crichton // with `OwnedInstance` that this indeed points to the vmctx. 18107e28c254SAlex Crichton let addr = unsafe { owned_vmctx_raw.add(1) }; 18117e28c254SAlex Crichton owned_vmctx 18127e28c254SAlex Crichton .vmctx_self_reference 18137e28c254SAlex Crichton .as_non_null() 18147e28c254SAlex Crichton .with_addr(addr.addr()) 18157e28c254SAlex Crichton } 18167e28c254SAlex Crichton 18177e28c254SAlex Crichton /// Helper function to access various locations offset from our `*mut 18187e28c254SAlex Crichton /// VMContext` object. 18197e28c254SAlex Crichton /// 18207e28c254SAlex Crichton /// Note that this method takes `&self` as an argument but returns 18217e28c254SAlex Crichton /// `NonNull<T>` which is frequently used to mutate said memory. This is an 18227e28c254SAlex Crichton /// intentional design decision where the safety of the modification of 18237e28c254SAlex Crichton /// memory is placed as a burden onto the caller. The implementation of this 18247e28c254SAlex Crichton /// method explicitly does not require `&mut self` to acquire mutable 18257e28c254SAlex Crichton /// provenance to update the `VMContext` region. Instead all pointers into 18267e28c254SAlex Crichton /// the `VMContext` area have provenance/permissions to write. 18277e28c254SAlex Crichton /// 18287e28c254SAlex Crichton /// Also note though that care must be taken to ensure that reads/writes of 18297e28c254SAlex Crichton /// memory must only happen where appropriate, for example a non-atomic 18307e28c254SAlex Crichton /// write (as most are) should never happen concurrently with another read 18317e28c254SAlex Crichton /// or write. It's generally on the burden of the caller to adhere to this. 18327e28c254SAlex Crichton /// 18337e28c254SAlex Crichton /// Also of note is that most of the time the usage of this method falls 18347e28c254SAlex Crichton /// into one of: 18357e28c254SAlex Crichton /// 18367e28c254SAlex Crichton /// * Something in the VMContext is being read or written. In that case use 18377e28c254SAlex Crichton /// `vmctx_plus_offset` or `vmctx_plus_offset_mut` if possible due to 18387e28c254SAlex Crichton /// that having a safer lifetime. 18397e28c254SAlex Crichton /// 18407e28c254SAlex Crichton /// * A pointer is being created to pass to other VM* data structures. In 18417e28c254SAlex Crichton /// that situation the lifetime of all VM data structures are typically 18427e28c254SAlex Crichton /// tied to the `Store<T>` which is what provides the guarantees around 18437e28c254SAlex Crichton /// concurrency/etc. 18447e28c254SAlex Crichton /// 18457e28c254SAlex Crichton /// There's quite a lot of unsafety riding on this method, especially 18467e28c254SAlex Crichton /// related to the ascription `T` of the byte `offset`. It's hoped that in 18477e28c254SAlex Crichton /// the future we're able to settle on an in theory safer design. 18487e28c254SAlex Crichton /// 18497e28c254SAlex Crichton /// # Safety 18507e28c254SAlex Crichton /// 18517e28c254SAlex Crichton /// This method is unsafe because the `offset` must be within bounds of the 18527e28c254SAlex Crichton /// `VMContext` object trailing this instance. Additionally `T` must be a 18537e28c254SAlex Crichton /// valid ascription of the value that resides at that location. vmctx_plus_offset_raw<T: VmSafe>(&self, offset: impl Into<u32>) -> NonNull<T>18547e28c254SAlex Crichton unsafe fn vmctx_plus_offset_raw<T: VmSafe>(&self, offset: impl Into<u32>) -> NonNull<T> { 18557e28c254SAlex Crichton // SAFETY: the safety requirements of `byte_add` are forwarded to this 18567e28c254SAlex Crichton // method's caller. 18577e28c254SAlex Crichton unsafe { 18587e28c254SAlex Crichton self.vmctx() 18597e28c254SAlex Crichton .byte_add(usize::try_from(offset.into()).unwrap()) 18607e28c254SAlex Crichton .cast() 18617e28c254SAlex Crichton } 18627e28c254SAlex Crichton } 18637e28c254SAlex Crichton 18647e28c254SAlex Crichton /// Helper above `vmctx_plus_offset_raw` which transfers the lifetime of 18657e28c254SAlex Crichton /// `&self` to the returned reference `&T`. 18667e28c254SAlex Crichton /// 18677e28c254SAlex Crichton /// # Safety 18687e28c254SAlex Crichton /// 18697e28c254SAlex Crichton /// See the safety documentation of `vmctx_plus_offset_raw`. vmctx_plus_offset<T: VmSafe>(&self, offset: impl Into<u32>) -> &T18707e28c254SAlex Crichton unsafe fn vmctx_plus_offset<T: VmSafe>(&self, offset: impl Into<u32>) -> &T { 18717e28c254SAlex Crichton // SAFETY: this method has the same safety requirements as 18727e28c254SAlex Crichton // `vmctx_plus_offset_raw`. 18737e28c254SAlex Crichton unsafe { self.vmctx_plus_offset_raw(offset).as_ref() } 18747e28c254SAlex Crichton } 18757e28c254SAlex Crichton 18767e28c254SAlex Crichton /// Helper above `vmctx_plus_offset_raw` which transfers the lifetime of 18777e28c254SAlex Crichton /// `&mut self` to the returned reference `&mut T`. 18787e28c254SAlex Crichton /// 18797e28c254SAlex Crichton /// # Safety 18807e28c254SAlex Crichton /// 18817e28c254SAlex Crichton /// See the safety documentation of `vmctx_plus_offset_raw`. vmctx_plus_offset_mut<T: VmSafe>( self: Pin<&mut Self>, offset: impl Into<u32>, ) -> &mut T18827e28c254SAlex Crichton unsafe fn vmctx_plus_offset_mut<T: VmSafe>( 18837e28c254SAlex Crichton self: Pin<&mut Self>, 18847e28c254SAlex Crichton offset: impl Into<u32>, 18857e28c254SAlex Crichton ) -> &mut T { 18867e28c254SAlex Crichton // SAFETY: this method has the same safety requirements as 18877e28c254SAlex Crichton // `vmctx_plus_offset_raw`. 18887e28c254SAlex Crichton unsafe { self.vmctx_plus_offset_raw(offset).as_mut() } 18897e28c254SAlex Crichton } 18907e28c254SAlex Crichton } 18917e28c254SAlex Crichton 18927e28c254SAlex Crichton impl<T: InstanceLayout> OwnedInstance<T> { 18937e28c254SAlex Crichton /// Allocates a new `OwnedInstance` and places `instance` inside of it. 18947e28c254SAlex Crichton /// 18957e28c254SAlex Crichton /// This will `instance` new(mut instance: T) -> Result<OwnedInstance<T>, OutOfMemory>1896a465eabfSNick Fitzgerald pub(super) fn new(mut instance: T) -> Result<OwnedInstance<T>, OutOfMemory> { 18977e28c254SAlex Crichton let layout = instance.layout(); 18987e28c254SAlex Crichton debug_assert!(layout.size() >= size_of_val(&instance)); 18997e28c254SAlex Crichton debug_assert!(layout.align() >= align_of_val(&instance)); 19007e28c254SAlex Crichton 19017e28c254SAlex Crichton // SAFETY: it's up to us to assert that `layout` has a non-zero size, 19027e28c254SAlex Crichton // which is asserted here. 19037e28c254SAlex Crichton let ptr = unsafe { 19047e28c254SAlex Crichton assert!(layout.size() > 0); 19057e28c254SAlex Crichton if T::INIT_ZEROED { 19067e28c254SAlex Crichton alloc::alloc::alloc_zeroed(layout) 19077e28c254SAlex Crichton } else { 19087e28c254SAlex Crichton alloc::alloc::alloc(layout) 19097e28c254SAlex Crichton } 19107e28c254SAlex Crichton }; 1911a465eabfSNick Fitzgerald let Some(instance_ptr) = NonNull::new(ptr.cast::<T>()) else { 1912a465eabfSNick Fitzgerald return Err(OutOfMemory::new(layout.size())); 1913a465eabfSNick Fitzgerald }; 19147e28c254SAlex Crichton 19157e28c254SAlex Crichton // SAFETY: it's part of the unsafe contract of `InstanceLayout` that the 19167e28c254SAlex Crichton // `add` here is appropriate for the layout allocated. 19177e28c254SAlex Crichton let vmctx_self_reference = unsafe { instance_ptr.add(1).cast() }; 19187e28c254SAlex Crichton instance.owned_vmctx_mut().vmctx_self_reference = vmctx_self_reference.into(); 19197e28c254SAlex Crichton 19207e28c254SAlex Crichton // SAFETY: we allocated above and it's an unsafe contract of 19217e28c254SAlex Crichton // `InstanceLayout` that the layout is suitable for writing the 19227e28c254SAlex Crichton // instance. 19237e28c254SAlex Crichton unsafe { 19247e28c254SAlex Crichton instance_ptr.write(instance); 19257e28c254SAlex Crichton } 19267e28c254SAlex Crichton 19277e28c254SAlex Crichton let ret = OwnedInstance { 19287e28c254SAlex Crichton instance: SendSyncPtr::new(instance_ptr), 19297e28c254SAlex Crichton _marker: marker::PhantomData, 19307e28c254SAlex Crichton }; 19317e28c254SAlex Crichton 19327e28c254SAlex Crichton // Double-check various vmctx calculations are correct. 19337e28c254SAlex Crichton debug_assert_eq!( 19347e28c254SAlex Crichton vmctx_self_reference.addr(), 19357e28c254SAlex Crichton // SAFETY: `InstanceLayout` should guarantee it's safe to add 1 to 19367e28c254SAlex Crichton // the last field to get a pointer to 1-byte-past-the-end of an 19377e28c254SAlex Crichton // object, which should be valid. 19387e28c254SAlex Crichton unsafe { NonNull::from(ret.get().owned_vmctx()).add(1).addr() } 19397e28c254SAlex Crichton ); 19407e28c254SAlex Crichton debug_assert_eq!(vmctx_self_reference.addr(), ret.get().vmctx().addr()); 19417e28c254SAlex Crichton 1942a465eabfSNick Fitzgerald Ok(ret) 19437e28c254SAlex Crichton } 19447e28c254SAlex Crichton 1945aad93a48SAlex Crichton /// Gets the raw underlying `&Instance` from this handle. get(&self) -> &T19467e28c254SAlex Crichton pub fn get(&self) -> &T { 1947aad93a48SAlex Crichton // SAFETY: this is an owned instance handle that retains exclusive 1948aad93a48SAlex Crichton // ownership of the `Instance` inside. With `&self` given we know 1949aad93a48SAlex Crichton // this pointer is valid valid and the returned lifetime is connected 1950aad93a48SAlex Crichton // to `self` so that should also be valid. 1951aad93a48SAlex Crichton unsafe { self.instance.as_non_null().as_ref() } 195272004aadSNick Fitzgerald } 195372004aadSNick Fitzgerald 1954aad93a48SAlex Crichton /// Same as [`Self::get`] except for mutability. get_mut(&mut self) -> Pin<&mut T>19557e28c254SAlex Crichton pub fn get_mut(&mut self) -> Pin<&mut T> { 1956aad93a48SAlex Crichton // SAFETY: The lifetime concerns here are the same as `get` above. 1957aad93a48SAlex Crichton // Otherwise `new_unchecked` is used here to uphold the contract that 1958aad93a48SAlex Crichton // instances are always pinned in memory. 1959aad93a48SAlex Crichton unsafe { Pin::new_unchecked(self.instance.as_non_null().as_mut()) } 196072004aadSNick Fitzgerald } 196172004aadSNick Fitzgerald } 196272004aadSNick Fitzgerald 19637e28c254SAlex Crichton impl<T: InstanceLayout> Drop for OwnedInstance<T> { drop(&mut self)1964aad93a48SAlex Crichton fn drop(&mut self) { 1965aad93a48SAlex Crichton unsafe { 19667e28c254SAlex Crichton let layout = self.get().layout(); 1967aad93a48SAlex Crichton ptr::drop_in_place(self.instance.as_ptr()); 1968aad93a48SAlex Crichton alloc::alloc::dealloc(self.instance.as_ptr().cast(), layout); 196972004aadSNick Fitzgerald } 197072004aadSNick Fitzgerald } 197172004aadSNick Fitzgerald } 1972