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.
This commit is contained in:
Peter Huene
2020-03-26 11:48:06 -07:00
parent 382f68c620
commit fb0762bbd6
3 changed files with 137 additions and 93 deletions

View File

@@ -103,9 +103,18 @@ WASM_API_EXTERN wasm_instance_t* wasmtime_linker_instantiate(
typedef struct wasmtime_caller_t wasmtime_caller_t; 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_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(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); WASM_API_EXTERN own wasm_extern_t* wasmtime_caller_export_get(const wasmtime_caller_t* caller, const wasm_name_t* name);
#undef own #undef own

View File

@@ -221,17 +221,22 @@ pub unsafe extern "C" fn wasmtime_linker_instantiate(
handle_instantiate(linker.instantiate(&(*module).module.borrow()), trap) handle_instantiate(linker.instantiate(&(*module).module.borrow()), trap)
} }
pub type wasmtime_func_callback_t = std::option::Option< pub type wasmtime_func_callback_t = unsafe extern "C" fn(
unsafe extern "C" fn(
caller: *const wasmtime_caller_t, caller: *const wasmtime_caller_t,
args: *const wasm_val_t, args: *const wasm_val_t,
results: *mut wasm_val_t, results: *mut wasm_val_t,
) -> *mut wasm_trap_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)] #[repr(C)]
pub struct wasmtime_caller_t<'a> { pub struct wasmtime_caller_t<'a> {
inner: wasmtime::Caller<'a>, pub inner: wasmtime::Caller<'a>,
} }
#[no_mangle] #[no_mangle]
@@ -240,32 +245,24 @@ pub unsafe extern "C" fn wasmtime_func_new(
ty: *const wasm_functype_t, ty: *const wasm_functype_t,
callback: wasmtime_func_callback_t, callback: wasmtime_func_callback_t,
) -> *mut wasm_func_t { ) -> *mut wasm_func_t {
let store = &(*store).store.borrow(); crate::create_function(store, ty, crate::Callback::Wasmtime(callback))
let ty = (*ty).functype.clone(); }
let func = Func::new(store, ty, move |caller, params, results| {
let params = params #[no_mangle]
.iter() pub unsafe extern "C" fn wasmtime_func_new_with_env(
.map(|p| wasm_val_t::from_val(p)) store: *mut wasm_store_t,
.collect::<Vec<_>>(); ty: *const wasm_functype_t,
let mut out_results = vec![wasm_val_t::default(); results.len()]; callback: wasmtime_func_callback_with_env_t,
let func = callback.expect("wasm_func_callback_t fn"); env: *mut std::ffi::c_void,
let caller = wasmtime_caller_t { inner: caller }; finalizer: Option<unsafe extern "C" fn(arg1: *mut std::ffi::c_void)>,
let out = func(&caller, params.as_ptr(), out_results.as_mut_ptr()); ) -> *mut wasm_func_t {
if !out.is_null() { crate::create_function_with_env(
let trap: Box<wasm_trap_t> = Box::from_raw(out); store,
return Err(trap.trap.borrow().clone()); ty,
} crate::CallbackWithEnv::Wasmtime(callback),
for i in 0..results.len() { env,
results[i] = out_results[i].val(); finalizer,
} )
Ok(())
});
let func = Box::new(wasm_func_t {
ext: wasm_extern_t {
which: ExternHost::Func(HostRef::new(func)),
},
});
Box::into_raw(func)
} }
#[no_mangle] #[no_mangle]

View File

@@ -368,16 +368,14 @@ impl wasm_func_t {
} }
} }
pub type wasm_func_callback_t = std::option::Option< pub type wasm_func_callback_t =
unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_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 = std::option::Option< pub type wasm_func_callback_with_env_t = unsafe extern "C" fn(
unsafe extern "C" fn(
env: *mut std::ffi::c_void, env: *mut std::ffi::c_void,
args: *const wasm_val_t, args: *const wasm_val_t,
results: *mut wasm_val_t, results: *mut wasm_val_t,
) -> *mut wasm_trap_t, ) -> *mut wasm_trap_t;
>;
#[derive(Clone)] #[derive(Clone)]
#[repr(transparent)] #[repr(transparent)]
@@ -622,22 +620,36 @@ impl wasm_val_t {
} }
} }
#[no_mangle] enum Callback {
pub unsafe extern "C" fn wasm_func_new( 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, store: *mut wasm_store_t,
ty: *const wasm_functype_t, ty: *const wasm_functype_t,
callback: wasm_func_callback_t, callback: Callback,
) -> *mut wasm_func_t { ) -> *mut wasm_func_t {
let store = &(*store).store.borrow(); let store = &(*store).store.borrow();
let ty = (*ty).functype.clone(); 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 let params = params
.iter() .iter()
.map(|p| wasm_val_t::from_val(p)) .map(|p| wasm_val_t::from_val(p))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut out_results = vec![wasm_val_t::default(); results.len()]; let mut out_results = vec![wasm_val_t::default(); results.len()];
let func = callback.expect("wasm_func_callback_t fn"); let out = match callback {
let out = func(params.as_ptr(), out_results.as_mut_ptr()); 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() { if !out.is_null() {
let trap: Box<wasm_trap_t> = Box::from_raw(out); let trap: Box<wasm_trap_t> = Box::from_raw(out);
return Err(trap.trap.borrow().clone()); return Err(trap.trap.borrow().clone());
@@ -655,6 +667,74 @@ pub unsafe extern "C" fn wasm_func_new(
Box::into_raw(func) 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<unsafe extern "C" fn(arg1: *mut std::ffi::c_void)>,
) -> *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: FnMut()>(F);
impl<F: FnMut()> Drop for RunOnDrop<F> {
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::<Vec<_>>();
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<wasm_trap_t> = 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] #[no_mangle]
pub unsafe extern "C" fn wasm_func_delete(f: *mut wasm_func_t) { pub unsafe extern "C" fn wasm_func_delete(f: *mut wasm_func_t) {
let _ = Box::from_raw(f); 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, env: *mut std::ffi::c_void,
finalizer: Option<unsafe extern "C" fn(arg1: *mut std::ffi::c_void)>, finalizer: Option<unsafe extern "C" fn(arg1: *mut std::ffi::c_void)>,
) -> *mut wasm_func_t { ) -> *mut wasm_func_t {
let store = &(*store).store.borrow(); create_function_with_env(store, ty, CallbackWithEnv::Wasm(callback), env, finalizer)
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: FnMut()>(F);
impl<F: FnMut()> Drop for RunOnDrop<F> {
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::<Vec<_>>();
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<wasm_trap_t> = 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] #[no_mangle]