Skip to content

Commit b67acbc

Browse files
committed
Add ErasedFunc for type-erased functions.
1 parent 2020901 commit b67acbc

File tree

2 files changed

+66
-13
lines changed

2 files changed

+66
-13
lines changed

lib/runtime-core-tests/tests/imports.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use wasmer_runtime_core::{
44
error::RuntimeError,
55
imports,
66
memory::Memory,
7-
typed_func::Func,
7+
typed_func::{ErasedFunc, Func},
88
types::{FuncSig, MemoryDescriptor, Type, Value},
99
units::Pages,
1010
vm, Instance,
@@ -154,7 +154,7 @@ fn imported_functions_forms(test: &dyn Fn(&Instance)) {
154154
Ok(n + 1)
155155
}),
156156

157-
"callback_closure_polymorphic" => Func::new_polymorphic(
157+
"callback_closure_polymorphic" => ErasedFunc::new_polymorphic(
158158
Arc::new(FuncSig::new(vec![Type::I32], vec![Type::I32])),
159159
|_, params| -> Vec<Value> {
160160
match params[0] {

lib/runtime-core/src/typed_func.rs

+64-11
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,32 @@ where
190190
}
191191
}
192192

193+
/// Represents a type-erased function provided by either the host or the WebAssembly program.
194+
#[allow(dead_code)]
195+
pub struct ErasedFunc<'a> {
196+
inner: Box<dyn Kind>,
197+
198+
/// The function pointer.
199+
func: NonNull<vm::Func>,
200+
201+
/// The function environment.
202+
func_env: Option<NonNull<vm::FuncEnv>>,
203+
204+
/// The famous `vm::Ctx`.
205+
vmctx: *mut vm::Ctx,
206+
207+
/// The runtime signature of this function.
208+
///
209+
/// When converted from a `Func`, this is determined by the static `Args` and `Rets` type parameters.
210+
/// otherwise the signature is dynamically assigned during `ErasedFunc` creation, usually when creating
211+
/// a polymorphic host function.
212+
signature: Arc<FuncSig>,
213+
214+
_phantom: PhantomData<&'a ()>,
215+
}
216+
217+
unsafe impl<'a> Send for ErasedFunc<'a> {}
218+
193219
/// Represents a function that can be used by WebAssembly.
194220
pub struct Func<'a, Args = (), Rets = (), Inner: Kind = Wasm> {
195221
inner: Inner,
@@ -203,17 +229,30 @@ pub struct Func<'a, Args = (), Rets = (), Inner: Kind = Wasm> {
203229
/// The famous `vm::Ctx`.
204230
vmctx: *mut vm::Ctx,
205231

206-
/// The signature is usually infered from `Args` and `Rets`. In
207-
/// case of polymorphic function, the signature is only known at
208-
/// runtime.
209-
signature: Arc<FuncSig>,
210-
211232
_phantom: PhantomData<(&'a (), Args, Rets)>,
212233
}
213234

214235
unsafe impl<'a, Args, Rets> Send for Func<'a, Args, Rets, Wasm> {}
215236
unsafe impl<'a, Args, Rets> Send for Func<'a, Args, Rets, Host> {}
216237

238+
impl<'a, Args, Rets, Inner> From<Func<'a, Args, Rets, Inner>> for ErasedFunc<'a>
239+
where
240+
Args: WasmTypeList,
241+
Rets: WasmTypeList,
242+
Inner: Kind + 'static,
243+
{
244+
fn from(that: Func<'a, Args, Rets, Inner>) -> ErasedFunc<'a> {
245+
ErasedFunc {
246+
inner: Box::new(that.inner),
247+
func: that.func,
248+
func_env: that.func_env,
249+
vmctx: that.vmctx,
250+
signature: Arc::new(FuncSig::new(Args::types(), Rets::types())),
251+
_phantom: PhantomData,
252+
}
253+
}
254+
}
255+
217256
impl<'a, Args, Rets> Func<'a, Args, Rets, Wasm>
218257
where
219258
Args: WasmTypeList,
@@ -230,7 +269,6 @@ where
230269
func,
231270
func_env,
232271
vmctx,
233-
signature: Arc::new(FuncSig::new(Args::types(), Rets::types())),
234272
_phantom: PhantomData,
235273
}
236274
}
@@ -254,13 +292,12 @@ where
254292
func,
255293
func_env,
256294
vmctx: ptr::null_mut(),
257-
signature: Arc::new(FuncSig::new(Args::types(), Rets::types())),
258295
_phantom: PhantomData,
259296
}
260297
}
261298
}
262299

263-
impl<'a> Func<'a, (), (), Host> {
300+
impl<'a> ErasedFunc<'a> {
264301
/// Creates a polymorphic function.
265302
#[allow(unused_variables)]
266303
#[cfg(all(unix, target_arch = "x86_64"))]
@@ -326,8 +363,8 @@ impl<'a> Func<'a, (), (), Host> {
326363
.append_global()
327364
.expect("cannot bump-allocate global trampoline memory");
328365

329-
Func {
330-
inner: Host(()),
366+
ErasedFunc {
367+
inner: Box::new(Host(())),
331368
func: ptr.cast::<vm::Func>(),
332369
func_env: None,
333370
vmctx: ptr::null_mut(),
@@ -765,6 +802,22 @@ impl_traits!([C] S24, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T
765802
impl_traits!([C] S25, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
766803
impl_traits!([C] S26, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
767804

805+
impl<'a> IsExport for ErasedFunc<'a> {
806+
fn to_export(&self) -> Export {
807+
let func = unsafe { FuncPointer::new(self.func.as_ptr()) };
808+
let ctx = match self.func_env {
809+
func_env @ Some(_) => Context::ExternalWithEnv(self.vmctx, func_env),
810+
None => Context::Internal,
811+
};
812+
813+
Export::Function {
814+
func,
815+
ctx,
816+
signature: self.signature.clone(),
817+
}
818+
}
819+
}
820+
768821
impl<'a, Args, Rets, Inner> IsExport for Func<'a, Args, Rets, Inner>
769822
where
770823
Args: WasmTypeList,
@@ -781,7 +834,7 @@ where
781834
Export::Function {
782835
func,
783836
ctx,
784-
signature: self.signature.clone(),
837+
signature: Arc::new(FuncSig::new(Args::types(), Rets::types())),
785838
}
786839
}
787840
}

0 commit comments

Comments
 (0)