From fb0762bbd6ff54c80d9c5b2e40bffd325b9c98bc Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Thu, 26 Mar 2020 11:48:06 -0700 Subject: [PATCH] Add wasmtime_func_new_with_env. This commit adds the `wasmtime_func_new_with_env` C API function and refactors the implementation to share the implementation between the C API and Wasmtime extension variants. --- crates/c-api/include/wasmtime.h | 9 ++ crates/c-api/src/ext.rs | 65 +++++++------ crates/c-api/src/lib.rs | 156 ++++++++++++++++++++------------ 3 files changed, 137 insertions(+), 93 deletions(-) diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h index a7ed8fcd55..1600b686fc 100644 --- a/crates/c-api/include/wasmtime.h +++ b/crates/c-api/include/wasmtime.h @@ -103,9 +103,18 @@ WASM_API_EXTERN wasm_instance_t* wasmtime_linker_instantiate( typedef struct wasmtime_caller_t wasmtime_caller_t; typedef own wasm_trap_t* (*wasmtime_func_callback_t)(const wasmtime_caller_t* caller, const wasm_val_t args[], wasm_val_t results[]); +typedef own wasm_trap_t* (*wasmtime_func_callback_with_env_t)(const wasmtime_caller_t* caller, void* env, const wasm_val_t args[], wasm_val_t results[]); WASM_API_EXTERN own wasm_func_t* wasmtime_func_new(wasm_store_t*, const wasm_functype_t*, wasmtime_func_callback_t callback); +WASM_API_EXTERN own wasm_func_t* wasmtime_func_new_with_env( + wasm_store_t* store, + const wasm_functype_t* type, + wasmtime_func_callback_with_env_t callback, + void* env, + void (*finalizer)(void*) +); + WASM_API_EXTERN own wasm_extern_t* wasmtime_caller_export_get(const wasmtime_caller_t* caller, const wasm_name_t* name); #undef own diff --git a/crates/c-api/src/ext.rs b/crates/c-api/src/ext.rs index 159b6a1635..dbccc6bc42 100644 --- a/crates/c-api/src/ext.rs +++ b/crates/c-api/src/ext.rs @@ -221,17 +221,22 @@ pub unsafe extern "C" fn wasmtime_linker_instantiate( handle_instantiate(linker.instantiate(&(*module).module.borrow()), trap) } -pub type wasmtime_func_callback_t = std::option::Option< - unsafe extern "C" fn( - caller: *const wasmtime_caller_t, - args: *const wasm_val_t, - results: *mut wasm_val_t, - ) -> *mut wasm_trap_t, ->; +pub type wasmtime_func_callback_t = unsafe extern "C" fn( + caller: *const wasmtime_caller_t, + args: *const wasm_val_t, + results: *mut wasm_val_t, +) -> *mut wasm_trap_t; + +pub type wasmtime_func_callback_with_env_t = unsafe extern "C" fn( + caller: *const wasmtime_caller_t, + env: *mut std::ffi::c_void, + args: *const wasm_val_t, + results: *mut wasm_val_t, +) -> *mut wasm_trap_t; #[repr(C)] pub struct wasmtime_caller_t<'a> { - inner: wasmtime::Caller<'a>, + pub inner: wasmtime::Caller<'a>, } #[no_mangle] @@ -240,32 +245,24 @@ pub unsafe extern "C" fn wasmtime_func_new( ty: *const wasm_functype_t, callback: wasmtime_func_callback_t, ) -> *mut wasm_func_t { - let store = &(*store).store.borrow(); - let ty = (*ty).functype.clone(); - let func = Func::new(store, ty, move |caller, params, results| { - let params = params - .iter() - .map(|p| wasm_val_t::from_val(p)) - .collect::>(); - let mut out_results = vec![wasm_val_t::default(); results.len()]; - let func = callback.expect("wasm_func_callback_t fn"); - let caller = wasmtime_caller_t { inner: caller }; - let out = func(&caller, params.as_ptr(), out_results.as_mut_ptr()); - if !out.is_null() { - let trap: Box = Box::from_raw(out); - return Err(trap.trap.borrow().clone()); - } - for i in 0..results.len() { - results[i] = out_results[i].val(); - } - Ok(()) - }); - let func = Box::new(wasm_func_t { - ext: wasm_extern_t { - which: ExternHost::Func(HostRef::new(func)), - }, - }); - Box::into_raw(func) + crate::create_function(store, ty, crate::Callback::Wasmtime(callback)) +} + +#[no_mangle] +pub unsafe extern "C" fn wasmtime_func_new_with_env( + store: *mut wasm_store_t, + ty: *const wasm_functype_t, + callback: wasmtime_func_callback_with_env_t, + env: *mut std::ffi::c_void, + finalizer: Option, +) -> *mut wasm_func_t { + crate::create_function_with_env( + store, + ty, + crate::CallbackWithEnv::Wasmtime(callback), + env, + finalizer, + ) } #[no_mangle] diff --git a/crates/c-api/src/lib.rs b/crates/c-api/src/lib.rs index e1af9ed205..47be831c4b 100644 --- a/crates/c-api/src/lib.rs +++ b/crates/c-api/src/lib.rs @@ -368,16 +368,14 @@ impl wasm_func_t { } } -pub type wasm_func_callback_t = std::option::Option< - unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t, ->; -pub type wasm_func_callback_with_env_t = std::option::Option< - unsafe extern "C" fn( - env: *mut std::ffi::c_void, - args: *const wasm_val_t, - results: *mut wasm_val_t, - ) -> *mut wasm_trap_t, ->; +pub type wasm_func_callback_t = + unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t; + +pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( + env: *mut std::ffi::c_void, + args: *const wasm_val_t, + results: *mut wasm_val_t, +) -> *mut wasm_trap_t; #[derive(Clone)] #[repr(transparent)] @@ -622,22 +620,36 @@ impl wasm_val_t { } } -#[no_mangle] -pub unsafe extern "C" fn wasm_func_new( +enum Callback { + Wasm(wasm_func_callback_t), + Wasmtime(crate::ext::wasmtime_func_callback_t), +} + +enum CallbackWithEnv { + Wasm(wasm_func_callback_with_env_t), + Wasmtime(crate::ext::wasmtime_func_callback_with_env_t), +} + +unsafe fn create_function( store: *mut wasm_store_t, ty: *const wasm_functype_t, - callback: wasm_func_callback_t, + callback: Callback, ) -> *mut wasm_func_t { let store = &(*store).store.borrow(); let ty = (*ty).functype.clone(); - let func = Func::new(store, ty, move |_, params, results| { + let func = Func::new(store, ty, move |caller, params, results| { let params = params .iter() .map(|p| wasm_val_t::from_val(p)) .collect::>(); let mut out_results = vec![wasm_val_t::default(); results.len()]; - let func = callback.expect("wasm_func_callback_t fn"); - let out = func(params.as_ptr(), out_results.as_mut_ptr()); + let out = match callback { + Callback::Wasm(callback) => callback(params.as_ptr(), out_results.as_mut_ptr()), + Callback::Wasmtime(callback) => { + let caller = crate::ext::wasmtime_caller_t { inner: caller }; + callback(&caller, params.as_ptr(), out_results.as_mut_ptr()) + } + }; if !out.is_null() { let trap: Box = Box::from_raw(out); return Err(trap.trap.borrow().clone()); @@ -655,6 +667,74 @@ pub unsafe extern "C" fn wasm_func_new( Box::into_raw(func) } +unsafe fn create_function_with_env( + store: *mut wasm_store_t, + ty: *const wasm_functype_t, + callback: CallbackWithEnv, + env: *mut std::ffi::c_void, + finalizer: Option, +) -> *mut wasm_func_t { + let store = &(*store).store.borrow(); + let ty = (*ty).functype.clone(); + + // Create a small object which will run the finalizer when it's dropped, and + // then we move this `run_finalizer` object into the closure below (via the + // `drop(&run_finalizer)` statement so it's all dropped when the closure is + // dropped. + struct RunOnDrop(F); + impl Drop for RunOnDrop { + fn drop(&mut self) { + (self.0)(); + } + } + let run_finalizer = RunOnDrop(move || { + if let Some(finalizer) = finalizer { + finalizer(env); + } + }); + let func = Func::new(store, ty, move |caller, params, results| { + drop(&run_finalizer); + let params = params + .iter() + .map(|p| wasm_val_t::from_val(p)) + .collect::>(); + let mut out_results = vec![wasm_val_t::default(); results.len()]; + let out = match callback { + CallbackWithEnv::Wasm(callback) => { + callback(env, params.as_ptr(), out_results.as_mut_ptr()) + } + CallbackWithEnv::Wasmtime(callback) => { + let caller = crate::ext::wasmtime_caller_t { inner: caller }; + callback(&caller, env, params.as_ptr(), out_results.as_mut_ptr()) + } + }; + if !out.is_null() { + let trap: Box = Box::from_raw(out); + return Err(trap.trap.borrow().clone()); + } + for i in 0..results.len() { + results[i] = out_results[i].val(); + } + Ok(()) + }); + + let func = Box::new(wasm_func_t { + ext: wasm_extern_t { + which: ExternHost::Func(HostRef::new(func)), + }, + }); + Box::into_raw(func) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_new( + store: *mut wasm_store_t, + ty: *const wasm_functype_t, + callback: wasm_func_callback_t, +) -> *mut wasm_func_t { + create_function(store, ty, Callback::Wasm(callback)) +} + #[no_mangle] pub unsafe extern "C" fn wasm_func_delete(f: *mut wasm_func_t) { let _ = Box::from_raw(f); @@ -896,49 +976,7 @@ pub unsafe extern "C" fn wasm_func_new_with_env( env: *mut std::ffi::c_void, finalizer: Option, ) -> *mut wasm_func_t { - let store = &(*store).store.borrow(); - let ty = (*ty).functype.clone(); - - // Create a small object which will run the finalizer when it's dropped, and - // then we move this `run_finalizer` object into the closure below (via the - // `drop(&run_finalizer)` statement so it's all dropped when the closure is - // dropped. - struct RunOnDrop(F); - impl Drop for RunOnDrop { - fn drop(&mut self) { - (self.0)(); - } - } - let run_finalizer = RunOnDrop(move || { - if let Some(finalizer) = finalizer { - finalizer(env); - } - }); - let func = Func::new(store, ty, move |_, params, results| { - drop(&run_finalizer); - let params = params - .iter() - .map(|p| wasm_val_t::from_val(p)) - .collect::>(); - let mut out_results = vec![wasm_val_t::default(); results.len()]; - let func = callback.expect("wasm_func_callback_with_env_t fn"); - let out = func(env, params.as_ptr(), out_results.as_mut_ptr()); - if !out.is_null() { - let trap: Box = Box::from_raw(out); - return Err(trap.trap.borrow().clone()); - } - for i in 0..results.len() { - results[i] = out_results[i].val(); - } - Ok(()) - }); - - let func = Box::new(wasm_func_t { - ext: wasm_extern_t { - which: ExternHost::Func(HostRef::new(func)), - }, - }); - Box::into_raw(func) + create_function_with_env(store, ty, CallbackWithEnv::Wasm(callback), env, finalizer) } #[no_mangle]