wasmtime: Rip out incomplete/incorrect externref "host info" support
Better to be loud that we don't support attaching arbitrary host info to `externref`s than to limp along and pretend we do support it. Supporting it properly won't reuse any of this code anyways.
This commit is contained in:
@@ -77,12 +77,13 @@ pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn #get_host_info(a: &#ty) -> *mut std::os::raw::c_void {
|
pub extern fn #get_host_info(a: &#ty) -> *mut std::os::raw::c_void {
|
||||||
crate::r#ref::get_host_info(&a.externref())
|
std::ptr::null_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn #set_host_info(a: &#ty, info: *mut std::os::raw::c_void) {
|
pub extern fn #set_host_info(a: &#ty, info: *mut std::os::raw::c_void) {
|
||||||
crate::r#ref::set_host_info(&a.externref(), info, None)
|
eprintln!("`{}` is not implemented", stringify!(#set_host_info));
|
||||||
|
std::process::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -91,7 +92,8 @@ pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
info: *mut std::os::raw::c_void,
|
info: *mut std::os::raw::c_void,
|
||||||
finalizer: Option<extern "C" fn(*mut std::os::raw::c_void)>,
|
finalizer: Option<extern "C" fn(*mut std::os::raw::c_void)>,
|
||||||
) {
|
) {
|
||||||
crate::r#ref::set_host_info(&a.externref(), info, finalizer)
|
eprintln!("`{}` is not implemented", stringify!(#set_host_info_final));
|
||||||
|
std::process::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::{wasm_name_t, wasm_trap_t};
|
use crate::{wasm_name_t, wasm_trap_t};
|
||||||
use anyhow::{anyhow, Error, Result};
|
use anyhow::{anyhow, Error, Result};
|
||||||
use wasmtime::{Store, Trap};
|
use wasmtime::Trap;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct wasmtime_error_t {
|
pub struct wasmtime_error_t {
|
||||||
@@ -10,8 +10,8 @@ pub struct wasmtime_error_t {
|
|||||||
wasmtime_c_api_macros::declare_own!(wasmtime_error_t);
|
wasmtime_c_api_macros::declare_own!(wasmtime_error_t);
|
||||||
|
|
||||||
impl wasmtime_error_t {
|
impl wasmtime_error_t {
|
||||||
pub(crate) fn to_trap(self, store: &Store) -> Box<wasm_trap_t> {
|
pub(crate) fn to_trap(self) -> Box<wasm_trap_t> {
|
||||||
Box::new(wasm_trap_t::new(store, Trap::from(self.error)))
|
Box::new(wasm_trap_t::new(Trap::from(self.error)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ fn create_function(
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
Box::new(HostRef::new(store, func).into())
|
Box::new(HostRef::new(func).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -183,7 +183,7 @@ pub unsafe extern "C" fn wasm_func_call(
|
|||||||
&mut trap,
|
&mut trap,
|
||||||
);
|
);
|
||||||
match error {
|
match error {
|
||||||
Some(err) => Box::into_raw(err.to_trap(&wasm_func.ext.externref().store().unwrap())),
|
Some(err) => Box::into_raw(err.to_trap()),
|
||||||
None => trap,
|
None => trap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,6 @@ fn _wasmtime_func_call(
|
|||||||
results: &mut [wasm_val_t],
|
results: &mut [wasm_val_t],
|
||||||
trap_ptr: &mut *mut wasm_trap_t,
|
trap_ptr: &mut *mut wasm_trap_t,
|
||||||
) -> Option<Box<wasmtime_error_t>> {
|
) -> Option<Box<wasmtime_error_t>> {
|
||||||
let store = &func.ext.externref().store().unwrap();
|
|
||||||
let func = func.func().borrow();
|
let func = func.func().borrow();
|
||||||
if results.len() != func.result_arity() {
|
if results.len() != func.result_arity() {
|
||||||
return Some(Box::new(anyhow!("wrong number of results provided").into()));
|
return Some(Box::new(anyhow!("wrong number of results provided").into()));
|
||||||
@@ -232,7 +231,7 @@ fn _wasmtime_func_call(
|
|||||||
}
|
}
|
||||||
Ok(Err(trap)) => match trap.downcast::<Trap>() {
|
Ok(Err(trap)) => match trap.downcast::<Trap>() {
|
||||||
Ok(trap) => {
|
Ok(trap) => {
|
||||||
*trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(store, trap)));
|
*trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(trap)));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Err(err) => Some(Box::new(err.into())),
|
Err(err) => Some(Box::new(err.into())),
|
||||||
@@ -245,7 +244,7 @@ fn _wasmtime_func_call(
|
|||||||
} else {
|
} else {
|
||||||
Trap::new("rust panic happened")
|
Trap::new("rust panic happened")
|
||||||
};
|
};
|
||||||
let trap = Box::new(wasm_trap_t::new(store, trap));
|
let trap = Box::new(wasm_trap_t::new(trap));
|
||||||
*trap_ptr = Box::into_raw(trap);
|
*trap_ptr = Box::into_raw(trap);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -279,12 +278,11 @@ pub extern "C" fn wasmtime_caller_export_get(
|
|||||||
) -> Option<Box<wasm_extern_t>> {
|
) -> Option<Box<wasm_extern_t>> {
|
||||||
let name = str::from_utf8(name.as_slice()).ok()?;
|
let name = str::from_utf8(name.as_slice()).ok()?;
|
||||||
let export = caller.caller.get_export(name)?;
|
let export = caller.caller.get_export(name)?;
|
||||||
let store = caller.caller.store();
|
|
||||||
let which = match export {
|
let which = match export {
|
||||||
Extern::Func(f) => ExternHost::Func(HostRef::new(&store, f)),
|
Extern::Func(f) => ExternHost::Func(HostRef::new(f)),
|
||||||
Extern::Global(g) => ExternHost::Global(HostRef::new(&store, g)),
|
Extern::Global(g) => ExternHost::Global(HostRef::new(g)),
|
||||||
Extern::Memory(m) => ExternHost::Memory(HostRef::new(&store, m)),
|
Extern::Memory(m) => ExternHost::Memory(HostRef::new(m)),
|
||||||
Extern::Table(t) => ExternHost::Table(HostRef::new(&store, t)),
|
Extern::Table(t) => ExternHost::Table(HostRef::new(t)),
|
||||||
};
|
};
|
||||||
Some(Box::new(wasm_extern_t { which }))
|
Some(Box::new(wasm_extern_t { which }))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub extern "C" fn wasmtime_global_new(
|
|||||||
handle_result(global, |global| {
|
handle_result(global, |global| {
|
||||||
*ret = Box::into_raw(Box::new(wasm_global_t {
|
*ret = Box::into_raw(Box::new(wasm_global_t {
|
||||||
ext: wasm_extern_t {
|
ext: wasm_extern_t {
|
||||||
which: ExternHost::Global(HostRef::new(&store.store, global)),
|
which: ExternHost::Global(HostRef::new(global)),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::any::Any;
|
|||||||
use std::cell::{self, RefCell};
|
use std::cell::{self, RefCell};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use wasmtime::{ExternRef, Store};
|
use wasmtime::ExternRef;
|
||||||
|
|
||||||
/// Represents a piece of data located in the host environment.
|
/// Represents a piece of data located in the host environment.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -19,9 +19,9 @@ where
|
|||||||
T: 'static + Any,
|
T: 'static + Any,
|
||||||
{
|
{
|
||||||
/// Creates a new `HostRef<T>` from `T`.
|
/// Creates a new `HostRef<T>` from `T`.
|
||||||
pub fn new(store: &Store, item: T) -> HostRef<T> {
|
pub fn new(item: T) -> HostRef<T> {
|
||||||
HostRef {
|
HostRef {
|
||||||
externref: ExternRef::new(store, RefCell::new(item)),
|
externref: ExternRef::new(RefCell::new(item)),
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::{wasm_store_t, wasmtime_error_t, ExternHost};
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use wasmtime::{Extern, Instance, Store, Trap};
|
use wasmtime::{Extern, Instance, Trap};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -17,9 +17,8 @@ wasmtime_c_api_macros::declare_ref!(wasm_instance_t);
|
|||||||
|
|
||||||
impl wasm_instance_t {
|
impl wasm_instance_t {
|
||||||
pub(crate) fn new(instance: Instance) -> wasm_instance_t {
|
pub(crate) fn new(instance: Instance) -> wasm_instance_t {
|
||||||
let store = instance.store().clone();
|
|
||||||
wasm_instance_t {
|
wasm_instance_t {
|
||||||
instance: HostRef::new(&store, instance),
|
instance: HostRef::new(instance),
|
||||||
exports_cache: RefCell::new(None),
|
exports_cache: RefCell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +50,7 @@ pub unsafe extern "C" fn wasm_instance_new(
|
|||||||
assert!(trap.is_null());
|
assert!(trap.is_null());
|
||||||
assert!(instance.is_null());
|
assert!(instance.is_null());
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
*result = Box::into_raw(err.to_trap(&store.store));
|
*result = Box::into_raw(err.to_trap());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -109,7 +108,6 @@ fn _wasmtime_instance_new(
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let module = &module.module.borrow();
|
let module = &module.module.borrow();
|
||||||
handle_instantiate(
|
handle_instantiate(
|
||||||
store,
|
|
||||||
Instance::new(store, module, &imports),
|
Instance::new(store, module, &imports),
|
||||||
instance_ptr,
|
instance_ptr,
|
||||||
trap_ptr,
|
trap_ptr,
|
||||||
@@ -117,7 +115,6 @@ fn _wasmtime_instance_new(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_instantiate(
|
pub fn handle_instantiate(
|
||||||
store: &Store,
|
|
||||||
instance: Result<Instance>,
|
instance: Result<Instance>,
|
||||||
instance_ptr: &mut *mut wasm_instance_t,
|
instance_ptr: &mut *mut wasm_instance_t,
|
||||||
trap_ptr: &mut *mut wasm_trap_t,
|
trap_ptr: &mut *mut wasm_trap_t,
|
||||||
@@ -133,7 +130,7 @@ pub fn handle_instantiate(
|
|||||||
}
|
}
|
||||||
Err(e) => match e.downcast::<Trap>() {
|
Err(e) => match e.downcast::<Trap>() {
|
||||||
Ok(trap) => {
|
Ok(trap) => {
|
||||||
write(trap_ptr, wasm_trap_t::new(store, trap));
|
write(trap_ptr, wasm_trap_t::new(trap));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Err(e) => Some(Box::new(e.into())),
|
Err(e) => Some(Box::new(e.into())),
|
||||||
@@ -149,10 +146,10 @@ pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wa
|
|||||||
instance
|
instance
|
||||||
.exports()
|
.exports()
|
||||||
.map(|e| match e.into_extern() {
|
.map(|e| match e.into_extern() {
|
||||||
Extern::Func(f) => ExternHost::Func(HostRef::new(instance.store(), f)),
|
Extern::Func(f) => ExternHost::Func(HostRef::new(f)),
|
||||||
Extern::Global(f) => ExternHost::Global(HostRef::new(instance.store(), f)),
|
Extern::Global(f) => ExternHost::Global(HostRef::new(f)),
|
||||||
Extern::Memory(f) => ExternHost::Memory(HostRef::new(instance.store(), f)),
|
Extern::Memory(f) => ExternHost::Memory(HostRef::new(f)),
|
||||||
Extern::Table(f) => ExternHost::Table(HostRef::new(instance.store(), f)),
|
Extern::Table(f) => ExternHost::Table(HostRef::new(f)),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ pub extern "C" fn wasmtime_linker_instantiate(
|
|||||||
trap_ptr: &mut *mut wasm_trap_t,
|
trap_ptr: &mut *mut wasm_trap_t,
|
||||||
) -> Option<Box<wasmtime_error_t>> {
|
) -> Option<Box<wasmtime_error_t>> {
|
||||||
let result = linker.linker.instantiate(&module.module.borrow());
|
let result = linker.linker.instantiate(&module.module.borrow());
|
||||||
super::instance::handle_instantiate(linker.linker.store(), result, instance_ptr, trap_ptr)
|
super::instance::handle_instantiate(result, instance_ptr, trap_ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -117,7 +117,7 @@ pub extern "C" fn wasmtime_linker_get_default(
|
|||||||
Err(_) => return bad_utf8(),
|
Err(_) => return bad_utf8(),
|
||||||
};
|
};
|
||||||
handle_result(linker.get_default(name), |f| {
|
handle_result(linker.get_default(name), |f| {
|
||||||
*func = Box::into_raw(Box::new(HostRef::new(linker.store(), f).into()))
|
*func = Box::into_raw(Box::new(HostRef::new(f).into()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,12 +138,11 @@ pub extern "C" fn wasmtime_linker_get_one_by_name(
|
|||||||
Err(_) => return bad_utf8(),
|
Err(_) => return bad_utf8(),
|
||||||
};
|
};
|
||||||
handle_result(linker.get_one_by_name(module, name), |item| {
|
handle_result(linker.get_one_by_name(module, name), |item| {
|
||||||
let store = linker.store();
|
|
||||||
let which = match item {
|
let which = match item {
|
||||||
Extern::Func(f) => ExternHost::Func(HostRef::new(&store, f)),
|
Extern::Func(f) => ExternHost::Func(HostRef::new(f)),
|
||||||
Extern::Global(g) => ExternHost::Global(HostRef::new(&store, g)),
|
Extern::Global(g) => ExternHost::Global(HostRef::new(g)),
|
||||||
Extern::Memory(m) => ExternHost::Memory(HostRef::new(&store, m)),
|
Extern::Memory(m) => ExternHost::Memory(HostRef::new(m)),
|
||||||
Extern::Table(t) => ExternHost::Table(HostRef::new(&store, t)),
|
Extern::Table(t) => ExternHost::Table(HostRef::new(t)),
|
||||||
};
|
};
|
||||||
*item_ptr = Box::into_raw(Box::new(wasm_extern_t { which }))
|
*item_ptr = Box::into_raw(Box::new(wasm_extern_t { which }))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub extern "C" fn wasm_memory_new(
|
|||||||
store: &wasm_store_t,
|
store: &wasm_store_t,
|
||||||
mt: &wasm_memorytype_t,
|
mt: &wasm_memorytype_t,
|
||||||
) -> Box<wasm_memory_t> {
|
) -> Box<wasm_memory_t> {
|
||||||
let memory = HostRef::new(&store.store, Memory::new(&store.store, mt.ty().ty.clone()));
|
let memory = HostRef::new(Memory::new(&store.store, mt.ty().ty.clone()));
|
||||||
Box::new(wasm_memory_t {
|
Box::new(wasm_memory_t {
|
||||||
ext: wasm_extern_t {
|
ext: wasm_extern_t {
|
||||||
which: ExternHost::Memory(memory),
|
which: ExternHost::Memory(memory),
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ pub extern "C" fn wasmtime_module_new(
|
|||||||
.map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty()))
|
.map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let module = Box::new(wasm_module_t {
|
let module = Box::new(wasm_module_t {
|
||||||
module: HostRef::new(store, module),
|
module: HostRef::new(module),
|
||||||
imports,
|
imports,
|
||||||
exports,
|
exports,
|
||||||
});
|
});
|
||||||
@@ -130,7 +130,7 @@ pub extern "C" fn wasm_module_obtain(
|
|||||||
.map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty()))
|
.map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
Some(Box::new(wasm_module_t {
|
Some(Box::new(wasm_module_t {
|
||||||
module: HostRef::new(&store.store, module),
|
module: HostRef::new(module),
|
||||||
imports,
|
imports,
|
||||||
exports,
|
exports,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::HostInfoState;
|
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use wasmtime::ExternRef;
|
use wasmtime::ExternRef;
|
||||||
|
|
||||||
@@ -24,47 +23,23 @@ pub extern "C" fn wasm_ref_same(a: &wasm_ref_t, b: &wasm_ref_t) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_host_info(r: &ExternRef) -> *mut c_void {
|
#[no_mangle]
|
||||||
let host_info = match r.host_info() {
|
pub extern "C" fn wasm_ref_get_host_info(_ref: &wasm_ref_t) -> *mut c_void {
|
||||||
Some(info) => info,
|
std::ptr::null_mut()
|
||||||
None => return std::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
let host_info = host_info.borrow();
|
|
||||||
match host_info.downcast_ref::<HostInfoState>() {
|
|
||||||
Some(state) => state.info,
|
|
||||||
None => std::ptr::null_mut(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_ref_get_host_info(a: &wasm_ref_t) -> *mut c_void {
|
pub extern "C" fn wasm_ref_set_host_info(_ref: &wasm_ref_t, _info: *mut c_void) {
|
||||||
a.r.as_ref()
|
eprintln!("`wasm_ref_set_host_info` is not implemented");
|
||||||
.map_or(std::ptr::null_mut(), |r| get_host_info(r))
|
std::process::abort();
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn set_host_info(
|
|
||||||
r: &ExternRef,
|
|
||||||
info: *mut c_void,
|
|
||||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
|
||||||
) {
|
|
||||||
let info = if info.is_null() && finalizer.is_none() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(Box::new(crate::HostInfoState { info, finalizer }) as Box<dyn std::any::Any>)
|
|
||||||
};
|
|
||||||
r.set_host_info(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn wasm_ref_set_host_info(a: &wasm_ref_t, info: *mut c_void) {
|
|
||||||
a.r.as_ref().map(|r| set_host_info(r, info, None));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_ref_set_host_info_with_finalizer(
|
pub extern "C" fn wasm_ref_set_host_info_with_finalizer(
|
||||||
a: &wasm_ref_t,
|
_ref: &wasm_ref_t,
|
||||||
info: *mut c_void,
|
_info: *mut c_void,
|
||||||
finalizer: Option<extern "C" fn(*mut c_void)>,
|
_finalizer: Option<extern "C" fn(*mut c_void)>,
|
||||||
) {
|
) {
|
||||||
a.r.as_ref().map(|r| set_host_info(r, info, finalizer));
|
eprintln!("`wasm_ref_set_host_info_with_finalizer` is not implemented");
|
||||||
|
std::process::abort();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ pub extern "C" fn wasm_table_new(
|
|||||||
let table = Table::new(&store.store, tt.ty().ty.clone(), init).ok()?;
|
let table = Table::new(&store.store, tt.ty().ty.clone(), init).ok()?;
|
||||||
Some(Box::new(wasm_table_t {
|
Some(Box::new(wasm_table_t {
|
||||||
ext: wasm_extern_t {
|
ext: wasm_extern_t {
|
||||||
which: ExternHost::Table(HostRef::new(&store.store, table)),
|
which: ExternHost::Table(HostRef::new(table)),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ pub extern "C" fn wasmtime_funcref_table_new(
|
|||||||
|table| {
|
|table| {
|
||||||
*out = Box::into_raw(Box::new(wasm_table_t {
|
*out = Box::into_raw(Box::new(wasm_table_t {
|
||||||
ext: wasm_extern_t {
|
ext: wasm_extern_t {
|
||||||
which: ExternHost::Table(HostRef::new(&store.store, table)),
|
which: ExternHost::Table(HostRef::new(table)),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@@ -100,13 +100,7 @@ pub extern "C" fn wasmtime_funcref_table_get(
|
|||||||
*ptr = match val {
|
*ptr = match val {
|
||||||
// TODO: what do do about creating new `HostRef` handles here?
|
// TODO: what do do about creating new `HostRef` handles here?
|
||||||
Val::FuncRef(None) => ptr::null_mut(),
|
Val::FuncRef(None) => ptr::null_mut(),
|
||||||
Val::FuncRef(Some(f)) => {
|
Val::FuncRef(Some(f)) => Box::into_raw(Box::new(HostRef::new(f).into())),
|
||||||
let store = match t.table().as_ref().store() {
|
|
||||||
None => return false,
|
|
||||||
Some(store) => store,
|
|
||||||
};
|
|
||||||
Box::into_raw(Box::new(HostRef::new(&store, f).into()))
|
|
||||||
}
|
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::host_ref::HostRef;
|
use crate::host_ref::HostRef;
|
||||||
use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t};
|
use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t};
|
||||||
use once_cell::unsync::OnceCell;
|
use once_cell::unsync::OnceCell;
|
||||||
use wasmtime::{Store, Trap};
|
use wasmtime::Trap;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -12,9 +12,9 @@ pub struct wasm_trap_t {
|
|||||||
wasmtime_c_api_macros::declare_ref!(wasm_trap_t);
|
wasmtime_c_api_macros::declare_ref!(wasm_trap_t);
|
||||||
|
|
||||||
impl wasm_trap_t {
|
impl wasm_trap_t {
|
||||||
pub(crate) fn new(store: &Store, trap: Trap) -> wasm_trap_t {
|
pub(crate) fn new(trap: Trap) -> wasm_trap_t {
|
||||||
wasm_trap_t {
|
wasm_trap_t {
|
||||||
trap: HostRef::new(store, trap),
|
trap: HostRef::new(trap),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ pub type wasm_message_t = wasm_name_t;
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_trap_new(
|
pub extern "C" fn wasm_trap_new(
|
||||||
store: &wasm_store_t,
|
_store: &wasm_store_t,
|
||||||
message: &wasm_message_t,
|
message: &wasm_message_t,
|
||||||
) -> Box<wasm_trap_t> {
|
) -> Box<wasm_trap_t> {
|
||||||
let message = message.as_slice();
|
let message = message.as_slice();
|
||||||
@@ -47,7 +47,7 @@ pub extern "C" fn wasm_trap_new(
|
|||||||
}
|
}
|
||||||
let message = String::from_utf8_lossy(&message[..message.len() - 1]);
|
let message = String::from_utf8_lossy(&message[..message.len() - 1]);
|
||||||
Box::new(wasm_trap_t {
|
Box::new(wasm_trap_t {
|
||||||
trap: HostRef::new(&store.store, Trap::new(message)),
|
trap: HostRef::new(Trap::new(message)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ pub unsafe extern "C" fn wasi_instance_new(
|
|||||||
})),
|
})),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
*trap = Box::into_raw(Box::new(wasm_trap_t {
|
*trap = Box::into_raw(Box::new(wasm_trap_t {
|
||||||
trap: HostRef::new(store, Trap::new(e)),
|
trap: HostRef::new(Trap::new(e)),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
None
|
None
|
||||||
@@ -352,14 +352,13 @@ pub extern "C" fn wasi_instance_bind_import<'a>(
|
|||||||
if &export.ty() != import.ty.func()? {
|
if &export.ty() != import.ty.func()? {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let store = export.store();
|
|
||||||
|
|
||||||
let entry = instance
|
let entry = instance
|
||||||
.export_cache
|
.export_cache
|
||||||
.entry(name.to_string())
|
.entry(name.to_string())
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
Box::new(wasm_extern_t {
|
Box::new(wasm_extern_t {
|
||||||
which: ExternHost::Func(HostRef::new(store, export.clone())),
|
which: ExternHost::Func(HostRef::new(export.clone())),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
Some(entry)
|
Some(entry)
|
||||||
|
|||||||
@@ -355,10 +355,9 @@ impl Table {
|
|||||||
Some(unsafe { from_checked_anyfunc(f, &self.instance.store) })
|
Some(unsafe { from_checked_anyfunc(f, &self.instance.store) })
|
||||||
}
|
}
|
||||||
runtime::TableElement::ExternRef(None) => Some(Val::ExternRef(None)),
|
runtime::TableElement::ExternRef(None) => Some(Val::ExternRef(None)),
|
||||||
runtime::TableElement::ExternRef(Some(x)) => Some(Val::ExternRef(Some(ExternRef {
|
runtime::TableElement::ExternRef(Some(x)) => {
|
||||||
inner: x,
|
Some(Val::ExternRef(Some(ExternRef { inner: x })))
|
||||||
store: self.instance.store.weak(),
|
}
|
||||||
}))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
53
crates/wasmtime/src/ref.rs
Normal file → Executable file
53
crates/wasmtime/src/ref.rs
Normal file → Executable file
@@ -1,34 +1,22 @@
|
|||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::fmt;
|
|
||||||
use std::rc::{Rc, Weak};
|
|
||||||
use wasmtime_runtime::VMExternRef;
|
use wasmtime_runtime::VMExternRef;
|
||||||
|
|
||||||
/// Represents an opaque reference to any data within WebAssembly.
|
/// Represents an opaque reference to any data within WebAssembly.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ExternRef {
|
pub struct ExternRef {
|
||||||
pub(crate) inner: VMExternRef,
|
pub(crate) inner: VMExternRef,
|
||||||
pub(crate) store: Weak<crate::runtime::StoreInner>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternRef {
|
impl ExternRef {
|
||||||
/// Creates a new instance of `ExternRef` wrapping the given value.
|
/// Creates a new instance of `ExternRef` wrapping the given value.
|
||||||
pub fn new<T>(store: &crate::Store, value: T) -> ExternRef
|
pub fn new<T>(value: T) -> ExternRef
|
||||||
where
|
where
|
||||||
T: 'static + Any,
|
T: 'static + Any,
|
||||||
{
|
{
|
||||||
let inner = VMExternRef::new(value);
|
let inner = VMExternRef::new(value);
|
||||||
let store = store.weak();
|
ExternRef { inner }
|
||||||
ExternRef { inner, store }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get this reference's store.
|
|
||||||
///
|
|
||||||
/// Returns `None` if this reference outlived its store.
|
|
||||||
pub fn store(&self) -> Option<crate::runtime::Store> {
|
|
||||||
crate::runtime::Store::upgrade(&self.store)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the underlying data for this `ExternRef`.
|
/// Get the underlying data for this `ExternRef`.
|
||||||
@@ -48,39 +36,4 @@ impl ExternRef {
|
|||||||
pub fn ptr_eq(&self, other: &ExternRef) -> bool {
|
pub fn ptr_eq(&self, other: &ExternRef) -> bool {
|
||||||
VMExternRef::eq(&self.inner, &other.inner)
|
VMExternRef::eq(&self.inner, &other.inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the host information for this `externref`, if previously created
|
|
||||||
/// with `set_host_info`.
|
|
||||||
pub fn host_info(&self) -> Option<Rc<RefCell<dyn Any>>> {
|
|
||||||
let store = crate::Store::upgrade(&self.store)?;
|
|
||||||
store.host_info(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the host information for this `externref`, returning the old host
|
|
||||||
/// information if it was previously set.
|
|
||||||
pub fn set_host_info<T>(&self, info: T) -> Option<Rc<RefCell<dyn Any>>>
|
|
||||||
where
|
|
||||||
T: 'static + Any,
|
|
||||||
{
|
|
||||||
let store = crate::Store::upgrade(&self.store)?;
|
|
||||||
store.set_host_info(self, Some(Rc::new(RefCell::new(info))))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove the host information for this `externref`, returning the old host
|
|
||||||
/// information if it was previously set.
|
|
||||||
pub fn remove_host_info(&self) -> Option<Rc<RefCell<dyn Any>>> {
|
|
||||||
let store = crate::Store::upgrade(&self.store)?;
|
|
||||||
store.set_host_info(self, None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for ExternRef {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
let ExternRef { inner, store: _ } = self;
|
|
||||||
let store = self.store();
|
|
||||||
f.debug_struct("ExternRef")
|
|
||||||
.field("inner", &inner)
|
|
||||||
.field("store", &store)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
use crate::externals::MemoryCreator;
|
use crate::externals::MemoryCreator;
|
||||||
use crate::r#ref::ExternRef;
|
|
||||||
use crate::trampoline::{MemoryCreatorProxy, StoreInstanceHandle};
|
use crate::trampoline::{MemoryCreatorProxy, StoreInstanceHandle};
|
||||||
use crate::Module;
|
use crate::Module;
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use std::any::Any;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
@@ -815,7 +812,6 @@ pub(crate) struct StoreInner {
|
|||||||
instances: RefCell<Vec<InstanceHandle>>,
|
instances: RefCell<Vec<InstanceHandle>>,
|
||||||
signal_handler: RefCell<Option<Box<SignalHandler<'static>>>>,
|
signal_handler: RefCell<Option<Box<SignalHandler<'static>>>>,
|
||||||
jit_code_ranges: RefCell<Vec<(usize, usize)>>,
|
jit_code_ranges: RefCell<Vec<(usize, usize)>>,
|
||||||
host_info: RefCell<HashMap<HostInfoKey, Rc<RefCell<dyn Any>>>>,
|
|
||||||
externref_activations_table: Rc<VMExternRefActivationsTable>,
|
externref_activations_table: Rc<VMExternRefActivationsTable>,
|
||||||
stack_map_registry: Rc<StackMapRegistry>,
|
stack_map_registry: Rc<StackMapRegistry>,
|
||||||
}
|
}
|
||||||
@@ -857,7 +853,6 @@ impl Store {
|
|||||||
instances: RefCell::new(Vec::new()),
|
instances: RefCell::new(Vec::new()),
|
||||||
signal_handler: RefCell::new(None),
|
signal_handler: RefCell::new(None),
|
||||||
jit_code_ranges: RefCell::new(Vec::new()),
|
jit_code_ranges: RefCell::new(Vec::new()),
|
||||||
host_info: RefCell::new(HashMap::new()),
|
|
||||||
externref_activations_table: Rc::new(VMExternRefActivationsTable::new()),
|
externref_activations_table: Rc::new(VMExternRefActivationsTable::new()),
|
||||||
stack_map_registry: Rc::new(StackMapRegistry::default()),
|
stack_map_registry: Rc::new(StackMapRegistry::default()),
|
||||||
}),
|
}),
|
||||||
@@ -980,32 +975,6 @@ impl Store {
|
|||||||
Some(Self { inner })
|
Some(Self { inner })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn host_info(&self, externref: &ExternRef) -> Option<Rc<RefCell<dyn Any>>> {
|
|
||||||
debug_assert!(
|
|
||||||
std::rc::Weak::ptr_eq(&self.weak(), &externref.store),
|
|
||||||
"externref must be from this store"
|
|
||||||
);
|
|
||||||
let infos = self.inner.host_info.borrow();
|
|
||||||
infos.get(&HostInfoKey(externref.inner.clone())).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn set_host_info(
|
|
||||||
&self,
|
|
||||||
externref: &ExternRef,
|
|
||||||
info: Option<Rc<RefCell<dyn Any>>>,
|
|
||||||
) -> Option<Rc<RefCell<dyn Any>>> {
|
|
||||||
debug_assert!(
|
|
||||||
std::rc::Weak::ptr_eq(&self.weak(), &externref.store),
|
|
||||||
"externref must be from this store"
|
|
||||||
);
|
|
||||||
let mut infos = self.inner.host_info.borrow_mut();
|
|
||||||
if let Some(info) = info {
|
|
||||||
infos.insert(HostInfoKey(externref.inner.clone()), info)
|
|
||||||
} else {
|
|
||||||
infos.remove(&HostInfoKey(externref.inner.clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn signal_handler(&self) -> std::cell::Ref<'_, Option<Box<SignalHandler<'static>>>> {
|
pub(crate) fn signal_handler(&self) -> std::cell::Ref<'_, Option<Box<SignalHandler<'static>>>> {
|
||||||
self.inner.signal_handler.borrow()
|
self.inner.signal_handler.borrow()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ impl Val {
|
|||||||
} else {
|
} else {
|
||||||
Val::ExternRef(Some(ExternRef {
|
Val::ExternRef(Some(ExternRef {
|
||||||
inner: VMExternRef::clone_from_raw(raw),
|
inner: VMExternRef::clone_from_raw(raw),
|
||||||
store: store.weak(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,15 +179,15 @@ impl Val {
|
|||||||
Val::FuncRef(Some(f)) => Store::same(store, f.store()),
|
Val::FuncRef(Some(f)) => Store::same(store, f.store()),
|
||||||
Val::FuncRef(None) => true,
|
Val::FuncRef(None) => true,
|
||||||
|
|
||||||
// TODO: need to implement this once we actually finalize what
|
// Integers, floats, vectors, and `externref`s have no association
|
||||||
// `externref` will look like and it's actually implemented to pass it
|
// with any particular store, so they're always considered as "yes I
|
||||||
// to compiled wasm as well.
|
// came from that store",
|
||||||
Val::ExternRef(Some(e)) => e.store.ptr_eq(&store.weak()),
|
Val::I32(_)
|
||||||
Val::ExternRef(None) => true,
|
| Val::I64(_)
|
||||||
|
| Val::F32(_)
|
||||||
// Integers have no association with any particular store, so
|
| Val::F64(_)
|
||||||
// they're always considered as "yes I came from that store",
|
| Val::V128(_)
|
||||||
Val::I32(_) | Val::I64(_) | Val::F32(_) | Val::F64(_) | Val::V128(_) => true,
|
| Val::ExternRef(_) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use wast::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Translate from a `script::Value` to a `RuntimeValue`.
|
/// Translate from a `script::Value` to a `RuntimeValue`.
|
||||||
fn runtime_value(store: &Store, v: &wast::Expression<'_>) -> Result<Val> {
|
fn runtime_value(v: &wast::Expression<'_>) -> Result<Val> {
|
||||||
use wast::Instruction::*;
|
use wast::Instruction::*;
|
||||||
|
|
||||||
if v.instrs.len() != 1 {
|
if v.instrs.len() != 1 {
|
||||||
@@ -24,7 +24,7 @@ fn runtime_value(store: &Store, v: &wast::Expression<'_>) -> Result<Val> {
|
|||||||
V128Const(x) => Val::V128(u128::from_le_bytes(x.to_le_bytes())),
|
V128Const(x) => Val::V128(u128::from_le_bytes(x.to_le_bytes())),
|
||||||
RefNull(RefType::Extern) => Val::ExternRef(None),
|
RefNull(RefType::Extern) => Val::ExternRef(None),
|
||||||
RefNull(RefType::Func) => Val::FuncRef(None),
|
RefNull(RefType::Func) => Val::FuncRef(None),
|
||||||
RefExtern(x) => Val::ExternRef(Some(ExternRef::new(store, *x))),
|
RefExtern(x) => Val::ExternRef(Some(ExternRef::new(*x))),
|
||||||
other => bail!("couldn't convert {:?} to a runtime value", other),
|
other => bail!("couldn't convert {:?} to a runtime value", other),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ impl WastContext {
|
|||||||
let values = exec
|
let values = exec
|
||||||
.args
|
.args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| runtime_value(&self.store, v))
|
.map(|v| runtime_value(v))
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
self.invoke(exec.module.map(|i| i.name()), exec.name, &values)
|
self.invoke(exec.module.map(|i| i.name()), exec.name, &values)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ fn smoke_test_gc() -> anyhow::Result<()> {
|
|||||||
let func = instance.get_func("func").unwrap();
|
let func = instance.get_func("func").unwrap();
|
||||||
|
|
||||||
let inner_dropped = Rc::new(Cell::new(false));
|
let inner_dropped = Rc::new(Cell::new(false));
|
||||||
let r = ExternRef::new(&store, SetFlagOnDrop(inner_dropped.clone()));
|
let r = ExternRef::new(SetFlagOnDrop(inner_dropped.clone()));
|
||||||
{
|
{
|
||||||
let args = [Val::I32(5), Val::ExternRef(Some(r.clone()))];
|
let args = [Val::I32(5), Val::ExternRef(Some(r.clone()))];
|
||||||
func.call(&args)?;
|
func.call(&args)?;
|
||||||
@@ -88,7 +88,7 @@ fn wasm_dropping_refs() -> anyhow::Result<()> {
|
|||||||
// NB: 4096 is greater than the initial `VMExternRefActivationsTable`
|
// NB: 4096 is greater than the initial `VMExternRefActivationsTable`
|
||||||
// capacity, so this will trigger at least one GC.
|
// capacity, so this will trigger at least one GC.
|
||||||
for _ in 0..4096 {
|
for _ in 0..4096 {
|
||||||
let r = ExternRef::new(&store, CountDrops(num_refs_dropped.clone()));
|
let r = ExternRef::new(CountDrops(num_refs_dropped.clone()));
|
||||||
let args = [Val::ExternRef(Some(r))];
|
let args = [Val::ExternRef(Some(r))];
|
||||||
drop_ref.call(&args)?;
|
drop_ref.call(&args)?;
|
||||||
}
|
}
|
||||||
@@ -158,13 +158,10 @@ fn many_live_refs() -> anyhow::Result<()> {
|
|||||||
vec![ValType::ExternRef].into_boxed_slice(),
|
vec![ValType::ExternRef].into_boxed_slice(),
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
let store = store.clone();
|
|
||||||
let live_refs = live_refs.clone();
|
let live_refs = live_refs.clone();
|
||||||
move |_caller, _params, results| {
|
move |_caller, _params, results| {
|
||||||
results[0] = Val::ExternRef(Some(ExternRef::new(
|
results[0] =
|
||||||
&store,
|
Val::ExternRef(Some(ExternRef::new(CountLiveRefs::new(live_refs.clone()))));
|
||||||
CountLiveRefs::new(live_refs.clone()),
|
|
||||||
)));
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user