diff --git a/crates/wasmi/src/engine/executor.rs b/crates/wasmi/src/engine/executor.rs index 05a5d69788..4107aaa1fd 100644 --- a/crates/wasmi/src/engine/executor.rs +++ b/crates/wasmi/src/engine/executor.rs @@ -665,7 +665,7 @@ impl<'ctx, 'engine, 'func> Executor<'ctx, 'engine, 'func> { .map(FuncRef::from) .ok_or(TrapCode::TableOutOfBounds)?; let func = funcref.func().ok_or(TrapCode::IndirectCallToNull)?; - let actual_signature = self.ctx.get_func_type(func); + let actual_signature = self.ctx.resolve_func(func).ty_dedup(); let expected_signature = self .ctx .resolve_instance(self.frame.instance()) diff --git a/crates/wasmi/src/engine/mod.rs b/crates/wasmi/src/engine/mod.rs index 7a77eb1ee6..466916b320 100644 --- a/crates/wasmi/src/engine/mod.rs +++ b/crates/wasmi/src/engine/mod.rs @@ -43,9 +43,12 @@ pub(crate) use self::{ func_args::{FuncFinished, FuncParams, FuncResults}, func_types::DedupFuncType, }; -use super::{func::FuncEntityInner, AsContext, AsContextMut, Func}; use crate::{ core::{Trap, TrapCode}, + func::FuncEntity, + AsContext, + AsContextMut, + Func, FuncType, StoreContextMut, }; @@ -210,7 +213,7 @@ impl Engine { pub(crate) fn execute_func( &self, ctx: StoreContextMut, - func: Func, + func: &Func, params: impl CallParams, results: Results, ) -> Result<::Results, Trap> @@ -245,7 +248,7 @@ impl Engine { pub(crate) fn execute_func_resumable( &self, ctx: StoreContextMut, - func: Func, + func: &Func, params: impl CallParams, results: Results, ) -> Result::Results>, Trap> @@ -399,7 +402,7 @@ impl EngineInner { fn execute_func( &self, ctx: StoreContextMut, - func: Func, + func: &Func, params: impl CallParams, results: Results, ) -> Result<::Results, Trap> @@ -418,7 +421,7 @@ impl EngineInner { fn execute_func_resumable( &self, mut ctx: StoreContextMut, - func: Func, + func: &Func, params: impl CallParams, results: Results, ) -> Result::Results>, Trap> @@ -447,7 +450,7 @@ impl EngineInner { host_trap, }) => Ok(ResumableCallBase::Resumable(ResumableInvocation::new( ctx.as_context().store.engine().clone(), - func, + *func, host_func, host_trap, stack, @@ -586,7 +589,7 @@ impl<'engine> EngineExecutor<'engine> { fn execute_func( &mut self, mut ctx: StoreContextMut, - func: Func, + func: &Func, params: impl CallParams, results: Results, ) -> Result<::Results, TaggedTrap> @@ -594,14 +597,14 @@ impl<'engine> EngineExecutor<'engine> { Results: CallResults, { self.initialize_args(params); - match func.as_internal(ctx.as_context()) { - FuncEntityInner::Wasm(wasm_func) => { + match ctx.as_context().store.inner.resolve_func(func) { + FuncEntity::Wasm(wasm_func) => { let mut frame = self.stack.call_wasm_root(wasm_func, &self.res.code_map)?; let mut cache = InstanceCache::from(frame.instance()); self.execute_wasm_func(ctx.as_context_mut(), &mut frame, &mut cache)?; } - FuncEntityInner::Host(host_func) => { - let host_func = host_func.clone(); + FuncEntity::Host(host_func) => { + let host_func = *host_func; self.stack .call_host_root(ctx.as_context_mut(), host_func, &self.res.func_types)?; } @@ -686,13 +689,13 @@ impl<'engine> EngineExecutor<'engine> { None => return Ok(()), }, CallOutcome::NestedCall(called_func) => { - match called_func.as_internal(ctx.as_context()) { - FuncEntityInner::Wasm(wasm_func) => { + match ctx.as_context().store.inner.resolve_func(&called_func) { + FuncEntity::Wasm(wasm_func) => { *frame = self.stack.call_wasm(frame, wasm_func, &self.res.code_map)?; } - FuncEntityInner::Host(host_func) => { + FuncEntity::Host(host_func) => { cache.reset_default_memory_bytes(); - let host_func = host_func.clone(); + let host_func = *host_func; self.stack .call_host( ctx.as_context_mut(), diff --git a/crates/wasmi/src/engine/stack/mod.rs b/crates/wasmi/src/engine/stack/mod.rs index 52f0f73fff..2dac4bf70a 100644 --- a/crates/wasmi/src/engine/stack/mod.rs +++ b/crates/wasmi/src/engine/stack/mod.rs @@ -14,8 +14,8 @@ use crate::{ core::UntypedValue, func::{HostFuncEntity, WasmFuncEntity}, AsContext, - AsContextMut, Instance, + StoreContextMut, }; use core::{ fmt::{self, Display}, @@ -222,29 +222,23 @@ impl Stack { } /// Executes the given host function as root. - pub(crate) fn call_host_root( + pub(crate) fn call_host_root( &mut self, - ctx: C, - host_func: HostFuncEntity<::UserState>, + ctx: StoreContextMut, + host_func: HostFuncEntity, func_types: &FuncTypeRegistry, - ) -> Result<(), Trap> - where - C: AsContextMut, - { + ) -> Result<(), Trap> { self.call_host_impl(ctx, host_func, None, func_types) } /// Executes the given host function called by a Wasm function. - pub(crate) fn call_host( + pub(crate) fn call_host( &mut self, - ctx: C, + ctx: StoreContextMut, caller: &FuncFrame, - host_func: HostFuncEntity<::UserState>, + host_func: HostFuncEntity, func_types: &FuncTypeRegistry, - ) -> Result<(), Trap> - where - C: AsContextMut, - { + ) -> Result<(), Trap> { let instance = caller.instance(); self.call_host_impl(ctx, host_func, Some(instance), func_types) } @@ -256,16 +250,13 @@ impl Stack { /// - If the host function returns a host side error or trap. /// - If the value stack overflowed upon pushing parameters or results. #[inline(never)] - fn call_host_impl( + fn call_host_impl( &mut self, - mut ctx: C, - host_func: HostFuncEntity<::UserState>, + ctx: StoreContextMut, + host_func: HostFuncEntity, instance: Option<&Instance>, func_types: &FuncTypeRegistry, - ) -> Result<(), Trap> - where - C: AsContextMut, - { + ) -> Result<(), Trap> { // The host function signature is required for properly // adjusting, inspecting and manipulating the value stack. let (input_types, output_types) = func_types @@ -295,8 +286,13 @@ impl Stack { // Now we are ready to perform the host function call. // Note: We need to clone the host function due to some borrowing issues. // This should not be a big deal since host functions usually are cheap to clone. - host_func - .call(&mut ctx, instance, params_results) + let trampoline = ctx + .as_context() + .store + .resolve_trampoline(host_func.trampoline()) + .clone(); + trampoline + .call(ctx, instance, params_results) .map_err(|error| { // Note: We drop the values that have been temporarily added to // the stack to act as parameter and result buffer for the diff --git a/crates/wasmi/src/func/into_func.rs b/crates/wasmi/src/func/into_func.rs index f6280712dd..5c6d155d15 100644 --- a/crates/wasmi/src/func/into_func.rs +++ b/crates/wasmi/src/func/into_func.rs @@ -1,6 +1,6 @@ use super::{ super::engine::{FuncFinished, FuncParams, FuncResults}, - HostFuncTrampoline, + TrampolineEntity, }; use crate::{ core::{Trap, ValueType, F32, F64}, @@ -24,7 +24,7 @@ pub trait IntoFunc: Send + Sync + 'static { /// Converts the function into its `wasmi` signature and its trampoline. #[doc(hidden)] - fn into_func(self) -> (FuncType, HostFuncTrampoline); + fn into_func(self) -> (FuncType, TrampolineEntity); } macro_rules! impl_into_func { @@ -42,7 +42,7 @@ macro_rules! impl_into_func { type Results = ::Ok; #[allow(non_snake_case)] - fn into_func(self) -> (FuncType, HostFuncTrampoline) { + fn into_func(self) -> (FuncType, TrampolineEntity) { IntoFunc::into_func( move | _: Caller<'_, T>, @@ -69,12 +69,12 @@ macro_rules! impl_into_func { type Results = ::Ok; #[allow(non_snake_case)] - fn into_func(self) -> (FuncType, HostFuncTrampoline) { + fn into_func(self) -> (FuncType, TrampolineEntity) { let signature = FuncType::new( ::types(), ::types(), ); - let trampoline = HostFuncTrampoline::new( + let trampoline = TrampolineEntity::new( move |caller: Caller, params_results: FuncParams| -> Result { let (($($tuple,)*), func_results): (Self::Params, FuncResults) = params_results.decode_params(); let results: Self::Results = diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index 59f8873381..f8b57964df 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -47,103 +47,102 @@ impl ArenaIndex for FuncIdx { } } -/// A function instance. -#[derive(Debug)] -pub struct FuncEntity { - /// We wrap this enum in a struct so that we can make its - /// variants private. This is advantageous since they are - /// implementation details and not important to the user. - inner: FuncEntityInner, -} +/// A raw index to a host function trampoline entity. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct TrampolineIdx(usize); -impl Clone for FuncEntity { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } +impl ArenaIndex for TrampolineIdx { + fn into_usize(self) -> usize { + self.0 } -} -impl From for FuncEntity { - fn from(wasm_func: WasmFuncEntity) -> Self { - Self { - inner: FuncEntityInner::Wasm(wasm_func), - } + fn from_usize(index: usize) -> Self { + Self(index) } } -impl From> for FuncEntity { - fn from(host_func: HostFuncEntity) -> Self { - Self { - inner: FuncEntityInner::Host(host_func), - } +/// A host function reference. +#[derive(Debug, Copy, Clone)] +#[repr(transparent)] +pub struct Trampoline(Stored); + +impl Trampoline { + /// Creates a new host function reference. + pub(super) fn from_inner(stored: Stored) -> Self { + Self(stored) } -} -impl FuncEntity { - /// Creates a new Wasm function from the given raw parts. - pub fn new_wasm(signature: DedupFuncType, body: FuncBody, instance: Instance) -> Self { - Self::from(WasmFuncEntity::new(signature, body, instance)) + /// Returns the underlying stored representation. + pub(super) fn as_inner(&self) -> &Stored { + &self.0 } +} - /// Creates a new host function from the given dynamically typed closure. - pub fn new( - engine: &Engine, - ty: FuncType, - func: impl Fn(Caller<'_, T>, &[Value], &mut [Value]) -> Result<(), Trap> + Send + Sync + 'static, - ) -> Self { - Self::from(HostFuncEntity::new(engine, ty, func)) +/// A Wasm or host function instance. +#[derive(Debug)] +pub enum FuncEntity { + /// A Wasm function. + Wasm(WasmFuncEntity), + /// A host function. + Host(HostFuncEntity), +} + +impl From for FuncEntity { + fn from(func: WasmFuncEntity) -> Self { + Self::Wasm(func) } +} - /// Creates a new host function from the given dynamically typed closure. - pub fn wrap(engine: &Engine, func: impl IntoFunc) -> Self { - Self::from(HostFuncEntity::wrap(engine, func)) +impl From for FuncEntity { + fn from(func: HostFuncEntity) -> Self { + Self::Host(func) } +} - /// Returns a shared reference to the [`FuncEntityInner`]. - /// - /// # Note - /// - /// This can be used to efficiently match against host or Wasm - /// function entities and efficiently extract their properties. - pub(crate) fn as_internal(&self) -> &FuncEntityInner { - &self.inner +/// A host function reference and its function type. +#[derive(Debug, Copy, Clone)] +pub struct HostFuncEntity { + /// The function type of the host function. + ty: DedupFuncType, + /// A reference to the trampoline of the host function. + func: Trampoline, +} + +impl HostFuncEntity { + /// Creates a new [`HostFuncEntity`]. + pub fn new(ty: DedupFuncType, func: Trampoline) -> Self { + Self { ty, func } } - /// Returns the signature of the Wasm function. + /// Returns the signature of the host function. pub fn ty_dedup(&self) -> &DedupFuncType { - match self.as_internal() { - FuncEntityInner::Wasm(func) => func.ty_dedup(), - FuncEntityInner::Host(func) => func.ty_dedup(), - } + &self.ty } -} -/// The internal representation of a function instance. -/// -/// This can either be a host function or a Wasm function. -#[derive(Debug)] -pub(crate) enum FuncEntityInner { - /// A Wasm function instance. - Wasm(WasmFuncEntity), - /// A host function instance. - Host(HostFuncEntity), + /// Returns the [`Trampoline`] of the host function. + pub fn trampoline(&self) -> &Trampoline { + &self.func + } } -impl Clone for FuncEntityInner { - fn clone(&self) -> Self { +impl FuncEntity { + /// Returns the signature of the Wasm function. + pub fn ty_dedup(&self) -> &DedupFuncType { match self { - Self::Wasm(func) => Self::Wasm(func.clone()), - Self::Host(func) => Self::Host(func.clone()), + Self::Wasm(func) => func.ty_dedup(), + Self::Host(func) => func.ty_dedup(), } } } /// A Wasm function instance. #[derive(Debug, Clone)] -pub(crate) struct WasmFuncEntity { - signature: DedupFuncType, +pub struct WasmFuncEntity { + /// The function type of the Wasm function. + ty: DedupFuncType, + /// The compiled function body of the Wasm function. body: FuncBody, + /// The instance associated to the Wasm function. instance: Instance, } @@ -151,7 +150,7 @@ impl WasmFuncEntity { /// Creates a new Wasm function from the given raw parts. pub fn new(signature: DedupFuncType, body: FuncBody, instance: Instance) -> Self { Self { - signature, + ty: signature, body, instance, } @@ -159,7 +158,7 @@ impl WasmFuncEntity { /// Returns the signature of the Wasm function. pub fn ty_dedup(&self) -> &DedupFuncType { - &self.signature + &self.ty } /// Returns the instance where the [`Func`] belong to. @@ -174,55 +173,30 @@ impl WasmFuncEntity { } /// A host function instance. -pub(crate) struct HostFuncEntity { - signature: DedupFuncType, - trampoline: HostFuncTrampoline, +pub struct HostFuncTrampolineEntity { + /// The type of the associated host function. + ty: DedupFuncType, + /// The trampoline of the associated host function. + trampoline: TrampolineEntity, } -impl Clone for HostFuncEntity { +impl Clone for HostFuncTrampolineEntity { fn clone(&self) -> Self { Self { - signature: self.signature, + ty: self.ty, trampoline: self.trampoline.clone(), } } } -type HostFuncTrampolineFn = - dyn Fn(Caller, FuncParams) -> Result + Send + Sync + 'static; - -pub struct HostFuncTrampoline { - closure: Arc>, -} - -impl HostFuncTrampoline { - /// Creates a new [`HostFuncTrampoline`] from the given trampoline function. - pub fn new(trampoline: F) -> Self - where - F: Fn(Caller, FuncParams) -> Result + Send + Sync + 'static, - { - Self { - closure: Arc::new(trampoline), - } - } -} - -impl Clone for HostFuncTrampoline { - fn clone(&self) -> Self { - Self { - closure: self.closure.clone(), - } - } -} - -impl Debug for HostFuncEntity { +impl Debug for HostFuncTrampolineEntity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - Debug::fmt(&self.signature, f) + Debug::fmt(&self.ty, f) } } -impl HostFuncEntity { - /// Creates a new host function from the given dynamically typed closure. +impl HostFuncTrampolineEntity { + /// Creates a new host function trampoline from the given dynamically typed closure. pub fn new( engine: &Engine, ty: FuncType, @@ -236,7 +210,7 @@ impl HostFuncEntity { let results_iter = ty.results().iter().copied().map(Value::default); let len_params = ty.params().len(); let params_results: Box<[Value]> = params_iter.chain(results_iter).collect(); - let trampoline = >::new(move |caller, args| { + let trampoline = >::new(move |caller, args| { // We are required to clone the buffer because we are operating within a `Fn`. // This way the trampoline closure only has to own a single slice buffer. // Note: An alternative solution is to use interior mutability but that solution @@ -247,29 +221,53 @@ impl HostFuncEntity { func(caller, params, results)?; Ok(func_results.encode_results_from_slice(results).unwrap()) }); - let signature = engine.alloc_func_type(ty.clone()); - Self { - signature, - trampoline, - } + let ty = engine.alloc_func_type(ty.clone()); + Self { ty, trampoline } } - /// Creates a new host function from the given statically typed closure. + /// Creates a new host function trampoline from the given statically typed closure. pub fn wrap(engine: &Engine, func: impl IntoFunc) -> Self { let (signature, trampoline) = func.into_func(); - let signature = engine.alloc_func_type(signature); - Self { - signature, - trampoline, - } + let ty = engine.alloc_func_type(signature); + Self { ty, trampoline } } /// Returns the signature of the host function. pub fn ty_dedup(&self) -> &DedupFuncType { - &self.signature + &self.ty + } + + /// Returns the trampoline of the host function. + pub fn trampoline(&self) -> &TrampolineEntity { + &self.trampoline + } +} + +type TrampolineFn = + dyn Fn(Caller, FuncParams) -> Result + Send + Sync + 'static; + +pub struct TrampolineEntity { + closure: Arc>, +} + +impl Debug for TrampolineEntity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TrampolineEntity").finish() + } +} + +impl TrampolineEntity { + /// Creates a new [`TrampolineEntity`] from the given host function. + pub fn new(trampoline: F) -> Self + where + F: Fn(Caller, FuncParams) -> Result + Send + Sync + 'static, + { + Self { + closure: Arc::new(trampoline), + } } - /// Calls the host function with the given inputs. + /// Calls the host function trampoline with the given inputs. /// /// The result is written back into the `outputs` buffer. pub fn call( @@ -279,7 +277,15 @@ impl HostFuncEntity { params: FuncParams, ) -> Result { let caller = >::new(&mut ctx, instance); - (self.trampoline.closure)(caller, params) + (self.closure)(caller, params) + } +} + +impl Clone for TrampolineEntity { + fn clone(&self) -> Self { + Self { + closure: self.closure.clone(), + } } } @@ -328,8 +334,14 @@ impl Func { func: impl Fn(Caller<'_, T>, &[Value], &mut [Value]) -> Result<(), Trap> + Send + Sync + 'static, ) -> Self { let engine = ctx.as_context().store.engine(); - let func = FuncEntity::new(engine, ty, func); - ctx.as_context_mut().store.alloc_func(func) + let host_func = HostFuncTrampolineEntity::new(engine, ty, func); + let ty_dedup = *host_func.ty_dedup(); + let trampoline = host_func.trampoline().clone(); + let func = ctx.as_context_mut().store.alloc_trampoline(trampoline); + ctx.as_context_mut() + .store + .inner + .alloc_func(HostFuncEntity::new(ty_dedup, func).into()) } /// Creates a new host function from the given closure. @@ -338,8 +350,14 @@ impl Func { func: impl IntoFunc, ) -> Self { let engine = ctx.as_context().store.engine(); - let func = FuncEntity::wrap(engine, func); - ctx.as_context_mut().store.alloc_func(func) + let host_func = HostFuncTrampolineEntity::wrap(engine, func); + let ty_dedup = *host_func.ty_dedup(); + let trampoline = host_func.trampoline().clone(); + let func = ctx.as_context_mut().store.alloc_trampoline(trampoline); + ctx.as_context_mut() + .store + .inner + .alloc_func(HostFuncEntity::new(ty_dedup, func).into()) } /// Returns the signature of the function. @@ -347,7 +365,7 @@ impl Func { &self, ctx: impl Into>, ) -> &'a DedupFuncType { - ctx.into().store.resolve_func(self).ty_dedup() + ctx.into().store.inner.resolve_func(self).ty_dedup() } /// Returns the function type of the [`Func`]. @@ -381,7 +399,7 @@ impl Func { // Note: Cloning an [`Engine`] is intentionally a cheap operation. ctx.as_context().store.engine().clone().execute_func( ctx.as_context_mut(), - *self, + self, inputs, outputs, )?; @@ -423,7 +441,7 @@ impl Func { .store .engine() .clone() - .execute_func_resumable(ctx.as_context_mut(), *self, inputs, outputs) + .execute_func_resumable(ctx.as_context_mut(), self, inputs, outputs) .map_err(Into::into) .map(ResumableCall::new) } @@ -481,17 +499,4 @@ impl Func { { TypedFunc::new(ctx, *self) } - - /// Returns the internal representation of the [`Func`] instance. - /// - /// # Note - /// - /// This is intentionally a private API and mainly provided for efficient - /// execution of the `wasmi` interpreter upon function dispatch. - pub(crate) fn as_internal<'a, T: 'a>( - &self, - ctx: impl Into>, - ) -> &'a FuncEntityInner { - ctx.into().store.resolve_func(self).as_internal() - } } diff --git a/crates/wasmi/src/func/typed_func.rs b/crates/wasmi/src/func/typed_func.rs index 766fa87f49..b98fd3bdbf 100644 --- a/crates/wasmi/src/func/typed_func.rs +++ b/crates/wasmi/src/func/typed_func.rs @@ -97,7 +97,7 @@ where // Note: Cloning an [`Engine`] is intentionally a cheap operation. ctx.as_context().store.engine().clone().execute_func( ctx.as_context_mut(), - self.func, + &self.func, params, >::default(), ) @@ -130,7 +130,7 @@ where .clone() .execute_func_resumable( ctx.as_context_mut(), - self.func, + &self.func, params, >::default(), ) diff --git a/crates/wasmi/src/instance/mod.rs b/crates/wasmi/src/instance/mod.rs index bd23e85377..28ab0aef5d 100644 --- a/crates/wasmi/src/instance/mod.rs +++ b/crates/wasmi/src/instance/mod.rs @@ -104,8 +104,8 @@ impl InstanceEntity { } /// Returns the signature at the `index` if any. - pub fn get_signature(&self, index: u32) -> Option { - self.func_types.get(index as usize).copied() + pub fn get_signature(&self, index: u32) -> Option<&DedupFuncType> { + self.func_types.get(index as usize) } /// Returns the [`DataSegment`] at the `index` if any. diff --git a/crates/wasmi/src/linker.rs b/crates/wasmi/src/linker.rs index 5edadd28fd..52ba332ee9 100644 --- a/crates/wasmi/src/linker.rs +++ b/crates/wasmi/src/linker.rs @@ -1,6 +1,6 @@ use super::{AsContextMut, Error, Extern, InstancePre, Module}; use crate::{ - func::HostFuncEntity, + func::HostFuncTrampolineEntity, module::{ImportName, ImportType}, AsContext, Engine, @@ -298,7 +298,7 @@ enum Definition { /// An external item from an [`Instance`](crate::Instance). Extern(Extern), /// A [`Linker`] internal host function. - HostFunc(HostFuncEntity), + HostFunc(HostFuncTrampolineEntity), } impl Clone for Definition { @@ -345,17 +345,17 @@ impl<'a, T> Debug for DebugDefinitions<'a, T> { } } -/// [`Debug`]-wrapper for [`HostFuncEntity`] in the [`Linker`]. +/// [`Debug`]-wrapper for [`HostFuncTrampolineEntity`] in the [`Linker`]. pub struct DebugHostFuncEntity<'a, T> { /// The [`Engine`] of the [`Linker`]. engine: &'a Engine, /// The host function to be [`Debug`] formatted. - host_func: &'a HostFuncEntity, + host_func: &'a HostFuncTrampolineEntity, } impl<'a, T> DebugHostFuncEntity<'a, T> { - /// Create a new [`Debug`]-wrapper for the [`HostFuncEntity`]. - fn new(engine: &'a Engine, host_func: &'a HostFuncEntity) -> Self { + /// Create a new [`Debug`]-wrapper for the [`HostFuncTrampolineEntity`]. + fn new(engine: &'a Engine, host_func: &'a HostFuncTrampolineEntity) -> Self { Self { engine, host_func } } } diff --git a/crates/wasmi/src/module/instantiate/mod.rs b/crates/wasmi/src/module/instantiate/mod.rs index 93f3685bd5..9abe634180 100644 --- a/crates/wasmi/src/module/instantiate/mod.rs +++ b/crates/wasmi/src/module/instantiate/mod.rs @@ -7,6 +7,7 @@ mod tests; pub use self::{error::InstantiationError, pre::InstancePre}; use super::{element::ElementSegmentKind, export, DataSegmentKind, InitExpr, Module}; use crate::{ + func::WasmFuncEntity, memory::DataSegment, AsContext, AsContextMut, @@ -14,7 +15,6 @@ use crate::{ Error, Extern, ExternType, - FuncEntity, FuncRef, FuncType, Global, @@ -166,10 +166,12 @@ impl Module { handle: Instance, ) { for (func_type, func_body) in self.internal_funcs() { + let wasm_func = WasmFuncEntity::new(func_type, func_body, handle); let func = context .as_context_mut() .store - .alloc_func(FuncEntity::new_wasm(func_type, func_body, handle)); + .inner + .alloc_func(wasm_func.into()); builder.push_func(func); } } diff --git a/crates/wasmi/src/store.rs b/crates/wasmi/src/store.rs index b10cf67724..6740f1c0fb 100644 --- a/crates/wasmi/src/store.rs +++ b/crates/wasmi/src/store.rs @@ -1,5 +1,8 @@ -use super::{ +use crate::{ engine::DedupFuncType, + externref::{ExternObject, ExternObjectEntity, ExternObjectIdx}, + func::{Trampoline, TrampolineEntity, TrampolineIdx}, + memory::DataSegment, DataSegmentEntity, DataSegmentIdx, ElementSegment, @@ -23,15 +26,11 @@ use super::{ TableEntity, TableIdx, }; -use crate::{ - externref::{ExternObject, ExternObjectEntity, ExternObjectIdx}, - memory::DataSegment, -}; use core::{ fmt::{self, Debug}, sync::atomic::{AtomicU32, Ordering}, }; -use wasmi_arena::{Arena, ArenaIndex, ComponentVec, GuardedEntity}; +use wasmi_arena::{Arena, ArenaIndex, GuardedEntity}; use wasmi_core::TrapCode; /// A unique store index. @@ -78,8 +77,8 @@ pub struct Store { /// This is re-exported to the rest of the crate since /// it is used directly by the engine's executor. pub(crate) inner: StoreInner, - /// Stored Wasm or host functions. - funcs: Arena>, + /// Stored host function trampolines. + trampolines: Arena>, /// User provided host data owned by the [`Store`]. data: T, } @@ -91,13 +90,8 @@ pub struct StoreInner { /// /// Used to protect against invalid entity indices. store_idx: StoreIdx, - /// Stores the function type for each function. - /// - /// # Note - /// - /// This is required so that the [`Engine`] can work entirely - /// with a `&mut StoreInner` reference. - func_types: ComponentVec, + /// Stored Wasm or host functions. + funcs: Arena, /// Stored linear memories. memories: Arena, /// Stored tables. @@ -233,7 +227,7 @@ impl StoreInner { StoreInner { engine: engine.clone(), store_idx: StoreIdx::new(), - func_types: ComponentVec::new(), + funcs: Arena::new(), memories: Arena::new(), tables: Arena::new(), globals: Arena::new(), @@ -287,31 +281,6 @@ impl StoreInner { }) } - /// Registers the `func_type` for the given `func`. - /// - /// # Note - /// - /// This is required so that the [`Engine`] can work entirely - /// with a `&mut StoreInner` reference. - pub fn register_func_type(&mut self, func: Func, func_type: &DedupFuncType) { - let idx = self.unwrap_stored(func.as_inner()); - let previous = self.func_types.set(idx, *func_type); - debug_assert!(previous.is_none()); - } - - /// Returns the [`DedupFuncType`] for the given [`Func`]. - /// - /// # Note - /// - /// Panics if no [`DedupFuncType`] for the given [`Func`] was registered. - pub fn get_func_type(&self, func: &Func) -> DedupFuncType { - let idx = self.unwrap_stored(func.as_inner()); - self.func_types - .get(idx) - .copied() - .unwrap_or_else(|| panic!("missing function type for func: {func:?}")) - } - /// Allocates a new [`GlobalEntity`] and returns a [`Global`] reference to it. pub fn alloc_global(&mut self, global: GlobalEntity) -> Global { let global = self.globals.alloc(global); @@ -694,6 +663,25 @@ impl StoreInner { pub fn resolve_external_object(&self, object: &ExternObject) -> &ExternObjectEntity { self.resolve(object.as_inner(), &self.extern_objects) } + + /// Allocates a new Wasm or host [`FuncEntity`] and returns a [`Func`] reference to it. + pub fn alloc_func(&mut self, func: FuncEntity) -> Func { + let idx = self.funcs.alloc(func); + Func::from_inner(self.wrap_stored(idx)) + } + + /// Returns a shared reference to the associated entity of the Wasm or host function. + /// + /// # Panics + /// + /// - If the [`Func`] does not originate from this [`Store`]. + /// - If the [`Func`] cannot be resolved to its entity. + pub fn resolve_func(&self, func: &Func) -> &FuncEntity { + let entity_index = self.unwrap_stored(func.as_inner()); + self.funcs.get(entity_index).unwrap_or_else(|| { + panic!("failed to resolve stored Wasm or host function: {entity_index:?}") + }) + } } impl Store { @@ -701,7 +689,7 @@ impl Store { pub fn new(engine: &Engine, data: T) -> Self { Self { inner: StoreInner::new(engine), - funcs: Arena::new(), + trampolines: Arena::new(), data, } } @@ -784,13 +772,10 @@ impl Store { .map_err(|_error| FuelError::out_of_fuel()) } - /// Allocates a new Wasm or host [`FuncEntity`] and returns a [`Func`] reference to it. - pub(super) fn alloc_func(&mut self, func: FuncEntity) -> Func { - let func_type = *func.ty_dedup(); - let idx = self.funcs.alloc(func); - let func = Func::from_inner(self.inner.wrap_stored(idx)); - self.inner.register_func_type(func, &func_type); - func + /// Allocates a new [`TrampolineEntity`] and returns a [`Trampoline`] reference to it. + pub(super) fn alloc_trampoline(&mut self, func: TrampolineEntity) -> Trampoline { + let idx = self.trampolines.alloc(func); + Trampoline::from_inner(self.inner.wrap_stored(idx)) } /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`] @@ -812,17 +797,17 @@ impl Store { (self.inner.resolve_memory_mut(memory), &mut self.data) } - /// Returns a shared reference to the associated entity of the Wasm or host function. + /// Returns a shared reference to the associated entity of the host function trampoline. /// /// # Panics /// - /// - If the [`Func`] does not originate from this [`Store`]. - /// - If the [`Func`] cannot be resolved to its entity. - pub(super) fn resolve_func(&self, func: &Func) -> &FuncEntity { + /// - If the [`Trampoline`] does not originate from this [`Store`]. + /// - If the [`Trampoline`] cannot be resolved to its entity. + pub(super) fn resolve_trampoline(&self, func: &Trampoline) -> &TrampolineEntity { let entity_index = self.inner.unwrap_stored(func.as_inner()); - self.funcs.get(entity_index).unwrap_or_else(|| { - panic!("failed to resolve stored Wasm or host function: {entity_index:?}") - }) + self.trampolines + .get(entity_index) + .unwrap_or_else(|| panic!("failed to resolve stored host function: {entity_index:?}")) } }