Implement RFC 11: Redesigning Wasmtime's APIs (#2897)
Implement Wasmtime's new API as designed by RFC 11. This is quite a large commit which has had lots of discussion externally, so for more information it's best to read the RFC thread and the PR thread.
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t};
|
||||
use crate::{wasm_instancetype_t, wasm_store_t, wasmtime_error_t};
|
||||
use anyhow::Result;
|
||||
use std::ptr;
|
||||
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_instancetype_t, wasmtime_module_t, CStoreContext, CStoreContextMut,
|
||||
StoreRef,
|
||||
};
|
||||
use std::mem::MaybeUninit;
|
||||
use wasmtime::{Extern, Instance, Trap};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -13,9 +15,10 @@ pub struct wasm_instance_t {
|
||||
wasmtime_c_api_macros::declare_ref!(wasm_instance_t);
|
||||
|
||||
impl wasm_instance_t {
|
||||
pub(crate) fn new(instance: Instance) -> wasm_instance_t {
|
||||
pub(crate) fn new(store: StoreRef, instance: Instance) -> wasm_instance_t {
|
||||
wasm_instance_t {
|
||||
ext: wasm_extern_t {
|
||||
store: store,
|
||||
which: instance.into(),
|
||||
},
|
||||
}
|
||||
@@ -28,8 +31,8 @@ impl wasm_instance_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn instance(&self) -> &Instance {
|
||||
match &self.ext.which {
|
||||
pub(crate) fn instance(&self) -> Instance {
|
||||
match self.ext.which {
|
||||
Extern::Instance(i) => i,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@@ -38,100 +41,30 @@ impl wasm_instance_t {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_instance_new(
|
||||
store: &wasm_store_t,
|
||||
store: &mut wasm_store_t,
|
||||
wasm_module: &wasm_module_t,
|
||||
imports: *const wasm_extern_vec_t,
|
||||
result: Option<&mut *mut wasm_trap_t>,
|
||||
) -> Option<Box<wasm_instance_t>> {
|
||||
let mut instance = ptr::null_mut();
|
||||
let mut trap = ptr::null_mut();
|
||||
let err = _wasmtime_instance_new(
|
||||
store,
|
||||
wasm_module,
|
||||
(*imports).as_slice(),
|
||||
&mut instance,
|
||||
&mut trap,
|
||||
);
|
||||
match err {
|
||||
Some(err) => {
|
||||
assert!(trap.is_null());
|
||||
assert!(instance.is_null());
|
||||
if let Some(result) = result {
|
||||
*result = Box::into_raw(err.to_trap());
|
||||
}
|
||||
None
|
||||
}
|
||||
None => {
|
||||
if instance.is_null() {
|
||||
assert!(!trap.is_null());
|
||||
if let Some(result) = result {
|
||||
*result = trap;
|
||||
} else {
|
||||
drop(Box::from_raw(trap))
|
||||
}
|
||||
None
|
||||
} else {
|
||||
assert!(trap.is_null());
|
||||
Some(Box::from_raw(instance))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_instance_new(
|
||||
store: &wasm_store_t,
|
||||
module: &wasm_module_t,
|
||||
imports: *const wasm_extern_vec_t,
|
||||
instance_ptr: &mut *mut wasm_instance_t,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
_wasmtime_instance_new(store, module, (*imports).as_slice(), instance_ptr, trap_ptr)
|
||||
}
|
||||
|
||||
fn _wasmtime_instance_new(
|
||||
store: &wasm_store_t,
|
||||
module: &wasm_module_t,
|
||||
imports: &[Option<Box<wasm_extern_t>>],
|
||||
instance_ptr: &mut *mut wasm_instance_t,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let store = &store.store;
|
||||
let imports = imports
|
||||
let imports = (*imports)
|
||||
.as_slice()
|
||||
.iter()
|
||||
.filter_map(|import| match import {
|
||||
Some(i) => Some(i.which.clone()),
|
||||
None => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
handle_instantiate(
|
||||
Instance::new(store, module.module(), &imports),
|
||||
instance_ptr,
|
||||
trap_ptr,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn handle_instantiate(
|
||||
instance: Result<Instance>,
|
||||
instance_ptr: &mut *mut wasm_instance_t,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
fn write<T>(ptr: &mut *mut T, val: T) {
|
||||
*ptr = Box::into_raw(Box::new(val))
|
||||
}
|
||||
|
||||
match instance {
|
||||
Ok(instance) => {
|
||||
write(instance_ptr, wasm_instance_t::new(instance));
|
||||
match Instance::new(store.store.context_mut(), wasm_module.module(), &imports) {
|
||||
Ok(instance) => Some(Box::new(wasm_instance_t::new(
|
||||
store.store.clone(),
|
||||
instance,
|
||||
))),
|
||||
Err(e) => {
|
||||
if let Some(ptr) = result {
|
||||
*ptr = Box::into_raw(Box::new(wasm_trap_t::new(e.into())));
|
||||
}
|
||||
None
|
||||
}
|
||||
Err(e) => match e.downcast::<Trap>() {
|
||||
Ok(trap) => {
|
||||
write(trap_ptr, wasm_trap_t::new(trap));
|
||||
None
|
||||
}
|
||||
Err(e) => Some(Box::new(e.into())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,14 +74,19 @@ pub extern "C" fn wasm_instance_as_extern(m: &wasm_instance_t) -> &wasm_extern_t
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) {
|
||||
pub unsafe extern "C" fn wasm_instance_exports(
|
||||
instance: &mut wasm_instance_t,
|
||||
out: &mut wasm_extern_vec_t,
|
||||
) {
|
||||
let store = instance.ext.store.clone();
|
||||
out.set_buffer(
|
||||
instance
|
||||
.instance()
|
||||
.exports()
|
||||
.exports(instance.ext.store.context_mut())
|
||||
.map(|e| {
|
||||
Some(Box::new(wasm_extern_t {
|
||||
which: e.into_extern(),
|
||||
store: store.clone(),
|
||||
}))
|
||||
})
|
||||
.collect(),
|
||||
@@ -156,6 +94,91 @@ pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wa
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_instance_type(f: &wasm_instance_t) -> Box<wasm_instancetype_t> {
|
||||
Box::new(wasm_instancetype_t::new(f.instance().ty()))
|
||||
pub unsafe extern "C" fn wasmtime_instance_new(
|
||||
store: CStoreContextMut<'_>,
|
||||
module: &wasmtime_module_t,
|
||||
imports: *const wasmtime_extern_t,
|
||||
nimports: usize,
|
||||
instance: &mut Instance,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
let imports = crate::slice_from_raw_parts(imports, nimports)
|
||||
.iter()
|
||||
.map(|i| i.to_extern())
|
||||
.collect::<Vec<_>>();
|
||||
handle_instantiate(
|
||||
Instance::new(store, &module.module, &imports),
|
||||
instance,
|
||||
trap_ptr,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_instantiate(
|
||||
instance: anyhow::Result<Instance>,
|
||||
instance_ptr: &mut Instance,
|
||||
trap_ptr: &mut *mut wasm_trap_t,
|
||||
) -> Option<Box<wasmtime_error_t>> {
|
||||
match instance {
|
||||
Ok(i) => {
|
||||
*instance_ptr = i;
|
||||
None
|
||||
}
|
||||
Err(e) => match e.downcast::<Trap>() {
|
||||
Ok(trap) => {
|
||||
*trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(trap)));
|
||||
None
|
||||
}
|
||||
Err(e) => Some(Box::new(e.into())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmtime_instance_type(
|
||||
store: CStoreContext<'_>,
|
||||
instance: &Instance,
|
||||
) -> Box<wasmtime_instancetype_t> {
|
||||
Box::new(wasmtime_instancetype_t::new(instance.ty(store)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_instance_export_get(
|
||||
store: CStoreContextMut<'_>,
|
||||
instance: &Instance,
|
||||
name: *const u8,
|
||||
name_len: usize,
|
||||
item: &mut MaybeUninit<wasmtime_extern_t>,
|
||||
) -> bool {
|
||||
let name = crate::slice_from_raw_parts(name, name_len);
|
||||
let name = match std::str::from_utf8(name) {
|
||||
Ok(name) => name,
|
||||
Err(_) => return false,
|
||||
};
|
||||
match instance.get_export(store, name) {
|
||||
Some(e) => {
|
||||
crate::initialize(item, e.into());
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_instance_export_nth(
|
||||
store: CStoreContextMut<'_>,
|
||||
instance: &Instance,
|
||||
index: usize,
|
||||
name_ptr: &mut *const u8,
|
||||
name_len: &mut usize,
|
||||
item: &mut MaybeUninit<wasmtime_extern_t>,
|
||||
) -> bool {
|
||||
match instance.exports(store).nth(index) {
|
||||
Some(e) => {
|
||||
*name_ptr = e.name().as_ptr();
|
||||
*name_len = e.name().len();
|
||||
crate::initialize(item, e.into_extern().into());
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user