From 141d34cd8f93e31127072c2dec81f294ec14ca86 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 20:46:03 +0100 Subject: [PATCH 01/13] rename field signature -> ty --- crates/wasmi/src/func/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index 59f8873381..4e01d54ce1 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -142,7 +142,7 @@ impl Clone for FuncEntityInner { /// A Wasm function instance. #[derive(Debug, Clone)] pub(crate) struct WasmFuncEntity { - signature: DedupFuncType, + ty: DedupFuncType, body: FuncBody, instance: Instance, } @@ -151,7 +151,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 +159,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. @@ -175,14 +175,14 @@ impl WasmFuncEntity { /// A host function instance. pub(crate) struct HostFuncEntity { - signature: DedupFuncType, + ty: DedupFuncType, trampoline: HostFuncTrampoline, } impl Clone for HostFuncEntity { fn clone(&self) -> Self { Self { - signature: self.signature, + ty: self.ty, trampoline: self.trampoline.clone(), } } @@ -217,7 +217,7 @@ impl Clone for HostFuncTrampoline { impl Debug for HostFuncEntity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - Debug::fmt(&self.signature, f) + Debug::fmt(&self.ty, f) } } @@ -249,7 +249,7 @@ impl HostFuncEntity { }); let signature = engine.alloc_func_type(ty.clone()); Self { - signature, + ty: signature, trampoline, } } @@ -259,14 +259,14 @@ impl HostFuncEntity { let (signature, trampoline) = func.into_func(); let signature = engine.alloc_func_type(signature); Self { - signature, + ty: signature, trampoline, } } /// Returns the signature of the host function. pub fn ty_dedup(&self) -> &DedupFuncType { - &self.signature + &self.ty } /// Calls the host function with the given inputs. From 210906bbe09737637357d05c3c5077fc2b72e201 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 20:48:10 +0100 Subject: [PATCH 02/13] remove Clone from FuncEntity and FuncEntityInner --- crates/wasmi/src/func/mod.rs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index 4e01d54ce1..4b6c31f480 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -56,14 +56,6 @@ pub struct FuncEntity { inner: FuncEntityInner, } -impl Clone for FuncEntity { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } -} - impl From for FuncEntity { fn from(wasm_func: WasmFuncEntity) -> Self { Self { @@ -130,15 +122,6 @@ pub(crate) enum FuncEntityInner { Host(HostFuncEntity), } -impl Clone for FuncEntityInner { - fn clone(&self) -> Self { - match self { - Self::Wasm(func) => Self::Wasm(func.clone()), - Self::Host(func) => Self::Host(func.clone()), - } - } -} - /// A Wasm function instance. #[derive(Debug, Clone)] pub(crate) struct WasmFuncEntity { From a1782f061e24baf6050188d05f79f4635cf7c3f2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 20:54:03 +0100 Subject: [PATCH 03/13] remove FuncEntityInner --- crates/wasmi/src/engine/mod.rs | 13 +++++--- crates/wasmi/src/func/mod.rs | 59 ++++++++++------------------------ 2 files changed, 25 insertions(+), 47 deletions(-) diff --git a/crates/wasmi/src/engine/mod.rs b/crates/wasmi/src/engine/mod.rs index 7a77eb1ee6..0e77006862 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, }; @@ -595,12 +598,12 @@ impl<'engine> EngineExecutor<'engine> { { self.initialize_args(params); match func.as_internal(ctx.as_context()) { - FuncEntityInner::Wasm(wasm_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) => { + FuncEntity::Host(host_func) => { let host_func = host_func.clone(); self.stack .call_host_root(ctx.as_context_mut(), host_func, &self.res.func_types)?; @@ -687,10 +690,10 @@ impl<'engine> EngineExecutor<'engine> { }, CallOutcome::NestedCall(called_func) => { match called_func.as_internal(ctx.as_context()) { - FuncEntityInner::Wasm(wasm_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(); self.stack diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index 4b6c31f480..823f16361e 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -47,28 +47,24 @@ impl ArenaIndex for FuncIdx { } } -/// A function instance. +/// A Wasm or host 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, +pub enum FuncEntity { + /// A Wasm function. + Wasm(WasmFuncEntity), + /// A host function. + Host(HostFuncEntity), } impl From for FuncEntity { - fn from(wasm_func: WasmFuncEntity) -> Self { - Self { - inner: FuncEntityInner::Wasm(wasm_func), - } + fn from(func: WasmFuncEntity) -> Self { + Self::Wasm(func) } } impl From> for FuncEntity { - fn from(host_func: HostFuncEntity) -> Self { - Self { - inner: FuncEntityInner::Host(host_func), - } + fn from(func: HostFuncEntity) -> Self { + Self::Host(func) } } @@ -92,39 +88,18 @@ impl FuncEntity { Self::from(HostFuncEntity::wrap(engine, 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 - } - /// Returns the signature of the Wasm function. pub fn ty_dedup(&self) -> &DedupFuncType { - match self.as_internal() { - FuncEntityInner::Wasm(func) => func.ty_dedup(), - FuncEntityInner::Host(func) => func.ty_dedup(), + match self { + Self::Wasm(func) => func.ty_dedup(), + Self::Host(func) => func.ty_dedup(), } } } -/// 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), -} - /// A Wasm function instance. #[derive(Debug, Clone)] -pub(crate) struct WasmFuncEntity { +pub struct WasmFuncEntity { ty: DedupFuncType, body: FuncBody, instance: Instance, @@ -157,7 +132,7 @@ impl WasmFuncEntity { } /// A host function instance. -pub(crate) struct HostFuncEntity { +pub struct HostFuncEntity { ty: DedupFuncType, trampoline: HostFuncTrampoline, } @@ -474,7 +449,7 @@ impl Func { pub(crate) fn as_internal<'a, T: 'a>( &self, ctx: impl Into>, - ) -> &'a FuncEntityInner { - ctx.into().store.resolve_func(self).as_internal() + ) -> &'a FuncEntity { + ctx.into().store.resolve_func(self) } } From 8dcb0f6393afb84980fbb7472491cd2073f4fb51 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 20:59:14 +0100 Subject: [PATCH 04/13] pass Func by reference instead of by value --- crates/wasmi/src/engine/mod.rs | 12 ++++++------ crates/wasmi/src/func/mod.rs | 4 ++-- crates/wasmi/src/func/typed_func.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/wasmi/src/engine/mod.rs b/crates/wasmi/src/engine/mod.rs index 0e77006862..69d64bdf37 100644 --- a/crates/wasmi/src/engine/mod.rs +++ b/crates/wasmi/src/engine/mod.rs @@ -213,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> @@ -248,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> @@ -402,7 +402,7 @@ impl EngineInner { fn execute_func( &self, ctx: StoreContextMut, - func: Func, + func: &Func, params: impl CallParams, results: Results, ) -> Result<::Results, Trap> @@ -421,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> @@ -450,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, @@ -589,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> diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index 823f16361e..eb89f66783 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -339,7 +339,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, )?; @@ -381,7 +381,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) } 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(), ) From 5d30615d90d271c35ac939c0beec788532034456 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 20:59:27 +0100 Subject: [PATCH 05/13] remove Func::as_internal --- crates/wasmi/src/engine/mod.rs | 4 ++-- crates/wasmi/src/func/mod.rs | 13 ------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/crates/wasmi/src/engine/mod.rs b/crates/wasmi/src/engine/mod.rs index 69d64bdf37..d3f2797b7e 100644 --- a/crates/wasmi/src/engine/mod.rs +++ b/crates/wasmi/src/engine/mod.rs @@ -597,7 +597,7 @@ impl<'engine> EngineExecutor<'engine> { Results: CallResults, { self.initialize_args(params); - match func.as_internal(ctx.as_context()) { + match ctx.as_context().store.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()); @@ -689,7 +689,7 @@ impl<'engine> EngineExecutor<'engine> { None => return Ok(()), }, CallOutcome::NestedCall(called_func) => { - match called_func.as_internal(ctx.as_context()) { + match ctx.as_context().store.resolve_func(&called_func) { FuncEntity::Wasm(wasm_func) => { *frame = self.stack.call_wasm(frame, wasm_func, &self.res.code_map)?; } diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index eb89f66783..7d7f784e90 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -439,17 +439,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 FuncEntity { - ctx.into().store.resolve_func(self) - } } From 9a03919b611551f32e6be6b96ddedf186392c8f0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 21:06:03 +0100 Subject: [PATCH 06/13] merge imports in store --- crates/wasmi/src/store.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/wasmi/src/store.rs b/crates/wasmi/src/store.rs index b10cf67724..069e3e4da8 100644 --- a/crates/wasmi/src/store.rs +++ b/crates/wasmi/src/store.rs @@ -1,5 +1,7 @@ -use super::{ +use crate::{ engine::DedupFuncType, + externref::{ExternObject, ExternObjectEntity, ExternObjectIdx}, + memory::DataSegment, DataSegmentEntity, DataSegmentIdx, ElementSegment, @@ -23,10 +25,6 @@ use super::{ TableEntity, TableIdx, }; -use crate::{ - externref::{ExternObject, ExternObjectEntity, ExternObjectIdx}, - memory::DataSegment, -}; use core::{ fmt::{self, Debug}, sync::atomic::{AtomicU32, Ordering}, From f16158ae77b42ca67fce0136eb1af19f3a860f75 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 22:13:56 +0100 Subject: [PATCH 07/13] move funcs into StoreInner Now Store only stores the host function trampolines because they are the only types that need to be generic over the host state. --- crates/wasmi/src/engine/mod.rs | 12 ++- crates/wasmi/src/func/mod.rs | 99 ++++++++++++++++------ crates/wasmi/src/module/instantiate/mod.rs | 6 +- crates/wasmi/src/store.rs | 57 +++++++++---- 4 files changed, 129 insertions(+), 45 deletions(-) diff --git a/crates/wasmi/src/engine/mod.rs b/crates/wasmi/src/engine/mod.rs index d3f2797b7e..a3a93b6321 100644 --- a/crates/wasmi/src/engine/mod.rs +++ b/crates/wasmi/src/engine/mod.rs @@ -597,13 +597,17 @@ impl<'engine> EngineExecutor<'engine> { Results: CallResults, { self.initialize_args(params); - match ctx.as_context().store.resolve_func(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)?; } FuncEntity::Host(host_func) => { + let host_func = ctx + .as_context() + .store + .resolve_host_func(host_func.host_func()); let host_func = host_func.clone(); self.stack .call_host_root(ctx.as_context_mut(), host_func, &self.res.func_types)?; @@ -689,11 +693,15 @@ impl<'engine> EngineExecutor<'engine> { None => return Ok(()), }, CallOutcome::NestedCall(called_func) => { - match ctx.as_context().store.resolve_func(&called_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)?; } FuncEntity::Host(host_func) => { + let host_func = ctx + .as_context() + .store + .resolve_host_func(host_func.host_func()); cache.reset_default_memory_bytes(); let host_func = host_func.clone(); self.stack diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index 7d7f784e90..4cd42c7075 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -47,47 +47,85 @@ impl ArenaIndex for FuncIdx { } } +/// A raw index to a host function entity. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct HostFuncIdx(usize); + +impl ArenaIndex for HostFuncIdx { + fn into_usize(self) -> usize { + self.0 + } + + fn from_usize(index: usize) -> Self { + Self(index) + } +} + +/// A host function reference. +#[derive(Debug, Copy, Clone)] +#[repr(transparent)] +pub struct HostFunc(Stored); + +impl HostFunc { + /// Creates a new host function reference. + pub(super) fn from_inner(stored: Stored) -> Self { + Self(stored) + } + + /// Returns the underlying stored representation. + pub(super) fn as_inner(&self) -> &Stored { + &self.0 + } +} + /// A Wasm or host function instance. #[derive(Debug)] -pub enum FuncEntity { +pub enum FuncEntity { /// A Wasm function. Wasm(WasmFuncEntity), /// A host function. - Host(HostFuncEntity), + Host(TypedHostFunc), } -impl From for FuncEntity { +impl From for FuncEntity { fn from(func: WasmFuncEntity) -> Self { Self::Wasm(func) } } -impl From> for FuncEntity { - fn from(func: HostFuncEntity) -> Self { +impl From for FuncEntity { + fn from(func: TypedHostFunc) -> Self { Self::Host(func) } } -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)) +/// A host function reference and its function type. +#[derive(Debug, Copy, Clone)] +pub struct TypedHostFunc { + /// The function type of the host function. + ty: DedupFuncType, + /// The host function reference. + func: HostFunc, +} + +impl TypedHostFunc { + /// Creates a new [`TypedHostFunc`]. + pub fn new(ty: DedupFuncType, func: HostFunc) -> Self { + Self { ty, func } } - /// 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)) + /// Returns the signature of the host function. + pub fn ty_dedup(&self) -> &DedupFuncType { + &self.ty } - /// 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)) + /// Returns the underlying [`HostFunc`]. + pub fn host_func(&self) -> &HostFunc { + &self.func } +} +impl FuncEntity { /// Returns the signature of the Wasm function. pub fn ty_dedup(&self) -> &DedupFuncType { match self { @@ -100,8 +138,11 @@ impl FuncEntity { /// A Wasm function instance. #[derive(Debug, Clone)] 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, } @@ -286,8 +327,13 @@ 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 = HostFuncEntity::new(engine, ty, func); + let ty_dedup = *host_func.ty_dedup(); + let func = ctx.as_context_mut().store.alloc_host_func(host_func); + ctx.as_context_mut() + .store + .inner + .alloc_func(TypedHostFunc::new(ty_dedup, func).into()) } /// Creates a new host function from the given closure. @@ -296,8 +342,13 @@ 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 = HostFuncEntity::wrap(engine, func); + let ty_dedup = *host_func.ty_dedup(); + let func = ctx.as_context_mut().store.alloc_host_func(host_func); + ctx.as_context_mut() + .store + .inner + .alloc_func(TypedHostFunc::new(ty_dedup, func).into()) } /// Returns the signature of the function. @@ -305,7 +356,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`]. 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 069e3e4da8..c8169a2f51 100644 --- a/crates/wasmi/src/store.rs +++ b/crates/wasmi/src/store.rs @@ -1,6 +1,7 @@ use crate::{ engine::DedupFuncType, externref::{ExternObject, ExternObjectEntity, ExternObjectIdx}, + func::{HostFunc, HostFuncEntity, HostFuncIdx}, memory::DataSegment, DataSegmentEntity, DataSegmentIdx, @@ -76,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 functions. + host_funcs: Arena>, /// User provided host data owned by the [`Store`]. data: T, } @@ -96,6 +97,8 @@ pub struct StoreInner { /// 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. @@ -232,6 +235,7 @@ impl StoreInner { engine: engine.clone(), store_idx: StoreIdx::new(), func_types: ComponentVec::new(), + funcs: Arena::new(), memories: Arena::new(), tables: Arena::new(), globals: Arena::new(), @@ -692,6 +696,28 @@ 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 func_type = *func.ty_dedup(); + let idx = self.funcs.alloc(func); + let func = Func::from_inner(self.wrap_stored(idx)); + self.register_func_type(func, &func_type); + func + } + + /// 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 { @@ -699,7 +725,7 @@ impl Store { pub fn new(engine: &Engine, data: T) -> Self { Self { inner: StoreInner::new(engine), - funcs: Arena::new(), + host_funcs: Arena::new(), data, } } @@ -782,13 +808,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 [`HostFuncEntity`] and returns a [`Func`] reference to it. + pub(super) fn alloc_host_func(&mut self, func: HostFuncEntity) -> HostFunc { + let idx = self.host_funcs.alloc(func); + HostFunc::from_inner(self.inner.wrap_stored(idx)) } /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`] @@ -810,17 +833,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. /// /// # 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 [`HostFunc`] does not originate from this [`Store`]. + /// - If the [`HostFunc`] cannot be resolved to its entity. + pub(super) fn resolve_host_func(&self, func: &HostFunc) -> &HostFuncEntity { 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.host_funcs + .get(entity_index) + .unwrap_or_else(|| panic!("failed to resolve stored host function: {entity_index:?}")) } } From 99a05a0def398409d4a1255ec878dd1c82339fd6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 22:35:33 +0100 Subject: [PATCH 08/13] simplify code --- crates/wasmi/src/func/mod.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index 4cd42c7075..d734487a46 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -246,21 +246,15 @@ impl HostFuncEntity { func(caller, params, results)?; Ok(func_results.encode_results_from_slice(results).unwrap()) }); - let signature = engine.alloc_func_type(ty.clone()); - Self { - ty: signature, - trampoline, - } + let ty = engine.alloc_func_type(ty.clone()); + Self { ty, trampoline } } /// Creates a new host function 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 { - ty: signature, - trampoline, - } + let ty = engine.alloc_func_type(signature); + Self { ty, trampoline } } /// Returns the signature of the host function. From fa9861ae4b5ad7da8d35c6bd6d237f4907695ab4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 22:49:13 +0100 Subject: [PATCH 09/13] lots of renamings to clear up the refactoring --- crates/wasmi/src/engine/mod.rs | 4 +- crates/wasmi/src/engine/stack/mod.rs | 8 +-- crates/wasmi/src/func/into_func.rs | 10 ++-- crates/wasmi/src/func/mod.rs | 74 ++++++++++++++-------------- crates/wasmi/src/linker.rs | 8 +-- crates/wasmi/src/store.rs | 32 +++++++----- 6 files changed, 72 insertions(+), 64 deletions(-) diff --git a/crates/wasmi/src/engine/mod.rs b/crates/wasmi/src/engine/mod.rs index a3a93b6321..f511da7431 100644 --- a/crates/wasmi/src/engine/mod.rs +++ b/crates/wasmi/src/engine/mod.rs @@ -607,7 +607,7 @@ impl<'engine> EngineExecutor<'engine> { let host_func = ctx .as_context() .store - .resolve_host_func(host_func.host_func()); + .resolve_trampoline(host_func.trampoline()); let host_func = host_func.clone(); self.stack .call_host_root(ctx.as_context_mut(), host_func, &self.res.func_types)?; @@ -701,7 +701,7 @@ impl<'engine> EngineExecutor<'engine> { let host_func = ctx .as_context() .store - .resolve_host_func(host_func.host_func()); + .resolve_trampoline(host_func.trampoline()); cache.reset_default_memory_bytes(); let host_func = host_func.clone(); self.stack diff --git a/crates/wasmi/src/engine/stack/mod.rs b/crates/wasmi/src/engine/stack/mod.rs index 52f0f73fff..9c6a8bdb91 100644 --- a/crates/wasmi/src/engine/stack/mod.rs +++ b/crates/wasmi/src/engine/stack/mod.rs @@ -12,7 +12,7 @@ use super::{ }; use crate::{ core::UntypedValue, - func::{HostFuncEntity, WasmFuncEntity}, + func::{HostFuncTrampolineEntity, WasmFuncEntity}, AsContext, AsContextMut, Instance, @@ -225,7 +225,7 @@ impl Stack { pub(crate) fn call_host_root( &mut self, ctx: C, - host_func: HostFuncEntity<::UserState>, + host_func: HostFuncTrampolineEntity<::UserState>, func_types: &FuncTypeRegistry, ) -> Result<(), Trap> where @@ -239,7 +239,7 @@ impl Stack { &mut self, ctx: C, caller: &FuncFrame, - host_func: HostFuncEntity<::UserState>, + host_func: HostFuncTrampolineEntity<::UserState>, func_types: &FuncTypeRegistry, ) -> Result<(), Trap> where @@ -259,7 +259,7 @@ impl Stack { fn call_host_impl( &mut self, mut ctx: C, - host_func: HostFuncEntity<::UserState>, + host_func: HostFuncTrampolineEntity<::UserState>, instance: Option<&Instance>, func_types: &FuncTypeRegistry, ) -> Result<(), Trap> 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 d734487a46..f8471deea7 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -47,11 +47,11 @@ impl ArenaIndex for FuncIdx { } } -/// A raw index to a host function entity. +/// A raw index to a host function trampoline entity. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct HostFuncIdx(usize); +pub struct TrampolineIdx(usize); -impl ArenaIndex for HostFuncIdx { +impl ArenaIndex for TrampolineIdx { fn into_usize(self) -> usize { self.0 } @@ -64,16 +64,16 @@ impl ArenaIndex for HostFuncIdx { /// A host function reference. #[derive(Debug, Copy, Clone)] #[repr(transparent)] -pub struct HostFunc(Stored); +pub struct HostFuncTrampoline(Stored); -impl HostFunc { +impl HostFuncTrampoline { /// Creates a new host function reference. - pub(super) fn from_inner(stored: Stored) -> Self { + pub(super) fn from_inner(stored: Stored) -> Self { Self(stored) } /// Returns the underlying stored representation. - pub(super) fn as_inner(&self) -> &Stored { + pub(super) fn as_inner(&self) -> &Stored { &self.0 } } @@ -84,7 +84,7 @@ pub enum FuncEntity { /// A Wasm function. Wasm(WasmFuncEntity), /// A host function. - Host(TypedHostFunc), + Host(HostFuncEntity), } impl From for FuncEntity { @@ -93,24 +93,24 @@ impl From for FuncEntity { } } -impl From for FuncEntity { - fn from(func: TypedHostFunc) -> Self { +impl From for FuncEntity { + fn from(func: HostFuncEntity) -> Self { Self::Host(func) } } /// A host function reference and its function type. #[derive(Debug, Copy, Clone)] -pub struct TypedHostFunc { +pub struct HostFuncEntity { /// The function type of the host function. ty: DedupFuncType, - /// The host function reference. - func: HostFunc, + /// A reference to the trampoline of the host function. + func: HostFuncTrampoline, } -impl TypedHostFunc { +impl HostFuncEntity { /// Creates a new [`TypedHostFunc`]. - pub fn new(ty: DedupFuncType, func: HostFunc) -> Self { + pub fn new(ty: DedupFuncType, func: HostFuncTrampoline) -> Self { Self { ty, func } } @@ -119,8 +119,8 @@ impl TypedHostFunc { &self.ty } - /// Returns the underlying [`HostFunc`]. - pub fn host_func(&self) -> &HostFunc { + /// Returns the [`HostFuncTrampoline`] of the host function. + pub fn trampoline(&self) -> &HostFuncTrampoline { &self.func } } @@ -173,12 +173,14 @@ impl WasmFuncEntity { } /// A host function instance. -pub struct HostFuncEntity { +pub struct HostFuncTrampolineEntity { + /// The type of the associated host function. ty: DedupFuncType, - trampoline: HostFuncTrampoline, + /// The trampoline of the associated host function. + trampoline: TrampolineEntity, } -impl Clone for HostFuncEntity { +impl Clone for HostFuncTrampolineEntity { fn clone(&self) -> Self { Self { ty: self.ty, @@ -187,14 +189,14 @@ impl Clone for HostFuncEntity { } } -type HostFuncTrampolineFn = +type TrampolineFn = dyn Fn(Caller, FuncParams) -> Result + Send + Sync + 'static; -pub struct HostFuncTrampoline { - closure: Arc>, +pub struct TrampolineEntity { + closure: Arc>, } -impl HostFuncTrampoline { +impl TrampolineEntity { /// Creates a new [`HostFuncTrampoline`] from the given trampoline function. pub fn new(trampoline: F) -> Self where @@ -206,7 +208,7 @@ impl HostFuncTrampoline { } } -impl Clone for HostFuncTrampoline { +impl Clone for TrampolineEntity { fn clone(&self) -> Self { Self { closure: self.closure.clone(), @@ -214,14 +216,14 @@ impl Clone for HostFuncTrampoline { } } -impl Debug for HostFuncEntity { +impl Debug for HostFuncTrampolineEntity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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, @@ -235,7 +237,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 @@ -250,7 +252,7 @@ impl HostFuncEntity { 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 ty = engine.alloc_func_type(signature); @@ -321,13 +323,13 @@ impl Func { func: impl Fn(Caller<'_, T>, &[Value], &mut [Value]) -> Result<(), Trap> + Send + Sync + 'static, ) -> Self { let engine = ctx.as_context().store.engine(); - let host_func = HostFuncEntity::new(engine, ty, func); + let host_func = HostFuncTrampolineEntity::new(engine, ty, func); let ty_dedup = *host_func.ty_dedup(); - let func = ctx.as_context_mut().store.alloc_host_func(host_func); + let func = ctx.as_context_mut().store.alloc_trampoline(host_func); ctx.as_context_mut() .store .inner - .alloc_func(TypedHostFunc::new(ty_dedup, func).into()) + .alloc_func(HostFuncEntity::new(ty_dedup, func).into()) } /// Creates a new host function from the given closure. @@ -336,13 +338,13 @@ impl Func { func: impl IntoFunc, ) -> Self { let engine = ctx.as_context().store.engine(); - let host_func = HostFuncEntity::wrap(engine, func); + let host_func = HostFuncTrampolineEntity::wrap(engine, func); let ty_dedup = *host_func.ty_dedup(); - let func = ctx.as_context_mut().store.alloc_host_func(host_func); + let func = ctx.as_context_mut().store.alloc_trampoline(host_func); ctx.as_context_mut() .store .inner - .alloc_func(TypedHostFunc::new(ty_dedup, func).into()) + .alloc_func(HostFuncEntity::new(ty_dedup, func).into()) } /// Returns the signature of the function. diff --git a/crates/wasmi/src/linker.rs b/crates/wasmi/src/linker.rs index 5edadd28fd..1b5f536124 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 { @@ -350,12 +350,12 @@ 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 { + fn new(engine: &'a Engine, host_func: &'a HostFuncTrampolineEntity) -> Self { Self { engine, host_func } } } diff --git a/crates/wasmi/src/store.rs b/crates/wasmi/src/store.rs index c8169a2f51..7c880c2cda 100644 --- a/crates/wasmi/src/store.rs +++ b/crates/wasmi/src/store.rs @@ -1,7 +1,7 @@ use crate::{ engine::DedupFuncType, externref::{ExternObject, ExternObjectEntity, ExternObjectIdx}, - func::{HostFunc, HostFuncEntity, HostFuncIdx}, + func::{HostFuncTrampoline, HostFuncTrampolineEntity, TrampolineIdx}, memory::DataSegment, DataSegmentEntity, DataSegmentIdx, @@ -77,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 host functions. - host_funcs: Arena>, + /// Stored host function trampolines. + trampolines: Arena>, /// User provided host data owned by the [`Store`]. data: T, } @@ -725,7 +725,7 @@ impl Store { pub fn new(engine: &Engine, data: T) -> Self { Self { inner: StoreInner::new(engine), - host_funcs: Arena::new(), + trampolines: Arena::new(), data, } } @@ -808,10 +808,13 @@ impl Store { .map_err(|_error| FuelError::out_of_fuel()) } - /// Allocates a new [`HostFuncEntity`] and returns a [`Func`] reference to it. - pub(super) fn alloc_host_func(&mut self, func: HostFuncEntity) -> HostFunc { - let idx = self.host_funcs.alloc(func); - HostFunc::from_inner(self.inner.wrap_stored(idx)) + /// Allocates a new [`HostFuncTrampolineEntity`] and returns a [`HostFuncTrampoline`] reference to it. + pub(super) fn alloc_trampoline( + &mut self, + func: HostFuncTrampolineEntity, + ) -> HostFuncTrampoline { + let idx = self.trampolines.alloc(func); + HostFuncTrampoline::from_inner(self.inner.wrap_stored(idx)) } /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`] @@ -833,15 +836,18 @@ impl Store { (self.inner.resolve_memory_mut(memory), &mut self.data) } - /// Returns a shared reference to the associated entity of the host function. + /// Returns a shared reference to the associated entity of the host function trampoline. /// /// # Panics /// - /// - If the [`HostFunc`] does not originate from this [`Store`]. - /// - If the [`HostFunc`] cannot be resolved to its entity. - pub(super) fn resolve_host_func(&self, func: &HostFunc) -> &HostFuncEntity { + /// - If the [`HostFuncTrampoline`] does not originate from this [`Store`]. + /// - If the [`HostFuncTrampoline`] cannot be resolved to its entity. + pub(super) fn resolve_trampoline( + &self, + func: &HostFuncTrampoline, + ) -> &HostFuncTrampolineEntity { let entity_index = self.inner.unwrap_stored(func.as_inner()); - self.host_funcs + self.trampolines .get(entity_index) .unwrap_or_else(|| panic!("failed to resolve stored host function: {entity_index:?}")) } From 13d0f5cbf53685657f11937cb975ff0f9c522846 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 22:55:06 +0100 Subject: [PATCH 10/13] fix internal doc links --- crates/wasmi/src/func/mod.rs | 2 +- crates/wasmi/src/linker.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index f8471deea7..ded3129681 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -109,7 +109,7 @@ pub struct HostFuncEntity { } impl HostFuncEntity { - /// Creates a new [`TypedHostFunc`]. + /// Creates a new [`HostFuncEntity`]. pub fn new(ty: DedupFuncType, func: HostFuncTrampoline) -> Self { Self { ty, func } } diff --git a/crates/wasmi/src/linker.rs b/crates/wasmi/src/linker.rs index 1b5f536124..52ba332ee9 100644 --- a/crates/wasmi/src/linker.rs +++ b/crates/wasmi/src/linker.rs @@ -345,7 +345,7 @@ 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, @@ -354,7 +354,7 @@ pub struct DebugHostFuncEntity<'a, T> { } impl<'a, T> DebugHostFuncEntity<'a, T> { - /// Create a new [`Debug`]-wrapper for the [`HostFuncEntity`]. + /// Create a new [`Debug`]-wrapper for the [`HostFuncTrampolineEntity`]. fn new(engine: &'a Engine, host_func: &'a HostFuncTrampolineEntity) -> Self { Self { engine, host_func } } From 8ee82b854e6d9155b78488c7e0787e01b9702350 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 23:30:39 +0100 Subject: [PATCH 11/13] clean up --- crates/wasmi/src/engine/mod.rs | 12 +--- crates/wasmi/src/engine/stack/mod.rs | 46 +++++++-------- crates/wasmi/src/func/mod.rs | 83 ++++++++++++++++------------ crates/wasmi/src/store.rs | 20 +++---- 4 files changed, 78 insertions(+), 83 deletions(-) diff --git a/crates/wasmi/src/engine/mod.rs b/crates/wasmi/src/engine/mod.rs index f511da7431..466916b320 100644 --- a/crates/wasmi/src/engine/mod.rs +++ b/crates/wasmi/src/engine/mod.rs @@ -604,11 +604,7 @@ impl<'engine> EngineExecutor<'engine> { self.execute_wasm_func(ctx.as_context_mut(), &mut frame, &mut cache)?; } FuncEntity::Host(host_func) => { - let host_func = ctx - .as_context() - .store - .resolve_trampoline(host_func.trampoline()); - let host_func = host_func.clone(); + let host_func = *host_func; self.stack .call_host_root(ctx.as_context_mut(), host_func, &self.res.func_types)?; } @@ -698,12 +694,8 @@ impl<'engine> EngineExecutor<'engine> { *frame = self.stack.call_wasm(frame, wasm_func, &self.res.code_map)?; } FuncEntity::Host(host_func) => { - let host_func = ctx - .as_context() - .store - .resolve_trampoline(host_func.trampoline()); 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 9c6a8bdb91..2dac4bf70a 100644 --- a/crates/wasmi/src/engine/stack/mod.rs +++ b/crates/wasmi/src/engine/stack/mod.rs @@ -12,10 +12,10 @@ use super::{ }; use crate::{ core::UntypedValue, - func::{HostFuncTrampolineEntity, WasmFuncEntity}, + 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: HostFuncTrampolineEntity<::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: HostFuncTrampolineEntity<::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: HostFuncTrampolineEntity<::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/mod.rs b/crates/wasmi/src/func/mod.rs index ded3129681..bc863a8665 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -64,9 +64,9 @@ impl ArenaIndex for TrampolineIdx { /// A host function reference. #[derive(Debug, Copy, Clone)] #[repr(transparent)] -pub struct HostFuncTrampoline(Stored); +pub struct Trampoline(Stored); -impl HostFuncTrampoline { +impl Trampoline { /// Creates a new host function reference. pub(super) fn from_inner(stored: Stored) -> Self { Self(stored) @@ -105,12 +105,12 @@ pub struct HostFuncEntity { /// The function type of the host function. ty: DedupFuncType, /// A reference to the trampoline of the host function. - func: HostFuncTrampoline, + func: Trampoline, } impl HostFuncEntity { /// Creates a new [`HostFuncEntity`]. - pub fn new(ty: DedupFuncType, func: HostFuncTrampoline) -> Self { + pub fn new(ty: DedupFuncType, func: Trampoline) -> Self { Self { ty, func } } @@ -120,7 +120,7 @@ impl HostFuncEntity { } /// Returns the [`HostFuncTrampoline`] of the host function. - pub fn trampoline(&self) -> &HostFuncTrampoline { + pub fn trampoline(&self) -> &Trampoline { &self.func } } @@ -189,33 +189,6 @@ impl Clone for HostFuncTrampolineEntity { } } -type TrampolineFn = - dyn Fn(Caller, FuncParams) -> Result + Send + Sync + 'static; - -pub struct TrampolineEntity { - closure: Arc>, -} - -impl TrampolineEntity { - /// 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 TrampolineEntity { - fn clone(&self) -> Self { - Self { - closure: self.closure.clone(), - } - } -} - impl Debug for HostFuncTrampolineEntity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Debug::fmt(&self.ty, f) @@ -264,6 +237,36 @@ impl HostFuncTrampolineEntity { &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 [`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), + } + } + /// Calls the host function with the given inputs. /// /// The result is written back into the `outputs` buffer. @@ -274,7 +277,15 @@ impl HostFuncTrampolineEntity { 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(), + } } } @@ -325,7 +336,8 @@ impl Func { let engine = ctx.as_context().store.engine(); let host_func = HostFuncTrampolineEntity::new(engine, ty, func); let ty_dedup = *host_func.ty_dedup(); - let func = ctx.as_context_mut().store.alloc_trampoline(host_func); + let trampoline = host_func.trampoline().clone(); + let func = ctx.as_context_mut().store.alloc_trampoline(trampoline); ctx.as_context_mut() .store .inner @@ -340,7 +352,8 @@ impl Func { let engine = ctx.as_context().store.engine(); let host_func = HostFuncTrampolineEntity::wrap(engine, func); let ty_dedup = *host_func.ty_dedup(); - let func = ctx.as_context_mut().store.alloc_trampoline(host_func); + let trampoline = host_func.trampoline().clone(); + let func = ctx.as_context_mut().store.alloc_trampoline(trampoline); ctx.as_context_mut() .store .inner diff --git a/crates/wasmi/src/store.rs b/crates/wasmi/src/store.rs index 7c880c2cda..7cf4b3e18c 100644 --- a/crates/wasmi/src/store.rs +++ b/crates/wasmi/src/store.rs @@ -1,7 +1,7 @@ use crate::{ engine::DedupFuncType, externref::{ExternObject, ExternObjectEntity, ExternObjectIdx}, - func::{HostFuncTrampoline, HostFuncTrampolineEntity, TrampolineIdx}, + func::{Trampoline, TrampolineEntity, TrampolineIdx}, memory::DataSegment, DataSegmentEntity, DataSegmentIdx, @@ -78,7 +78,7 @@ pub struct Store { /// it is used directly by the engine's executor. pub(crate) inner: StoreInner, /// Stored host function trampolines. - trampolines: Arena>, + trampolines: Arena>, /// User provided host data owned by the [`Store`]. data: T, } @@ -809,12 +809,9 @@ impl Store { } /// Allocates a new [`HostFuncTrampolineEntity`] and returns a [`HostFuncTrampoline`] reference to it. - pub(super) fn alloc_trampoline( - &mut self, - func: HostFuncTrampolineEntity, - ) -> HostFuncTrampoline { + pub(super) fn alloc_trampoline(&mut self, func: TrampolineEntity) -> Trampoline { let idx = self.trampolines.alloc(func); - HostFuncTrampoline::from_inner(self.inner.wrap_stored(idx)) + Trampoline::from_inner(self.inner.wrap_stored(idx)) } /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`] @@ -840,12 +837,9 @@ impl Store { /// /// # Panics /// - /// - If the [`HostFuncTrampoline`] does not originate from this [`Store`]. - /// - If the [`HostFuncTrampoline`] cannot be resolved to its entity. - pub(super) fn resolve_trampoline( - &self, - func: &HostFuncTrampoline, - ) -> &HostFuncTrampolineEntity { + /// - 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.trampolines .get(entity_index) From 8bd5e72ba55353ac3c2ab2774d1fcf63557fa6a1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 23:34:59 +0100 Subject: [PATCH 12/13] remove func_types field from StoreInner Func type information is already stored in the funcs field now. --- crates/wasmi/src/engine/executor.rs | 2 +- crates/wasmi/src/instance/mod.rs | 4 +-- crates/wasmi/src/store.rs | 40 ++--------------------------- 3 files changed, 5 insertions(+), 41 deletions(-) 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/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/store.rs b/crates/wasmi/src/store.rs index 7cf4b3e18c..92b45b463a 100644 --- a/crates/wasmi/src/store.rs +++ b/crates/wasmi/src/store.rs @@ -30,7 +30,7 @@ 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. @@ -90,13 +90,6 @@ 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. @@ -234,7 +227,6 @@ impl StoreInner { StoreInner { engine: engine.clone(), store_idx: StoreIdx::new(), - func_types: ComponentVec::new(), funcs: Arena::new(), memories: Arena::new(), tables: Arena::new(), @@ -289,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); @@ -699,11 +666,8 @@ impl StoreInner { /// Allocates a new Wasm or host [`FuncEntity`] and returns a [`Func`] reference to it. pub 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.wrap_stored(idx)); - self.register_func_type(func, &func_type); - func + Func::from_inner(self.wrap_stored(idx)) } /// Returns a shared reference to the associated entity of the Wasm or host function. From 5e16c0508d011f64634df176852e8d656e566a6f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Feb 2023 23:52:20 +0100 Subject: [PATCH 13/13] fix internal doc links --- crates/wasmi/src/func/mod.rs | 6 +++--- crates/wasmi/src/store.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/wasmi/src/func/mod.rs b/crates/wasmi/src/func/mod.rs index bc863a8665..f8b57964df 100644 --- a/crates/wasmi/src/func/mod.rs +++ b/crates/wasmi/src/func/mod.rs @@ -119,7 +119,7 @@ impl HostFuncEntity { &self.ty } - /// Returns the [`HostFuncTrampoline`] of the host function. + /// Returns the [`Trampoline`] of the host function. pub fn trampoline(&self) -> &Trampoline { &self.func } @@ -257,7 +257,7 @@ impl Debug for TrampolineEntity { } impl TrampolineEntity { - /// Creates a new [`HostFuncTrampoline`] from the given trampoline function. + /// Creates a new [`TrampolineEntity`] from the given host function. pub fn new(trampoline: F) -> Self where F: Fn(Caller, FuncParams) -> Result + Send + Sync + 'static, @@ -267,7 +267,7 @@ impl TrampolineEntity { } } - /// 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( diff --git a/crates/wasmi/src/store.rs b/crates/wasmi/src/store.rs index 92b45b463a..6740f1c0fb 100644 --- a/crates/wasmi/src/store.rs +++ b/crates/wasmi/src/store.rs @@ -772,7 +772,7 @@ impl Store { .map_err(|_error| FuelError::out_of_fuel()) } - /// Allocates a new [`HostFuncTrampolineEntity`] and returns a [`HostFuncTrampoline`] reference to it. + /// 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))