From 2ee1e80f3b15f1c266bdfeeb828e5c1aed2919a3 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 17 Feb 2020 15:43:14 +0100 Subject: [PATCH] feat(runtime-core) Allow dynamic signature for polymorphic host functions. This patch adds a new field in `Func`: `signature`. It contains the signature of the host function. For non-polymorphic host functions, the signature is computed from the `Args` and `Rets` implementation parameters at compile-time. For polymorphic host functions though, to be fully dynamic, the signature given to `new_polymorphic` is used in `Func` as the correct signature. --- lib/runtime-core-tests/tests/imports.rs | 2 +- lib/runtime-core/src/typed_func.rs | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/runtime-core-tests/tests/imports.rs b/lib/runtime-core-tests/tests/imports.rs index 42a09d84460..ce3cea2c4a9 100644 --- a/lib/runtime-core-tests/tests/imports.rs +++ b/lib/runtime-core-tests/tests/imports.rs @@ -154,7 +154,7 @@ fn imported_functions_forms(test: &dyn Fn(&Instance)) { Ok(n + 1) }), - "callback_closure_polymorphic" => Func::::new_polymorphic( + "callback_closure_polymorphic" => Func::new_polymorphic( Arc::new(FuncSig::new(vec![Type::I32], vec![Type::I32])), |_, params| -> Vec { match params[0] { diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index eca73f61b86..4abad5a1741 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -189,9 +189,21 @@ where /// Represents a function that can be used by WebAssembly. pub struct Func<'a, Args = (), Rets = (), Inner: Kind = Wasm> { inner: Inner, + + /// The function pointer. func: NonNull, + + /// The function environment. func_env: Option>, + + /// The famous `vm::Ctx`. vmctx: *mut vm::Ctx, + + /// The signature is usually infered from `Args` and `Rets`. In + /// case of polymorphic function, the signature is only known at + /// runtime. + signature: Arc, + _phantom: PhantomData<(&'a (), Args, Rets)>, } @@ -214,6 +226,7 @@ where func, func_env, vmctx, + signature: Arc::new(FuncSig::new(Args::types(), Rets::types())), _phantom: PhantomData, } } @@ -225,7 +238,7 @@ where Rets: WasmTypeList, { /// Creates a new `Func`. - pub fn new(func: F) -> Func<'a, Args, Rets, Host> + pub fn new(func: F) -> Self where Kind: ExternalFunctionKind, F: ExternalFunction, @@ -237,14 +250,17 @@ where func, func_env, vmctx: ptr::null_mut(), + signature: Arc::new(FuncSig::new(Args::types(), Rets::types())), _phantom: PhantomData, } } +} +impl<'a> Func<'a, (), (), Host> { /// Creates a polymorphic function. #[allow(unused_variables)] #[cfg(all(unix, target_arch = "x86_64"))] - pub fn new_polymorphic(signature: Arc, func: F) -> Func<'a, Args, Rets, Host> + pub fn new_polymorphic(signature: Arc, func: F) -> Self where F: Fn(&mut vm::Ctx, &[crate::types::Value]) -> Vec + 'static, { @@ -305,11 +321,13 @@ where let ptr = builder .append_global() .expect("cannot bump-allocate global trampoline memory"); + Func { inner: Host(()), func: ptr.cast::(), func_env: None, vmctx: ptr::null_mut(), + signature, _phantom: PhantomData, } } @@ -751,12 +769,11 @@ where func_env @ Some(_) => Context::ExternalWithEnv(self.vmctx, func_env), None => Context::Internal, }; - let signature = Arc::new(FuncSig::new(Args::types(), Rets::types())); Export::Function { func, ctx, - signature, + signature: self.signature.clone(), } } }