Skip to content

Commit 059c3d7

Browse files
authored
Improve host call performance (#1506)
* try to drop T:'static from wasmi::Store * turn RestorePrunedWrapper into v-table This resolves T:'static issues with call_host_func but unfortunately not with store_inner_and_resource_limiter getter. * add Copy for RestorePrunedWrapper * use &self in RestorePrunedWrapper methods * add more explicit lifetimes to PrunedStore::store_inner_and_resource_limiter_ref * remove commented out code * use infered lifetimes in store_inner_and_resource_limiter_ref * remove unnecesary for<'a> * add some #[inline] annotations * remove non-static typeid impl
1 parent 94cabd5 commit 059c3d7

File tree

2 files changed

+86
-65
lines changed

2 files changed

+86
-65
lines changed

crates/wasmi/src/store/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use self::pruned::RestorePrunedWrapper;
66
pub use self::{
77
context::{AsContext, AsContextMut, StoreContext, StoreContextMut},
88
inner::{StoreInner, Stored},
9-
pruned::{PrunedStore, TypedStore},
9+
pruned::PrunedStore,
1010
};
1111
use crate::{
1212
collections::arena::Arena,

crates/wasmi/src/store/pruned.rs

Lines changed: 85 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use super::{CallHooks, FuncInOut, HostFuncEntity, ResourceLimiterRef, StoreInner};
22
use crate::{core::hint, CallHook, Error, Instance, Store};
3-
use alloc::sync::Arc;
43
use core::{
54
any::{type_name, TypeId},
65
fmt::{self, Debug},
@@ -15,25 +14,70 @@ use crate::Engine;
1514
/// This wrapper exists to provide a `Debug` impl so that `#[derive(Debug)]`
1615
/// works for [`Store`].
1716
#[allow(clippy::type_complexity)]
18-
#[derive(Clone)]
19-
pub struct RestorePrunedWrapper(Arc<dyn Send + Sync + Fn(&mut PrunedStore) -> &mut dyn TypedStore>);
17+
#[derive(Copy, Clone)]
18+
pub struct RestorePrunedWrapper {
19+
/// Calls the given [`HostFuncEntity`] with the `params` and `results` on `instance`.
20+
///
21+
/// # Errors
22+
///
23+
/// If the called host function returned an error.
24+
call_host_func: fn(
25+
/* store: */ &mut PrunedStore,
26+
/* func: */ &HostFuncEntity,
27+
/* instance: */ Option<&Instance>,
28+
/* params_results:*/ FuncInOut,
29+
/* call_hooks: */ CallHooks,
30+
) -> Result<(), Error>,
31+
/// Returns an exclusive reference to [`StoreInner`] and a [`ResourceLimiterRef`].
32+
store_inner_and_resource_limiter_ref:
33+
fn(&mut PrunedStore) -> (&mut StoreInner, ResourceLimiterRef<'_>),
34+
}
2035
impl RestorePrunedWrapper {
2136
pub fn new<T: 'static>() -> Self {
22-
Self(Arc::new(|pruned| -> &mut dyn TypedStore {
23-
let Ok(store) = PrunedStore::restore::<T>(pruned) else {
24-
panic!(
25-
"failed to convert `PrunedStore` back into `Store<{}>`",
26-
type_name::<T>(),
27-
);
28-
};
29-
store
30-
}))
37+
Self {
38+
call_host_func: |pruned: &mut PrunedStore,
39+
func: &HostFuncEntity,
40+
instance: Option<&Instance>,
41+
params_results: FuncInOut,
42+
call_hooks: CallHooks|
43+
-> Result<(), Error> {
44+
let store: &mut Store<T> = pruned.restore_or_panic();
45+
if matches!(call_hooks, CallHooks::Call) {
46+
store.invoke_call_hook(CallHook::CallingHost)?;
47+
}
48+
store.call_host_func(func, instance, params_results)?;
49+
if matches!(call_hooks, CallHooks::Call) {
50+
store.invoke_call_hook(CallHook::ReturningFromHost)?;
51+
}
52+
Ok(())
53+
},
54+
store_inner_and_resource_limiter_ref: |pruned: &mut PrunedStore| {
55+
pruned
56+
.restore_or_panic::<T>()
57+
.store_inner_and_resource_limiter_ref()
58+
},
59+
}
60+
}
61+
}
62+
impl RestorePrunedWrapper {
63+
#[inline]
64+
fn call_host_func(
65+
&self,
66+
pruned: &mut PrunedStore,
67+
func: &HostFuncEntity,
68+
instance: Option<&Instance>,
69+
params_results: FuncInOut,
70+
call_hooks: CallHooks,
71+
) -> Result<(), Error> {
72+
(self.call_host_func)(pruned, func, instance, params_results, call_hooks)
3173
}
3274

33-
/// Restores the [`PrunedStore`] and returns a reference to it via [`TypedStore`].
3475
#[inline]
35-
fn restore<'a>(&self, pruned: &'a mut PrunedStore) -> &'a mut dyn TypedStore {
36-
(self.0)(pruned)
76+
fn store_inner_and_resource_limiter_ref<'a>(
77+
&self,
78+
pruned: &'a mut PrunedStore,
79+
) -> (&'a mut StoreInner, ResourceLimiterRef<'a>) {
80+
(self.store_inner_and_resource_limiter_ref)(pruned)
3781
}
3882
}
3983
impl Debug for RestorePrunedWrapper {
@@ -94,27 +138,47 @@ impl PrunedStore {
94138
/// # Errors
95139
///
96140
/// If the host function returns an error.
141+
#[inline]
97142
pub fn call_host_func(
98143
&mut self,
99144
func: &HostFuncEntity,
100145
instance: Option<&Instance>,
101146
params_results: FuncInOut,
102147
call_hooks: CallHooks,
103148
) -> Result<(), Error> {
104-
self.typed_store()
105-
.call_host_func(func, instance, params_results, call_hooks)
149+
self.pruned.restore_pruned.clone().call_host_func(
150+
self,
151+
func,
152+
instance,
153+
params_results,
154+
call_hooks,
155+
)
106156
}
107157

108158
/// Returns an exclusive reference to [`StoreInner`] and a [`ResourceLimiterRef`].
159+
#[inline]
109160
pub fn store_inner_and_resource_limiter_ref(
110161
&mut self,
111162
) -> (&mut StoreInner, ResourceLimiterRef) {
112-
self.typed_store().store_inner_and_resource_limiter_ref()
163+
self.pruned
164+
.restore_pruned
165+
.clone()
166+
.store_inner_and_resource_limiter_ref(self)
113167
}
114168

115-
/// Returns the associated [`TypedStore`] of `self`.
116-
fn typed_store(&mut self) -> &mut dyn TypedStore {
117-
self.pruned.restore_pruned.clone().restore(self)
169+
/// Restores `self` to a proper [`Store<T>`] if possible.
170+
///
171+
/// # Panics
172+
///
173+
/// If the `T` of the resulting [`Store<T>`] does not match the given `T`.
174+
fn restore_or_panic<T: 'static>(&mut self) -> &mut Store<T> {
175+
let Ok(store) = self.restore() else {
176+
panic!(
177+
"failed to convert `PrunedStore` back into `Store<{}>`",
178+
type_name::<T>(),
179+
);
180+
};
181+
store
118182
}
119183

120184
/// Restores `self` to a proper [`Store<T>`] if possible.
@@ -145,49 +209,6 @@ impl PrunedStore {
145209
#[derive(Debug)]
146210
pub struct PrunedStoreError;
147211

148-
/// Methods available from [`PrunedStore`] that have been restored dynamically.
149-
pub trait TypedStore {
150-
/// Calls the given [`HostFuncEntity`] with the `params` and `results` on `instance`.
151-
///
152-
/// # Errors
153-
///
154-
/// If the called host function returned an error.
155-
fn call_host_func(
156-
&mut self,
157-
func: &HostFuncEntity,
158-
instance: Option<&Instance>,
159-
params_results: FuncInOut,
160-
call_hooks: CallHooks,
161-
) -> Result<(), Error>;
162-
163-
/// Returns an exclusive reference to [`StoreInner`] and a [`ResourceLimiterRef`].
164-
fn store_inner_and_resource_limiter_ref(&mut self) -> (&mut StoreInner, ResourceLimiterRef);
165-
}
166-
167-
impl<T> TypedStore for Store<T> {
168-
fn call_host_func(
169-
&mut self,
170-
func: &HostFuncEntity,
171-
instance: Option<&Instance>,
172-
params_results: FuncInOut,
173-
call_hooks: CallHooks,
174-
) -> Result<(), Error> {
175-
if matches!(call_hooks, CallHooks::Call) {
176-
<Store<T>>::invoke_call_hook(self, CallHook::CallingHost)?;
177-
}
178-
<Store<T>>::call_host_func(self, func, instance, params_results)?;
179-
if matches!(call_hooks, CallHooks::Call) {
180-
<Store<T>>::invoke_call_hook(self, CallHook::ReturningFromHost)?;
181-
}
182-
Ok(())
183-
}
184-
185-
#[inline]
186-
fn store_inner_and_resource_limiter_ref(&mut self) -> (&mut StoreInner, ResourceLimiterRef) {
187-
<Store<T>>::store_inner_and_resource_limiter_ref(self)
188-
}
189-
}
190-
191212
#[test]
192213
fn pruning_works() {
193214
let engine = Engine::default();

0 commit comments

Comments
 (0)