From bad0329fbb33265bdcaed7ba37cbdac4845e99f3 Mon Sep 17 00:00:00 2001 From: Tyler Rockwood Date: Tue, 3 Oct 2023 12:51:07 -0500 Subject: [PATCH] c-api: Support InstancePre (#7140) * c-api: Support InstancePre Signed-off-by: Tyler Rockwood * c-api: Consolidate all the instance_pre functionality Signed-off-by: Tyler Rockwood * c-api: Add async instantiate support to pre instances Signed-off-by: Tyler Rockwood * c-api: Add star to comment for doxygen prtest:full Signed-off-by: Tyler Rockwood --------- Signed-off-by: Tyler Rockwood --- crates/c-api/include/wasmtime/async.h | 26 +++++++++++++- crates/c-api/include/wasmtime/instance.h | 45 ++++++++++++++++++++++++ crates/c-api/include/wasmtime/linker.h | 18 ++++++++++ crates/c-api/src/async.rs | 36 +++++++++++++++++-- crates/c-api/src/instance.rs | 24 +++++++++++-- crates/c-api/src/linker.rs | 15 +++++++- 6 files changed, 158 insertions(+), 6 deletions(-) diff --git a/crates/c-api/include/wasmtime/async.h b/crates/c-api/include/wasmtime/async.h index 0c92bf8ec31e..dbe4312dc118 100644 --- a/crates/c-api/include/wasmtime/async.h +++ b/crates/c-api/include/wasmtime/async.h @@ -256,7 +256,31 @@ WASM_API_EXTERN wasmtime_call_future_t *wasmtime_linker_instantiate_async( const wasmtime_module_t *module, wasmtime_instance_t *instance, wasm_trap_t** trap_ret, - wasmtime_error_t** wasmtime_error_t); + wasmtime_error_t** error_ret); + +/** + * \brief Instantiates instance within the given store. + * + * This will also run the function's startup function, if there is one. + * + * For more information on async instantiation see #wasmtime_linker_instantiate_async. + * + * \param instance_pre the pre-initialized instance + * \param store the store in which to create the instance + * \param instance where to store the returned instance + * \param trap_ret where to store the returned trap + * \param error_ret where to store the returned trap + * + * The `trap_ret` and `error_ret` pointers may *not* be `NULL` and the returned memory is owned by the caller. + * + * All arguments to this function must outlive the returned future and be unmodified until the future is deleted. + */ +WASM_API_EXTERN wasmtime_call_future_t *wasmtime_instance_pre_instantiate_async( + const wasmtime_instance_pre_t* instance_pre, + wasmtime_context_t *store, + wasmtime_instance_t *instance, + wasm_trap_t** trap_ret, + wasmtime_error_t** error_ret); #ifdef __cplusplus } // extern "C" diff --git a/crates/c-api/include/wasmtime/instance.h b/crates/c-api/include/wasmtime/instance.h index 544661f9d8fe..72f398ec9cff 100644 --- a/crates/c-api/include/wasmtime/instance.h +++ b/crates/c-api/include/wasmtime/instance.h @@ -121,6 +121,51 @@ WASM_API_EXTERN bool wasmtime_instance_export_nth( wasmtime_extern_t *item ); +/** + * \brief A #wasmtime_instance_t, pre-instantiation, that is ready to be instantiated. + * + * Must be deleted using #wasmtime_instance_pre_delete. + * + * For more information see the Rust documentation: + * https://docs.wasmtime.dev/api/wasmtime/struct.InstancePre.html + */ +typedef struct wasmtime_instance_pre wasmtime_instance_pre_t; + +/** + * \brief Delete a previously created wasmtime_instance_pre_t. + */ +WASM_API_EXTERN void +wasmtime_instance_pre_delete(wasmtime_instance_pre_t *instance); + +/** + * \brief Instantiates instance within the given store. + * + * This will also run the function's startup function, if there is one. + * + * For more information on instantiation see #wasmtime_instance_new. + * + * \param instance_pre the pre-initialized instance + * \param store the store in which to create the instance + * \param instance where to store the returned instance + * \param trap_ptr where to store the returned trap + * + * \return One of three things can happen as a result of this function. First + * the module could be successfully instantiated and returned through + * `instance`, meaning the return value and `trap` are both set to `NULL`. + * Second the start function may trap, meaning the return value and `instance` + * are set to `NULL` and `trap` describes the trap that happens. Finally + * instantiation may fail for another reason, in which case an error is returned + * and `trap` and `instance` are set to `NULL`. + * + * This function does not take ownership of any of its arguments, and all return + * values are owned by the caller. + */ +WASM_API_EXTERN wasmtime_error_t* wasmtime_instance_pre_instantiate( + const wasmtime_instance_pre_t* instance_pre, + wasmtime_store_t *store, + wasmtime_instance_t* instance, + wasm_trap_t **trap_ptr); + #ifdef __cplusplus } // extern "C" #endif diff --git a/crates/c-api/include/wasmtime/linker.h b/crates/c-api/include/wasmtime/linker.h index 453ef73d64ea..3215efe9ff6c 100644 --- a/crates/c-api/include/wasmtime/linker.h +++ b/crates/c-api/include/wasmtime/linker.h @@ -292,6 +292,24 @@ WASM_API_EXTERN bool wasmtime_linker_get( wasmtime_extern_t *item ); +/** + * \brief Preform all the checks for instantiating `module` with the linker, + * except that instantiation doesn't actually finish. + * + * \param linker the linker used to instantiate the provided module. + * \param module the module that is being instantiated. + * \param instance_pre the returned instance_pre, if successful. + * + * \return An error or `NULL` if successful. + * + * For more information see the Rust documentation at: + * https://docs.wasmtime.dev/api/wasmtime/struct.Linker.html#method.instantiate_pre + */ +WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_instantiate_pre( + const wasmtime_linker_t *linker, + const wasmtime_module_t *module, + wasmtime_instance_t **instance_pre); + #ifdef __cplusplus } // extern "C" #endif diff --git a/crates/c-api/src/async.rs b/crates/c-api/src/async.rs index 99702cf26402..23572db32e22 100644 --- a/crates/c-api/src/async.rs +++ b/crates/c-api/src/async.rs @@ -9,8 +9,8 @@ use wasmtime::{AsContextMut, Caller, Func, Instance, Result, Trap, Val}; use crate::{ bad_utf8, handle_result, to_str, translate_args, wasm_config_t, wasm_functype_t, wasm_trap_t, - wasmtime_caller_t, wasmtime_error_t, wasmtime_linker_t, wasmtime_module_t, wasmtime_val_t, - wasmtime_val_union, CStoreContextMut, WASMTIME_I32, + wasmtime_caller_t, wasmtime_error_t, wasmtime_instance_pre_t, wasmtime_linker_t, + wasmtime_module_t, wasmtime_val_t, wasmtime_val_union, CStoreContextMut, WASMTIME_I32, }; #[no_mangle] @@ -303,3 +303,35 @@ pub extern "C" fn wasmtime_linker_instantiate_async<'a>( )); Box::new(crate::wasmtime_call_future_t { underlying: fut }) } + +async fn do_instance_pre_instantiate_async( + instance_pre: &wasmtime_instance_pre_t, + store: CStoreContextMut<'_>, + instance_ptr: &mut Instance, + trap_ret: &mut *mut wasm_trap_t, + err_ret: &mut *mut wasmtime_error_t, +) { + let result = instance_pre.underlying.instantiate_async(store).await; + match result { + Ok(instance) => *instance_ptr = instance, + Err(err) => handle_call_error(err, trap_ret, err_ret), + } +} + +#[no_mangle] +pub extern "C" fn wasmtime_instance_pre_instantiate_async<'a>( + instance_pre: &'a wasmtime_instance_pre_t, + store: CStoreContextMut<'a>, + instance_ptr: &'a mut Instance, + trap_ret: &'a mut *mut wasm_trap_t, + err_ret: &'a mut *mut wasmtime_error_t, +) -> Box> { + let fut = Box::pin(do_instance_pre_instantiate_async( + instance_pre, + store, + instance_ptr, + trap_ret, + err_ret, + )); + Box::new(crate::wasmtime_call_future_t { underlying: fut }) +} diff --git a/crates/c-api/src/instance.rs b/crates/c-api/src/instance.rs index 13fb96a36914..b8ae5bc82341 100644 --- a/crates/c-api/src/instance.rs +++ b/crates/c-api/src/instance.rs @@ -1,9 +1,9 @@ use crate::{ wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_store_t, wasm_trap_t, wasmtime_error_t, - wasmtime_extern_t, wasmtime_module_t, CStoreContextMut, StoreRef, + wasmtime_extern_t, wasmtime_module_t, CStoreContextMut, StoreData, StoreRef, }; use std::mem::MaybeUninit; -use wasmtime::{Instance, Trap}; +use wasmtime::{Instance, InstancePre, Trap}; #[derive(Clone)] pub struct wasm_instance_t { @@ -150,3 +150,23 @@ pub unsafe extern "C" fn wasmtime_instance_export_nth( None => false, } } + +#[repr(transparent)] +pub struct wasmtime_instance_pre_t { + pub(crate) underlying: InstancePre, +} + +#[no_mangle] +pub unsafe extern "C" fn wasmtime_instance_pre_delete(_instance_pre: Box) { +} + +#[no_mangle] +pub unsafe extern "C" fn wasmtime_instance_pre_instantiate( + instance_pre: &wasmtime_instance_pre_t, + store: CStoreContextMut<'_>, + instance_ptr: &mut Instance, + trap_ptr: &mut *mut wasm_trap_t, +) -> Option> { + let result = instance_pre.underlying.instantiate(store); + handle_instantiate(result, instance_ptr, trap_ptr) +} diff --git a/crates/c-api/src/linker.rs b/crates/c-api/src/linker.rs index bf9cf3af4591..7cf9391d8f8a 100644 --- a/crates/c-api/src/linker.rs +++ b/crates/c-api/src/linker.rs @@ -1,6 +1,6 @@ use crate::{ bad_utf8, handle_result, wasm_engine_t, wasm_functype_t, wasm_trap_t, wasmtime_error_t, - wasmtime_extern_t, wasmtime_module_t, CStoreContext, CStoreContextMut, + wasmtime_extern_t, wasmtime_instance_pre_t, wasmtime_module_t, CStoreContext, CStoreContextMut, }; use std::ffi::c_void; use std::mem::MaybeUninit; @@ -138,6 +138,19 @@ pub extern "C" fn wasmtime_linker_instantiate( super::instance::handle_instantiate(result, instance_ptr, trap_ptr) } +#[no_mangle] +pub unsafe extern "C" fn wasmtime_linker_instantiate_pre( + linker: &wasmtime_linker_t, + module: &wasmtime_module_t, + instance_ptr: &mut *mut wasmtime_instance_pre_t, +) -> Option> { + let linker = &linker.linker; + handle_result(linker.instantiate_pre(&module.module), |i| { + let instance_pre = Box::new(wasmtime_instance_pre_t { underlying: i }); + *instance_ptr = Box::into_raw(instance_pre) + }) +} + #[no_mangle] pub unsafe extern "C" fn wasmtime_linker_module( linker: &mut wasmtime_linker_t,