Remove HostRef from the wasmtime public API (#788)

* Remove `HostRef` from the `wasmtime` public API

This commit removes all remaining usages of `HostRef` in the public API
of the `wasmtime` crate. This involved a number of API decisions such
as:

* None of `Func`, `Global`, `Table`, or `Memory` are wrapped in `HostRef`
* All of `Func`, `Global`, `Table`, and `Memory` implement `Clone` now.
* Methods called `type` are renamed to `ty` to avoid typing `r#type`.
* Methods requiring mutability for external items now no longer require
  mutability. The mutable reference here is sort of a lie anyway since
  the internals are aliased by the underlying module anyway. This
  affects:
  * `Table::set`
  * `Table::grow`
  * `Memory::grow`
  * `Instance::set_signal_handler`
* The `Val::FuncRef` type is now no longer automatically coerced to
  `AnyRef`. This is technically a breaking change which is pretty bad,
  but I'm hoping that we can live with this interim state while we sort
  out the `AnyRef` story in general.
* The implementation of the C API was refactored and updated in a few
  locations to account for these changes:
  * Accessing the exports of an instance are now cached to ensure we
    always hand out the same `HostRef` values.
  * `wasm_*_t` for external values no longer have internal cache,
    instead they all wrap `wasm_external_t` and have an unchecked
    accessor for the underlying variant (since the type is proof that
    it's there). This makes casting back and forth much more trivial.

This is all related to #708 and while there's still more work to be done
in terms of documentation, this is the major bulk of the rest of the
implementation work on #708 I believe.

* More API updates

* Run rustfmt

* Fix a doc test

* More test updates
This commit is contained in:
Alex Crichton
2020-01-10 10:42:14 -06:00
committed by GitHub
parent 068c249439
commit 6571fb8f4f
25 changed files with 435 additions and 489 deletions

View File

@@ -54,7 +54,7 @@ fn main() -> anyhow::Result<()> {
// Invoke `gcd` export // Invoke `gcd` export
let gcd = instance.exports()[gcd_index].func().expect("gcd"); let gcd = instance.exports()[gcd_index].func().expect("gcd");
let result = gcd.borrow().call(&[Val::from(6i32), Val::from(27i32)])?; let result = gcd.call(&[Val::from(6i32), Val::from(27i32)])?;
println!("{:?}", result); println!("{:?}", result);
Ok(()) Ok(())

View File

@@ -41,15 +41,15 @@ fn main() -> Result<()> {
// `HelloCallback` type and its associated implementation of `Callback. // `HelloCallback` type and its associated implementation of `Callback.
println!("Creating callback..."); println!("Creating callback...");
let hello_type = FuncType::new(Box::new([]), Box::new([])); let hello_type = FuncType::new(Box::new([]), Box::new([]));
let hello_func = HostRef::new(Func::new(&store, hello_type, Rc::new(HelloCallback))); let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback));
// Once we've got that all set up we can then move to the instantiation // Once we've got that all set up we can then move to the instantiation
// phase, pairing together a compiled module as well as a set of imports. // phase, pairing together a compiled module as well as a set of imports.
// Note that this is where the wasm `start` function, if any, would run. // Note that this is where the wasm `start` function, if any, would run.
println!("Instantiating module..."); println!("Instantiating module...");
let imports = vec![hello_func.into()]; let imports = vec![hello_func.into()];
let instance = Instance::new(&store, &module, imports.as_slice()) let instance =
.context("> Error instantiating module!")?; Instance::new(&store, &module, &imports).context("> Error instantiating module!")?;
// Next we poke around a bit to extract the `run` function from the module. // Next we poke around a bit to extract the `run` function from the module.
println!("Extracting export..."); println!("Extracting export...");
@@ -59,7 +59,7 @@ fn main() -> Result<()> {
// And last but not least we can call it! // And last but not least we can call it!
println!("Calling export..."); println!("Calling export...");
run_func.borrow().call(&[])?; run_func.call(&[])?;
println!("Done."); println!("Done.");
Ok(()) Ok(())

View File

@@ -3,7 +3,7 @@
use anyhow::{bail, ensure, Context as _, Error}; use anyhow::{bail, ensure, Context as _, Error};
use wasmtime::*; use wasmtime::*;
fn get_export_memory(exports: &[Extern], i: usize) -> Result<HostRef<Memory>, Error> { fn get_export_memory(exports: &[Extern], i: usize) -> Result<Memory, Error> {
if exports.len() <= i { if exports.len() <= i {
bail!("> Error accessing memory export {}!", i); bail!("> Error accessing memory export {}!", i);
} }
@@ -13,7 +13,7 @@ fn get_export_memory(exports: &[Extern], i: usize) -> Result<HostRef<Memory>, Er
.clone()) .clone())
} }
fn get_export_func(exports: &[Extern], i: usize) -> Result<HostRef<Func>, Error> { fn get_export_func(exports: &[Extern], i: usize) -> Result<Func, Error> {
if exports.len() <= i { if exports.len() <= i {
bail!("> Error accessing function export {}!", i); bail!("> Error accessing function export {}!", i);
} }
@@ -33,7 +33,7 @@ macro_rules! check {
macro_rules! check_ok { macro_rules! check_ok {
($func:expr, $($p:expr),*) => { ($func:expr, $($p:expr),*) => {
if let Err(_) = $func.borrow().call(&[$($p.into()),*]) { if let Err(_) = $func.call(&[$($p.into()),*]) {
bail!("> Error on result, expected return"); bail!("> Error on result, expected return");
} }
} }
@@ -41,7 +41,7 @@ macro_rules! check_ok {
macro_rules! check_trap { macro_rules! check_trap {
($func:expr, $($p:expr),*) => { ($func:expr, $($p:expr),*) => {
if let Ok(_) = $func.borrow().call(&[$($p.into()),*]) { if let Ok(_) = $func.call(&[$($p.into()),*]) {
bail!("> Error on result, expected trap"); bail!("> Error on result, expected trap");
} }
} }
@@ -49,7 +49,7 @@ macro_rules! check_trap {
macro_rules! call { macro_rules! call {
($func:expr, $($p:expr),*) => { ($func:expr, $($p:expr),*) => {
match $func.borrow().call(&[$($p.into()),*]) { match $func.call(&[$($p.into()),*]) {
Ok(result) => { Ok(result) => {
let result: i32 = result[0].unwrap_i32(); let result: i32 = result[0].unwrap_i32();
result result
@@ -101,16 +101,13 @@ fn main() -> Result<(), Error> {
let load_func = get_export_func(&exports, 2)?; let load_func = get_export_func(&exports, 2)?;
let store_func = get_export_func(&exports, 3)?; let store_func = get_export_func(&exports, 3)?;
// Try cloning.
check!(memory.clone().ptr_eq(&memory), true);
// Check initial memory. // Check initial memory.
println!("Checking memory..."); println!("Checking memory...");
check!(memory.borrow().size(), 2u32); check!(memory.size(), 2u32);
check!(memory.borrow().data_size(), 0x20000usize); check!(memory.data_size(), 0x20000usize);
check!(unsafe { memory.borrow().data()[0] }, 0); check!(unsafe { memory.data()[0] }, 0);
check!(unsafe { memory.borrow().data()[0x1000] }, 1); check!(unsafe { memory.data()[0x1000] }, 1);
check!(unsafe { memory.borrow().data()[0x1003] }, 4); check!(unsafe { memory.data()[0x1003] }, 4);
check!(call!(size_func,), 2); check!(call!(size_func,), 2);
check!(call!(load_func, 0), 0); check!(call!(load_func, 0), 0);
@@ -122,36 +119,36 @@ fn main() -> Result<(), Error> {
// Mutate memory. // Mutate memory.
println!("Mutating memory..."); println!("Mutating memory...");
unsafe { unsafe {
memory.borrow_mut().data()[0x1003] = 5; memory.data()[0x1003] = 5;
} }
check_ok!(store_func, 0x1002, 6); check_ok!(store_func, 0x1002, 6);
check_trap!(store_func, 0x20000, 0); check_trap!(store_func, 0x20000, 0);
check!(unsafe { memory.borrow().data()[0x1002] }, 6); check!(unsafe { memory.data()[0x1002] }, 6);
check!(unsafe { memory.borrow().data()[0x1003] }, 5); check!(unsafe { memory.data()[0x1003] }, 5);
check!(call!(load_func, 0x1002), 6); check!(call!(load_func, 0x1002), 6);
check!(call!(load_func, 0x1003), 5); check!(call!(load_func, 0x1003), 5);
// Grow memory. // Grow memory.
println!("Growing memory..."); println!("Growing memory...");
check!(memory.borrow_mut().grow(1), true); check!(memory.grow(1), true);
check!(memory.borrow().size(), 3u32); check!(memory.size(), 3u32);
check!(memory.borrow().data_size(), 0x30000usize); check!(memory.data_size(), 0x30000usize);
check!(call!(load_func, 0x20000), 0); check!(call!(load_func, 0x20000), 0);
check_ok!(store_func, 0x20000, 0); check_ok!(store_func, 0x20000, 0);
check_trap!(load_func, 0x30000); check_trap!(load_func, 0x30000);
check_trap!(store_func, 0x30000, 0); check_trap!(store_func, 0x30000, 0);
check!(memory.borrow_mut().grow(1), false); check!(memory.grow(1), false);
check!(memory.borrow_mut().grow(0), true); check!(memory.grow(0), true);
// Create stand-alone memory. // Create stand-alone memory.
// TODO(wasm+): Once Wasm allows multiple memories, turn this into import. // TODO(wasm+): Once Wasm allows multiple memories, turn this into import.
println!("Creating stand-alone memory..."); println!("Creating stand-alone memory...");
let memorytype = MemoryType::new(Limits::new(5, Some(5))); let memorytype = MemoryType::new(Limits::new(5, Some(5)));
let mut memory2 = Memory::new(&store, memorytype); let memory2 = Memory::new(&store, memorytype);
check!(memory2.size(), 5u32); check!(memory2.size(), 5u32);
check!(memory2.grow(1), false); check!(memory2.grow(1), false);
check!(memory2.grow(0), true); check!(memory2.grow(0), true);

View File

@@ -62,7 +62,7 @@ fn main() -> Result<()> {
Box::new([ValType::I32, ValType::I64]), Box::new([ValType::I32, ValType::I64]),
Box::new([ValType::I64, ValType::I32]), Box::new([ValType::I64, ValType::I32]),
); );
let callback_func = HostRef::new(Func::new(&store, callback_type, Rc::new(Callback))); let callback_func = Func::new(&store, callback_type, Rc::new(Callback));
// Instantiate. // Instantiate.
println!("Instantiating module..."); println!("Instantiating module...");
@@ -83,7 +83,6 @@ fn main() -> Result<()> {
println!("Calling export \"g\"..."); println!("Calling export \"g\"...");
let args = vec![Val::I32(1), Val::I64(3)]; let args = vec![Val::I32(1), Val::I64(3)];
let results = g let results = g
.borrow()
.call(&args) .call(&args)
.map_err(|e| format_err!("> Error calling g! {:?}", e))?; .map_err(|e| format_err!("> Error calling g! {:?}", e))?;
@@ -108,7 +107,6 @@ fn main() -> Result<()> {
Val::I64(9), Val::I64(9),
]; ];
let results = round_trip_many let results = round_trip_many
.borrow()
.call(&args) .call(&args)
.map_err(|e| format_err!("> Error calling round_trip_many! {:?}", e))?; .map_err(|e| format_err!("> Error calling round_trip_many! {:?}", e))?;

View File

@@ -12,7 +12,7 @@ use wasmtime_runtime::Export;
/// WebAssembly. /// WebAssembly.
/// # Example /// # Example
/// ``` /// ```
/// use wasmtime::{HostRef, Val}; /// use wasmtime::Val;
/// ///
/// struct TimesTwo; /// struct TimesTwo;
/// ///
@@ -54,9 +54,8 @@ use wasmtime_runtime::Export;
/// ); /// );
/// ///
/// // Build a reference to the "times_two" function that can be used. /// // Build a reference to the "times_two" function that can be used.
/// let times_two_function = HostRef::new( /// let times_two_function =
/// wasmtime::Func::new(&store, times_two_type, std::rc::Rc::new(TimesTwo)) /// wasmtime::Func::new(&store, times_two_type, std::rc::Rc::new(TimesTwo));
/// );
/// ///
/// // Create module instance that imports our function /// // Create module instance that imports our function
/// let instance = wasmtime::Instance::new( /// let instance = wasmtime::Instance::new(
@@ -71,7 +70,6 @@ use wasmtime_runtime::Export;
/// // Borrow and call "run". Returning any error message from Wasm as a string. /// // Borrow and call "run". Returning any error message from Wasm as a string.
/// let original = 5i32; /// let original = 5i32;
/// let results = run_function /// let results = run_function
/// .borrow()
/// .call(&[original.into()]) /// .call(&[original.into()])
/// .map_err(|trap| trap.to_string())?; /// .map_err(|trap| trap.to_string())?;
/// ///

View File

@@ -1,5 +1,5 @@
use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable}; use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable};
use crate::r#ref::{AnyRef, HostRef}; use crate::r#ref::AnyRef;
use crate::runtime::Store; use crate::runtime::Store;
use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export}; use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export};
use crate::trap::Trap; use crate::trap::Trap;
@@ -15,53 +15,53 @@ use wasmtime_runtime::InstanceHandle;
#[derive(Clone)] #[derive(Clone)]
pub enum Extern { pub enum Extern {
Func(HostRef<Func>), Func(Func),
Global(HostRef<Global>), Global(Global),
Table(HostRef<Table>), Table(Table),
Memory(HostRef<Memory>), Memory(Memory),
} }
impl Extern { impl Extern {
pub fn func(&self) -> Option<&HostRef<Func>> { pub fn func(&self) -> Option<&Func> {
match self { match self {
Extern::Func(func) => Some(func), Extern::Func(func) => Some(func),
_ => None, _ => None,
} }
} }
pub fn global(&self) -> Option<&HostRef<Global>> { pub fn global(&self) -> Option<&Global> {
match self { match self {
Extern::Global(global) => Some(global), Extern::Global(global) => Some(global),
_ => None, _ => None,
} }
} }
pub fn table(&self) -> Option<&HostRef<Table>> { pub fn table(&self) -> Option<&Table> {
match self { match self {
Extern::Table(table) => Some(table), Extern::Table(table) => Some(table),
_ => None, _ => None,
} }
} }
pub fn memory(&self) -> Option<&HostRef<Memory>> { pub fn memory(&self) -> Option<&Memory> {
match self { match self {
Extern::Memory(memory) => Some(memory), Extern::Memory(memory) => Some(memory),
_ => None, _ => None,
} }
} }
pub fn r#type(&self) -> ExternType { pub fn ty(&self) -> ExternType {
match self { match self {
Extern::Func(ft) => ExternType::Func(ft.borrow().r#type().clone()), Extern::Func(ft) => ExternType::Func(ft.ty().clone()),
Extern::Memory(ft) => ExternType::Memory(ft.borrow().r#type().clone()), Extern::Memory(ft) => ExternType::Memory(ft.ty().clone()),
Extern::Table(tt) => ExternType::Table(tt.borrow().r#type().clone()), Extern::Table(tt) => ExternType::Table(tt.ty().clone()),
Extern::Global(gt) => ExternType::Global(gt.borrow().r#type().clone()), Extern::Global(gt) => ExternType::Global(gt.ty().clone()),
} }
} }
pub(crate) fn get_wasmtime_export(&self) -> wasmtime_runtime::Export { pub(crate) fn get_wasmtime_export(&self) -> wasmtime_runtime::Export {
match self { match self {
Extern::Func(f) => f.borrow().wasmtime_export().clone(), Extern::Func(f) => f.wasmtime_export().clone(),
Extern::Global(g) => g.borrow().wasmtime_export().clone(), Extern::Global(g) => g.wasmtime_export().clone(),
Extern::Memory(m) => m.borrow().wasmtime_export().clone(), Extern::Memory(m) => m.wasmtime_export().clone(),
Extern::Table(t) => t.borrow().wasmtime_export().clone(), Extern::Table(t) => t.wasmtime_export().clone(),
} }
} }
@@ -71,50 +71,51 @@ impl Extern {
export: wasmtime_runtime::Export, export: wasmtime_runtime::Export,
) -> Extern { ) -> Extern {
match export { match export {
wasmtime_runtime::Export::Function { .. } => Extern::Func(HostRef::new( wasmtime_runtime::Export::Function { .. } => {
Func::from_wasmtime_function(export, store, instance_handle), Extern::Func(Func::from_wasmtime_function(export, store, instance_handle))
)), }
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(HostRef::new( wasmtime_runtime::Export::Memory { .. } => {
Memory::from_wasmtime_memory(export, store, instance_handle), Extern::Memory(Memory::from_wasmtime_memory(export, store, instance_handle))
)), }
wasmtime_runtime::Export::Global { .. } => { wasmtime_runtime::Export::Global { .. } => {
Extern::Global(HostRef::new(Global::from_wasmtime_global(export, store))) Extern::Global(Global::from_wasmtime_global(export, store))
}
wasmtime_runtime::Export::Table { .. } => {
Extern::Table(Table::from_wasmtime_table(export, store, instance_handle))
} }
wasmtime_runtime::Export::Table { .. } => Extern::Table(HostRef::new(
Table::from_wasmtime_table(export, store, instance_handle),
)),
} }
} }
} }
impl From<HostRef<Func>> for Extern { impl From<Func> for Extern {
fn from(r: HostRef<Func>) -> Self { fn from(r: Func) -> Self {
Extern::Func(r) Extern::Func(r)
} }
} }
impl From<HostRef<Global>> for Extern { impl From<Global> for Extern {
fn from(r: HostRef<Global>) -> Self { fn from(r: Global) -> Self {
Extern::Global(r) Extern::Global(r)
} }
} }
impl From<HostRef<Memory>> for Extern { impl From<Memory> for Extern {
fn from(r: HostRef<Memory>) -> Self { fn from(r: Memory) -> Self {
Extern::Memory(r) Extern::Memory(r)
} }
} }
impl From<HostRef<Table>> for Extern { impl From<Table> for Extern {
fn from(r: HostRef<Table>) -> Self { fn from(r: Table) -> Self {
Extern::Table(r) Extern::Table(r)
} }
} }
#[derive(Clone)]
pub struct Func { pub struct Func {
_store: Store, _store: Store,
callable: Rc<dyn WrappedCallable + 'static>, callable: Rc<dyn WrappedCallable + 'static>,
r#type: FuncType, ty: FuncType,
} }
impl Func { impl Func {
@@ -125,26 +126,26 @@ impl Func {
fn from_wrapped( fn from_wrapped(
store: &Store, store: &Store,
r#type: FuncType, ty: FuncType,
callable: Rc<dyn WrappedCallable + 'static>, callable: Rc<dyn WrappedCallable + 'static>,
) -> Func { ) -> Func {
Func { Func {
_store: store.clone(), _store: store.clone(),
callable, callable,
r#type, ty,
} }
} }
pub fn r#type(&self) -> &FuncType { pub fn ty(&self) -> &FuncType {
&self.r#type &self.ty
} }
pub fn param_arity(&self) -> usize { pub fn param_arity(&self) -> usize {
self.r#type.params().len() self.ty.params().len()
} }
pub fn result_arity(&self) -> usize { pub fn result_arity(&self) -> usize {
self.r#type.results().len() self.ty.results().len()
} }
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Trap> { pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Trap> {
@@ -178,32 +179,39 @@ impl fmt::Debug for Func {
} }
} }
#[derive(Clone)]
pub struct Global { pub struct Global {
inner: Rc<GlobalInner>,
}
struct GlobalInner {
_store: Store, _store: Store,
r#type: GlobalType, ty: GlobalType,
wasmtime_export: wasmtime_runtime::Export, wasmtime_export: wasmtime_runtime::Export,
#[allow(dead_code)] #[allow(dead_code)]
wasmtime_state: Option<crate::trampoline::GlobalState>, wasmtime_state: Option<crate::trampoline::GlobalState>,
} }
impl Global { impl Global {
pub fn new(store: &Store, r#type: GlobalType, val: Val) -> Global { pub fn new(store: &Store, ty: GlobalType, val: Val) -> Global {
let (wasmtime_export, wasmtime_state) = let (wasmtime_export, wasmtime_state) =
generate_global_export(&r#type, val).expect("generated global"); generate_global_export(&ty, val).expect("generated global");
Global { Global {
inner: Rc::new(GlobalInner {
_store: store.clone(), _store: store.clone(),
r#type, ty,
wasmtime_export, wasmtime_export,
wasmtime_state: Some(wasmtime_state), wasmtime_state: Some(wasmtime_state),
}),
} }
} }
pub fn r#type(&self) -> &GlobalType { pub fn ty(&self) -> &GlobalType {
&self.r#type &self.inner.ty
} }
fn wasmtime_global_definition(&self) -> *mut wasmtime_runtime::VMGlobalDefinition { fn wasmtime_global_definition(&self) -> *mut wasmtime_runtime::VMGlobalDefinition {
match self.wasmtime_export { match self.inner.wasmtime_export {
wasmtime_runtime::Export::Global { definition, .. } => definition, wasmtime_runtime::Export::Global { definition, .. } => definition,
_ => panic!("global definition not found"), _ => panic!("global definition not found"),
} }
@@ -212,22 +220,22 @@ impl Global {
pub fn get(&self) -> Val { pub fn get(&self) -> Val {
let definition = unsafe { &mut *self.wasmtime_global_definition() }; let definition = unsafe { &mut *self.wasmtime_global_definition() };
unsafe { unsafe {
match self.r#type().content() { match self.ty().content() {
ValType::I32 => Val::from(*definition.as_i32()), ValType::I32 => Val::from(*definition.as_i32()),
ValType::I64 => Val::from(*definition.as_i64()), ValType::I64 => Val::from(*definition.as_i64()),
ValType::F32 => Val::F32(*definition.as_u32()), ValType::F32 => Val::F32(*definition.as_u32()),
ValType::F64 => Val::F64(*definition.as_u64()), ValType::F64 => Val::F64(*definition.as_u64()),
_ => unimplemented!("Global::get for {:?}", self.r#type().content()), _ => unimplemented!("Global::get for {:?}", self.ty().content()),
} }
} }
} }
pub fn set(&mut self, val: Val) { pub fn set(&self, val: Val) {
if val.r#type() != *self.r#type().content() { if val.ty() != *self.ty().content() {
panic!( panic!(
"global of type {:?} cannot be set to {:?}", "global of type {:?} cannot be set to {:?}",
self.r#type().content(), self.ty().content(),
val.r#type() val.ty()
); );
} }
let definition = unsafe { &mut *self.wasmtime_global_definition() }; let definition = unsafe { &mut *self.wasmtime_global_definition() };
@@ -237,13 +245,13 @@ impl Global {
Val::I64(i) => *definition.as_i64_mut() = i, Val::I64(i) => *definition.as_i64_mut() = i,
Val::F32(f) => *definition.as_u32_mut() = f, Val::F32(f) => *definition.as_u32_mut() = f,
Val::F64(f) => *definition.as_u64_mut() = f, Val::F64(f) => *definition.as_u64_mut() = f,
_ => unimplemented!("Global::set for {:?}", val.r#type()), _ => unimplemented!("Global::set for {:?}", val.ty()),
} }
} }
} }
pub(crate) fn wasmtime_export(&self) -> &wasmtime_runtime::Export { pub(crate) fn wasmtime_export(&self) -> &wasmtime_runtime::Export {
&self.wasmtime_export &self.inner.wasmtime_export
} }
pub(crate) fn from_wasmtime_global(export: wasmtime_runtime::Export, store: &Store) -> Global { pub(crate) fn from_wasmtime_global(export: wasmtime_runtime::Export, store: &Store) -> Global {
@@ -254,17 +262,20 @@ impl Global {
}; };
let ty = GlobalType::from_wasmtime_global(&global); let ty = GlobalType::from_wasmtime_global(&global);
Global { Global {
inner: Rc::new(GlobalInner {
_store: store.clone(), _store: store.clone(),
r#type: ty, ty: ty,
wasmtime_export: export, wasmtime_export: export,
wasmtime_state: None, wasmtime_state: None,
}),
} }
} }
} }
#[derive(Clone)]
pub struct Table { pub struct Table {
store: Store, store: Store,
r#type: TableType, ty: TableType,
wasmtime_handle: InstanceHandle, wasmtime_handle: InstanceHandle,
wasmtime_export: wasmtime_runtime::Export, wasmtime_export: wasmtime_runtime::Export,
} }
@@ -299,13 +310,13 @@ fn set_table_item(
} }
impl Table { impl Table {
pub fn new(store: &Store, r#type: TableType, init: Val) -> Table { pub fn new(store: &Store, ty: TableType, init: Val) -> Table {
match r#type.element() { match ty.element() {
ValType::FuncRef => (), ValType::FuncRef => (),
_ => panic!("table is not for funcref"), _ => panic!("table is not for funcref"),
} }
let (mut wasmtime_handle, wasmtime_export) = let (mut wasmtime_handle, wasmtime_export) =
generate_table_export(&r#type).expect("generated table"); generate_table_export(&ty).expect("generated table");
// Initialize entries with the init value. // Initialize entries with the init value.
match wasmtime_export { match wasmtime_export {
@@ -323,14 +334,14 @@ impl Table {
Table { Table {
store: store.clone(), store: store.clone(),
r#type, ty,
wasmtime_handle, wasmtime_handle,
wasmtime_export, wasmtime_export,
} }
} }
pub fn r#type(&self) -> &TableType { pub fn ty(&self) -> &TableType {
&self.r#type &self.ty
} }
fn wasmtime_table_index(&self) -> wasm::DefinedTableIndex { fn wasmtime_table_index(&self) -> wasm::DefinedTableIndex {
@@ -362,9 +373,9 @@ impl Table {
} }
} }
pub fn grow(&mut self, delta: u32, init: Val) -> bool { pub fn grow(&self, delta: u32, init: Val) -> bool {
let index = self.wasmtime_table_index(); let index = self.wasmtime_table_index();
if let Some(len) = self.wasmtime_handle.table_grow(index, delta) { if let Some(len) = self.wasmtime_handle.clone().table_grow(index, delta) {
let mut wasmtime_handle = self.wasmtime_handle.clone(); let mut wasmtime_handle = self.wasmtime_handle.clone();
for i in 0..delta { for i in 0..delta {
let i = len - (delta - i); let i = len - (delta - i);
@@ -395,34 +406,35 @@ impl Table {
let ty = TableType::from_wasmtime_table(&table.table); let ty = TableType::from_wasmtime_table(&table.table);
Table { Table {
store: store.clone(), store: store.clone(),
r#type: ty, ty: ty,
wasmtime_handle: instance_handle, wasmtime_handle: instance_handle,
wasmtime_export: export, wasmtime_export: export,
} }
} }
} }
#[derive(Clone)]
pub struct Memory { pub struct Memory {
_store: Store, _store: Store,
r#type: MemoryType, ty: MemoryType,
wasmtime_handle: InstanceHandle, wasmtime_handle: InstanceHandle,
wasmtime_export: wasmtime_runtime::Export, wasmtime_export: wasmtime_runtime::Export,
} }
impl Memory { impl Memory {
pub fn new(store: &Store, r#type: MemoryType) -> Memory { pub fn new(store: &Store, ty: MemoryType) -> Memory {
let (wasmtime_handle, wasmtime_export) = let (wasmtime_handle, wasmtime_export) =
generate_memory_export(&r#type).expect("generated memory"); generate_memory_export(&ty).expect("generated memory");
Memory { Memory {
_store: store.clone(), _store: store.clone(),
r#type, ty,
wasmtime_handle, wasmtime_handle,
wasmtime_export, wasmtime_export,
} }
} }
pub fn r#type(&self) -> &MemoryType { pub fn ty(&self) -> &MemoryType {
&self.r#type &self.ty
} }
fn wasmtime_memory_definition(&self) -> *mut wasmtime_runtime::VMMemoryDefinition { fn wasmtime_memory_definition(&self) -> *mut wasmtime_runtime::VMMemoryDefinition {
@@ -453,12 +465,15 @@ impl Memory {
(self.data_size() / wasmtime_environ::WASM_PAGE_SIZE as usize) as u32 (self.data_size() / wasmtime_environ::WASM_PAGE_SIZE as usize) as u32
} }
pub fn grow(&mut self, delta: u32) -> bool { pub fn grow(&self, delta: u32) -> bool {
match self.wasmtime_export { match self.wasmtime_export {
wasmtime_runtime::Export::Memory { definition, .. } => { wasmtime_runtime::Export::Memory { definition, .. } => {
let definition = unsafe { &(*definition) }; let definition = unsafe { &(*definition) };
let index = self.wasmtime_handle.memory_index(definition); let index = self.wasmtime_handle.memory_index(definition);
self.wasmtime_handle.memory_grow(index, delta).is_some() self.wasmtime_handle
.clone()
.memory_grow(index, delta)
.is_some()
} }
_ => panic!("memory definition not found"), _ => panic!("memory definition not found"),
} }
@@ -481,7 +496,7 @@ impl Memory {
let ty = MemoryType::from_wasmtime_memory(&memory.memory); let ty = MemoryType::from_wasmtime_memory(&memory.memory);
Memory { Memory {
_store: store.clone(), _store: store.clone(),
r#type: ty, ty: ty,
wasmtime_handle: instance_handle, wasmtime_handle: instance_handle,
wasmtime_export: export, wasmtime_export: export,
} }

View File

@@ -167,29 +167,29 @@ cfg_if::cfg_if! {
impl Instance { impl Instance {
/// The signal handler must be /// The signal handler must be
/// [async-signal-safe](http://man7.org/linux/man-pages/man7/signal-safety.7.html). /// [async-signal-safe](http://man7.org/linux/man-pages/man7/signal-safety.7.html).
pub fn set_signal_handler<H>(&mut self, handler: H) pub fn set_signal_handler<H>(&self, handler: H)
where where
H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool, H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool,
{ {
self.instance_handle.set_signal_handler(handler); self.instance_handle.clone().set_signal_handler(handler);
} }
} }
} else if #[cfg(target_os = "windows")] { } else if #[cfg(target_os = "windows")] {
impl Instance { impl Instance {
pub fn set_signal_handler<H>(&mut self, handler: H) pub fn set_signal_handler<H>(&self, handler: H)
where where
H: 'static + Fn(winapi::um::winnt::EXCEPTION_POINTERS) -> bool, H: 'static + Fn(winapi::um::winnt::EXCEPTION_POINTERS) -> bool,
{ {
self.instance_handle.set_signal_handler(handler); self.instance_handle.clone().set_signal_handler(handler);
} }
} }
} else if #[cfg(target_os = "macos")] { } else if #[cfg(target_os = "macos")] {
impl Instance { impl Instance {
pub fn set_signal_handler<H>(&mut self, handler: H) pub fn set_signal_handler<H>(&self, handler: H)
where where
H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool, H: 'static + Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool,
{ {
self.instance_handle.set_signal_handler(handler); self.instance_handle.clone().set_signal_handler(handler);
} }
} }
} }

View File

@@ -1,5 +1,5 @@
use crate::externals::Func; use crate::externals::Func;
use crate::r#ref::{AnyRef, HostRef}; use crate::r#ref::AnyRef;
use crate::runtime::Store; use crate::runtime::Store;
use crate::types::ValType; use crate::types::ValType;
use std::ptr; use std::ptr;
@@ -34,7 +34,7 @@ pub enum Val {
AnyRef(AnyRef), AnyRef(AnyRef),
/// A first-class reference to a WebAssembly function. /// A first-class reference to a WebAssembly function.
FuncRef(HostRef<Func>), FuncRef(Func),
/// A 128-bit number /// A 128-bit number
V128(u128), V128(u128),
@@ -71,7 +71,7 @@ impl Val {
} }
/// Returns the corresponding [`ValType`] for this `Val`. /// Returns the corresponding [`ValType`] for this `Val`.
pub fn r#type(&self) -> ValType { pub fn ty(&self) -> ValType {
match self { match self {
Val::I32(_) => ValType::I32, Val::I32(_) => ValType::I32,
Val::I64(_) => ValType::I64, Val::I64(_) => ValType::I64,
@@ -111,7 +111,7 @@ impl Val {
(I64(i64) i64 unwrap_i64 *e) (I64(i64) i64 unwrap_i64 *e)
(F32(f32) f32 unwrap_f32 f32::from_bits(*e)) (F32(f32) f32 unwrap_f32 f32::from_bits(*e))
(F64(f64) f64 unwrap_f64 f64::from_bits(*e)) (F64(f64) f64 unwrap_f64 f64::from_bits(*e))
(FuncRef(&HostRef<Func>) funcref unwrap_funcref e) (FuncRef(&Func) funcref unwrap_funcref e)
(V128(u128) v128 unwrap_v128 *e) (V128(u128) v128 unwrap_v128 *e)
} }
@@ -122,7 +122,6 @@ impl Val {
pub fn anyref(&self) -> Option<AnyRef> { pub fn anyref(&self) -> Option<AnyRef> {
match self { match self {
Val::AnyRef(e) => Some(e.clone()), Val::AnyRef(e) => Some(e.clone()),
Val::FuncRef(e) => Some(e.anyref()),
_ => None, _ => None,
} }
} }
@@ -164,21 +163,12 @@ impl From<f64> for Val {
impl From<AnyRef> for Val { impl From<AnyRef> for Val {
fn from(val: AnyRef) -> Val { fn from(val: AnyRef) -> Val {
match &val {
AnyRef::Ref(r) => {
if r.is_ref::<Func>() {
Val::FuncRef(r.get_ref())
} else {
Val::AnyRef(val) Val::AnyRef(val)
} }
}
_ => unimplemented!("AnyRef::Other"),
}
}
} }
impl From<HostRef<Func>> for Val { impl From<Func> for Val {
fn from(val: HostRef<Func>) -> Val { fn from(val: Func) -> Val {
Val::FuncRef(val) Val::FuncRef(val)
} }
} }
@@ -206,7 +196,6 @@ pub(crate) fn into_checked_anyfunc(
vmctx: ptr::null_mut(), vmctx: ptr::null_mut(),
}, },
Val::FuncRef(f) => { Val::FuncRef(f) => {
let f = f.borrow();
let (vmctx, func_ptr, signature) = match f.wasmtime_export() { let (vmctx, func_ptr, signature) = match f.wasmtime_export() {
wasmtime_runtime::Export::Function { wasmtime_runtime::Export::Function {
vmctx, vmctx,
@@ -243,5 +232,5 @@ pub(crate) fn from_checked_anyfunc(
vmctx: item.vmctx, vmctx: item.vmctx,
}; };
let f = Func::from_wasmtime_function(export, store, instance_handle); let f = Func::from_wasmtime_function(export, store, instance_handle);
Val::FuncRef(HostRef::new(f)) Val::FuncRef(f)
} }

View File

@@ -10,6 +10,7 @@ use super::{
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table, HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table,
TableType, Trap, Val, ValType, TableType, Trap, Val, ValType,
}; };
use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::{mem, ptr, slice}; use std::{mem, ptr, slice};
@@ -243,6 +244,12 @@ enum wasm_externtype_t_type_cache {
declare_vec!(wasm_externtype_vec_t, *mut wasm_externtype_t); declare_vec!(wasm_externtype_vec_t, *mut wasm_externtype_t);
pub type wasm_externkind_t = u8; pub type wasm_externkind_t = u8;
const WASM_EXTERN_FUNC: wasm_externkind_t = 0;
const WASM_EXTERN_GLOBAL: wasm_externkind_t = 1;
const WASM_EXTERN_TABLE: wasm_externkind_t = 2;
const WASM_EXTERN_MEMORY: wasm_externkind_t = 3;
#[repr(C)] #[repr(C)]
#[derive(Clone)] #[derive(Clone)]
pub struct wasm_importtype_t { pub struct wasm_importtype_t {
@@ -312,6 +319,7 @@ declare_vec!(wasm_frame_vec_t, *mut wasm_frame_t);
#[derive(Clone)] #[derive(Clone)]
pub struct wasm_instance_t { pub struct wasm_instance_t {
instance: HostRef<Instance>, instance: HostRef<Instance>,
exports_cache: RefCell<Option<Vec<ExternHost>>>,
} }
pub type wasm_message_t = wasm_name_t; pub type wasm_message_t = wasm_name_t;
#[repr(C)] #[repr(C)]
@@ -336,12 +344,22 @@ pub struct wasm_module_t {
pub struct wasm_shared_module_t { pub struct wasm_shared_module_t {
_unused: [u8; 0], _unused: [u8; 0],
} }
#[repr(C)]
#[derive(Clone)] #[derive(Clone)]
#[repr(transparent)]
pub struct wasm_func_t { pub struct wasm_func_t {
func: HostRef<Func>, ext: wasm_extern_t,
ext: Option<Box<wasm_extern_t>>,
} }
impl wasm_func_t {
fn func(&self) -> &HostRef<Func> {
match &self.ext.which {
ExternHost::Func(f) => f,
_ => unsafe { std::hint::unreachable_unchecked() },
}
}
}
pub type wasm_func_callback_t = std::option::Option< 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, unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t,
>; >;
@@ -352,40 +370,67 @@ pub type wasm_func_callback_with_env_t = std::option::Option<
results: *mut wasm_val_t, results: *mut wasm_val_t,
) -> *mut wasm_trap_t, ) -> *mut wasm_trap_t,
>; >;
#[repr(C)]
#[derive(Clone)] #[derive(Clone)]
#[repr(transparent)]
pub struct wasm_global_t { pub struct wasm_global_t {
global: HostRef<Global>, ext: wasm_extern_t,
ext: Option<Box<wasm_extern_t>>,
} }
#[repr(C)]
#[derive(Clone)] impl wasm_global_t {
pub struct wasm_table_t { fn global(&self) -> &HostRef<Global> {
table: HostRef<Table>, match &self.ext.which {
ext: Option<Box<wasm_extern_t>>, ExternHost::Global(g) => g,
} _ => unsafe { std::hint::unreachable_unchecked() },
pub type wasm_table_size_t = u32; }
#[repr(C)] }
#[derive(Clone)]
pub struct wasm_memory_t {
memory: HostRef<Memory>,
ext: Option<Box<wasm_extern_t>>,
}
pub type wasm_memory_pages_t = u32;
#[repr(C)]
#[derive(Clone)]
pub struct wasm_extern_t {
ext: Extern,
cache: wasm_extern_t_type_cache,
} }
#[derive(Clone)] #[derive(Clone)]
enum wasm_extern_t_type_cache { #[repr(transparent)]
Empty, pub struct wasm_table_t {
Func(wasm_func_t), ext: wasm_extern_t,
Global(wasm_global_t), }
Memory(wasm_memory_t),
Table(wasm_table_t), impl wasm_table_t {
fn table(&self) -> &HostRef<Table> {
match &self.ext.which {
ExternHost::Table(t) => t,
_ => unsafe { std::hint::unreachable_unchecked() },
}
}
}
pub type wasm_table_size_t = u32;
#[derive(Clone)]
#[repr(transparent)]
pub struct wasm_memory_t {
ext: wasm_extern_t,
}
impl wasm_memory_t {
fn memory(&self) -> &HostRef<Memory> {
match &self.ext.which {
ExternHost::Memory(m) => m,
_ => unsafe { std::hint::unreachable_unchecked() },
}
}
}
pub type wasm_memory_pages_t = u32;
#[derive(Clone)]
pub struct wasm_extern_t {
which: ExternHost,
}
#[derive(Clone)]
enum ExternHost {
Func(HostRef<Func>),
Global(HostRef<Global>),
Memory(HostRef<Memory>),
Table(HostRef<Table>),
} }
declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t); declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t);
@@ -415,16 +460,9 @@ pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t { pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t {
if let wasm_extern_t_type_cache::Empty = (*e).cache { match &(*e).which {
(*e).cache = wasm_extern_t_type_cache::Func(wasm_func_t { ExternHost::Func(_) => e.cast(),
func: (*e).ext.func().unwrap().clone(), _ => ptr::null_mut(),
ext: None,
});
}
match &mut (*e).cache {
wasm_extern_t_type_cache::Func(f) => f,
_ => panic!("wasm_extern_as_func"),
} }
} }
@@ -435,17 +473,7 @@ pub unsafe extern "C" fn wasm_extern_vec_delete(v: *mut wasm_extern_vec_t) {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t { pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t {
if (*f).ext.is_none() { &mut (*f).ext
(*f).ext = Some(Box::new(wasm_extern_t {
ext: Extern::Func((*f).func.clone()),
cache: wasm_extern_t_type_cache::Empty,
}));
}
match &mut (*f).ext {
Some(e) => e.as_mut(),
_ => panic!("wasm_func_as_extern"),
}
} }
#[no_mangle] #[no_mangle]
@@ -454,7 +482,7 @@ pub unsafe extern "C" fn wasm_func_call(
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 {
let func = (*func).func.borrow(); let func = (*func).func().borrow();
let mut params = Vec::with_capacity(func.param_arity()); let mut params = Vec::with_capacity(func.param_arity());
for i in 0..func.param_arity() { for i in 0..func.param_arity() {
let val = &(*args.add(i)); let val = &(*args.add(i));
@@ -606,8 +634,9 @@ pub unsafe extern "C" fn wasm_func_new(
let ty = (*ty).functype.clone(); let ty = (*ty).functype.clone();
let callback = Rc::new(callback); let callback = Rc::new(callback);
let func = Box::new(wasm_func_t { let func = Box::new(wasm_func_t {
func: HostRef::new(Func::new(store, ty, callback)), ext: wasm_extern_t {
ext: None, which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))),
},
}); });
Box::into_raw(func) Box::into_raw(func)
} }
@@ -660,13 +689,19 @@ pub unsafe extern "C" fn wasm_instance_new(
let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len()); let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len());
for i in 0..(*module).imports.len() { for i in 0..(*module).imports.len() {
let import = *imports.add(i); let import = *imports.add(i);
externs.push((*import).ext.clone()); externs.push(match &(*import).which {
ExternHost::Func(e) => Extern::Func(e.borrow().clone()),
ExternHost::Table(e) => Extern::Table(e.borrow().clone()),
ExternHost::Global(e) => Extern::Global(e.borrow().clone()),
ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()),
});
} }
let module = &(*module).module.borrow(); let module = &(*module).module.borrow();
match Instance::new(store, module, &externs) { match Instance::new(store, module, &externs) {
Ok(instance) => { Ok(instance) => {
let instance = Box::new(wasm_instance_t { let instance = Box::new(wasm_instance_t {
instance: HostRef::new(instance), instance: HostRef::new(instance),
exports_cache: RefCell::new(None),
}); });
if !result.is_null() { if !result.is_null() {
(*result) = ptr::null_mut(); (*result) = ptr::null_mut();
@@ -694,14 +729,23 @@ pub unsafe extern "C" fn wasm_instance_exports(
instance: *const wasm_instance_t, instance: *const wasm_instance_t,
out: *mut wasm_extern_vec_t, out: *mut wasm_extern_vec_t,
) { ) {
let mut cache = (*instance).exports_cache.borrow_mut();
let exports = cache.get_or_insert_with(|| {
let instance = &(*instance).instance.borrow(); let instance = &(*instance).instance.borrow();
let exports = instance.exports(); instance
let mut buffer = Vec::with_capacity(exports.len()); .exports()
for e in exports.iter() { .iter()
let ext = Box::new(wasm_extern_t { .map(|e| match e {
ext: e.clone(), Extern::Func(f) => ExternHost::Func(HostRef::new(f.clone())),
cache: wasm_extern_t_type_cache::Empty, Extern::Global(f) => ExternHost::Global(HostRef::new(f.clone())),
Extern::Memory(f) => ExternHost::Memory(HostRef::new(f.clone())),
Extern::Table(f) => ExternHost::Table(HostRef::new(f.clone())),
})
.collect()
}); });
let mut buffer = Vec::with_capacity(exports.len());
for e in exports {
let ext = Box::new(wasm_extern_t { which: e.clone() });
buffer.push(Box::into_raw(ext)); buffer.push(Box::into_raw(ext));
} }
(*out).set_buffer(buffer); (*out).set_buffer(buffer);
@@ -817,8 +861,9 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
finalizer, finalizer,
}); });
let func = Box::new(wasm_func_t { let func = Box::new(wasm_func_t {
func: HostRef::new(Func::new(store, ty, callback)), ext: wasm_extern_t {
ext: None, which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))),
},
}); });
Box::into_raw(func) Box::into_raw(func)
} }
@@ -1012,24 +1057,25 @@ pub unsafe extern "C" fn wasm_exporttype_vec_delete(et: *mut wasm_exporttype_vec
(*et).uninitialize(); (*et).uninitialize();
} }
fn from_externtype(ty: &ExternType) -> wasm_externkind_t {
match ty {
ExternType::Func(_) => 0,
ExternType::Global(_) => 1,
ExternType::Table(_) => 2,
ExternType::Memory(_) => 3,
}
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_extern_kind(e: *const wasm_extern_t) -> wasm_externkind_t { pub unsafe extern "C" fn wasm_extern_kind(e: *const wasm_extern_t) -> wasm_externkind_t {
from_externtype(&(*e).ext.r#type()) match (*e).which {
ExternHost::Func(_) => WASM_EXTERN_FUNC,
ExternHost::Global(_) => WASM_EXTERN_GLOBAL,
ExternHost::Table(_) => WASM_EXTERN_TABLE,
ExternHost::Memory(_) => WASM_EXTERN_MEMORY,
}
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_extern_type(e: *const wasm_extern_t) -> *mut wasm_externtype_t { pub unsafe extern "C" fn wasm_extern_type(e: *const wasm_extern_t) -> *mut wasm_externtype_t {
let et = Box::new(wasm_externtype_t { let et = Box::new(wasm_externtype_t {
ty: (*e).ext.r#type(), ty: match &(*e).which {
ExternHost::Func(f) => ExternType::Func(f.borrow().ty().clone()),
ExternHost::Global(f) => ExternType::Global(f.borrow().ty().clone()),
ExternHost::Table(f) => ExternType::Table(f.borrow().ty().clone()),
ExternHost::Memory(f) => ExternType::Memory(f.borrow().ty().clone()),
},
cache: wasm_externtype_t_type_cache::Empty, cache: wasm_externtype_t_type_cache::Empty,
}); });
Box::into_raw(et) Box::into_raw(et)
@@ -1120,17 +1166,22 @@ pub unsafe extern "C" fn wasm_externtype_delete(et: *mut wasm_externtype_t) {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_externtype_kind(et: *const wasm_externtype_t) -> wasm_externkind_t { pub unsafe extern "C" fn wasm_externtype_kind(et: *const wasm_externtype_t) -> wasm_externkind_t {
from_externtype(&(*et).ty) match &(*et).ty {
ExternType::Func(_) => WASM_EXTERN_FUNC,
ExternType::Table(_) => WASM_EXTERN_TABLE,
ExternType::Global(_) => WASM_EXTERN_GLOBAL,
ExternType::Memory(_) => WASM_EXTERN_MEMORY,
}
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_func_param_arity(f: *const wasm_func_t) -> usize { pub unsafe extern "C" fn wasm_func_param_arity(f: *const wasm_func_t) -> usize {
(*f).func.borrow().param_arity() (*f).func().borrow().param_arity()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_func_result_arity(f: *const wasm_func_t) -> usize { pub unsafe extern "C" fn wasm_func_result_arity(f: *const wasm_func_t) -> usize {
(*f).func.borrow().result_arity() (*f).func().borrow().result_arity()
} }
#[no_mangle] #[no_mangle]
@@ -1279,32 +1330,15 @@ pub unsafe extern "C" fn wasm_valtype_kind(vt: *const wasm_valtype_t) -> wasm_va
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_extern_as_global(e: *mut wasm_extern_t) -> *mut wasm_global_t { pub unsafe extern "C" fn wasm_extern_as_global(e: *mut wasm_extern_t) -> *mut wasm_global_t {
if let wasm_extern_t_type_cache::Empty = (*e).cache { match &(*e).which {
(*e).cache = wasm_extern_t_type_cache::Global(wasm_global_t { ExternHost::Global(_) => e.cast(),
global: (*e).ext.global().unwrap().clone(), _ => ptr::null_mut(),
ext: None,
});
}
match &mut (*e).cache {
wasm_extern_t_type_cache::Global(g) => g,
_ => panic!("wasm_extern_as_global"),
} }
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t { pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
if (*g).ext.is_none() { &mut (*g).ext
(*g).ext = Some(Box::new(wasm_extern_t {
ext: Extern::Global((*g).global.clone()),
cache: wasm_extern_t_type_cache::Empty,
}));
}
match &mut (*g).ext {
Some(e) => e.as_mut(),
_ => panic!("wasm_global_as_extern"),
}
} }
#[no_mangle] #[no_mangle]
@@ -1322,7 +1356,7 @@ pub unsafe extern "C" fn wasm_global_same(
g1: *const wasm_global_t, g1: *const wasm_global_t,
g2: *const wasm_global_t, g2: *const wasm_global_t,
) -> bool { ) -> bool {
(*g1).global.ptr_eq(&(*g2).global) (*g1).global().ptr_eq(&(*g2).global())
} }
#[no_mangle] #[no_mangle]
@@ -1336,18 +1370,22 @@ pub unsafe extern "C" fn wasm_global_new(
(*gt).globaltype.clone(), (*gt).globaltype.clone(),
(*val).val(), (*val).val(),
)); ));
let g = Box::new(wasm_global_t { global, ext: None }); let g = Box::new(wasm_global_t {
ext: wasm_extern_t {
which: ExternHost::Global(global),
},
});
Box::into_raw(g) Box::into_raw(g)
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_global_get(g: *const wasm_global_t, out: *mut wasm_val_t) { pub unsafe extern "C" fn wasm_global_get(g: *const wasm_global_t, out: *mut wasm_val_t) {
(*out).set((*g).global.borrow_mut().get()); (*out).set((*g).global().borrow().get());
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_global_set(g: *mut wasm_global_t, val: *const wasm_val_t) { pub unsafe extern "C" fn wasm_global_set(g: *mut wasm_global_t, val: *const wasm_val_t) {
(*g).global.borrow_mut().set((*val).val()) (*g).global().borrow().set((*val).val())
} }
#[no_mangle] #[no_mangle]
@@ -1377,32 +1415,15 @@ pub unsafe extern "C" fn wasm_globaltype_new(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_extern_as_memory(e: *mut wasm_extern_t) -> *mut wasm_memory_t { pub unsafe extern "C" fn wasm_extern_as_memory(e: *mut wasm_extern_t) -> *mut wasm_memory_t {
if let wasm_extern_t_type_cache::Empty = (*e).cache { match &(*e).which {
(*e).cache = wasm_extern_t_type_cache::Memory(wasm_memory_t { ExternHost::Memory(_) => e.cast(),
memory: (*e).ext.memory().unwrap().clone(), _ => ptr::null_mut(),
ext: None,
});
}
match &mut (*e).cache {
wasm_extern_t_type_cache::Memory(m) => m,
_ => panic!("wasm_extern_as_memory"),
} }
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_memory_as_extern(m: *mut wasm_memory_t) -> *mut wasm_extern_t { pub unsafe extern "C" fn wasm_memory_as_extern(m: *mut wasm_memory_t) -> *mut wasm_extern_t {
if (*m).ext.is_none() { &mut (*m).ext
(*m).ext = Some(Box::new(wasm_extern_t {
ext: Extern::Memory((*m).memory.clone()),
cache: wasm_extern_t_type_cache::Empty,
}));
}
match &mut (*m).ext {
Some(e) => e.as_mut(),
_ => panic!("wasm_global_as_extern"),
}
} }
#[no_mangle] #[no_mangle]
@@ -1420,22 +1441,22 @@ pub unsafe extern "C" fn wasm_memory_same(
m1: *const wasm_memory_t, m1: *const wasm_memory_t,
m2: *const wasm_memory_t, m2: *const wasm_memory_t,
) -> bool { ) -> bool {
(*m1).memory.ptr_eq(&(*m2).memory) (*m1).memory().ptr_eq(&(*m2).memory())
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_memory_data(m: *mut wasm_memory_t) -> *mut u8 { pub unsafe extern "C" fn wasm_memory_data(m: *mut wasm_memory_t) -> *mut u8 {
(*m).memory.borrow().data_ptr() (*m).memory().borrow().data_ptr()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_memory_data_size(m: *const wasm_memory_t) -> usize { pub unsafe extern "C" fn wasm_memory_data_size(m: *const wasm_memory_t) -> usize {
(*m).memory.borrow().data_size() (*m).memory().borrow().data_size()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_memory_size(m: *const wasm_memory_t) -> wasm_memory_pages_t { pub unsafe extern "C" fn wasm_memory_size(m: *const wasm_memory_t) -> wasm_memory_pages_t {
(*m).memory.borrow().size() (*m).memory().borrow().size()
} }
#[no_mangle] #[no_mangle]
@@ -1443,7 +1464,7 @@ pub unsafe extern "C" fn wasm_memory_grow(
m: *mut wasm_memory_t, m: *mut wasm_memory_t,
delta: wasm_memory_pages_t, delta: wasm_memory_pages_t,
) -> bool { ) -> bool {
(*m).memory.borrow_mut().grow(delta) (*m).memory().borrow().grow(delta)
} }
#[no_mangle] #[no_mangle]
@@ -1455,7 +1476,11 @@ pub unsafe extern "C" fn wasm_memory_new(
&(*store).store.borrow(), &(*store).store.borrow(),
(*mt).memorytype.clone(), (*mt).memorytype.clone(),
)); ));
let m = Box::new(wasm_memory_t { memory, ext: None }); let m = Box::new(wasm_memory_t {
ext: wasm_extern_t {
which: ExternHost::Memory(memory),
},
});
Box::into_raw(m) Box::into_raw(m)
} }
@@ -1483,37 +1508,20 @@ pub unsafe extern "C" fn wasm_memorytype_new(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t { pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t {
if let wasm_extern_t_type_cache::Empty = (*e).cache { match &(*e).which {
(*e).cache = wasm_extern_t_type_cache::Table(wasm_table_t { ExternHost::Table(_) => e.cast(),
table: (*e).ext.table().unwrap().clone(), _ => ptr::null_mut(),
ext: None,
});
}
match &mut (*e).cache {
wasm_extern_t_type_cache::Table(t) => t,
_ => panic!("wasm_extern_as_table"),
} }
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_table_as_extern(t: *mut wasm_table_t) -> *mut wasm_extern_t { pub unsafe extern "C" fn wasm_table_as_extern(t: *mut wasm_table_t) -> *mut wasm_extern_t {
if (*t).ext.is_none() { &mut (*t).ext
(*t).ext = Some(Box::new(wasm_extern_t {
ext: Extern::Table((*t).table.clone()),
cache: wasm_extern_t_type_cache::Empty,
}));
}
match &mut (*t).ext {
Some(e) => e.as_mut(),
_ => panic!("wasm_table_as_extern"),
}
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_func_as_ref(f: *mut wasm_func_t) -> *mut wasm_ref_t { pub unsafe extern "C" fn wasm_func_as_ref(f: *mut wasm_func_t) -> *mut wasm_ref_t {
let r = (*f).func.anyref(); let r = (*f).func().anyref();
let f = Box::new(wasm_ref_t { r }); let f = Box::new(wasm_ref_t { r });
Box::into_raw(f) Box::into_raw(f)
} }
@@ -1547,12 +1555,13 @@ pub unsafe extern "C" fn wasm_table_new(
Val::AnyRef(AnyRef::Null) Val::AnyRef(AnyRef::Null)
}; };
let t = Box::new(wasm_table_t { let t = Box::new(wasm_table_t {
table: HostRef::new(Table::new( ext: wasm_extern_t {
which: ExternHost::Table(HostRef::new(Table::new(
&(*store).store.borrow(), &(*store).store.borrow(),
(*tt).tabletype.clone(), (*tt).tabletype.clone(),
init, init,
)), ))),
ext: None, },
}); });
Box::into_raw(t) Box::into_raw(t)
} }
@@ -1582,7 +1591,7 @@ pub unsafe extern "C" fn wasm_table_get(
t: *const wasm_table_t, t: *const wasm_table_t,
index: wasm_table_size_t, index: wasm_table_size_t,
) -> *mut wasm_ref_t { ) -> *mut wasm_ref_t {
let val = (*t).table.borrow().get(index); let val = (*t).table().borrow().get(index);
into_funcref(val) into_funcref(val)
} }
@@ -1593,12 +1602,12 @@ pub unsafe extern "C" fn wasm_table_set(
r: *mut wasm_ref_t, r: *mut wasm_ref_t,
) -> bool { ) -> bool {
let val = from_funcref(r); let val = from_funcref(r);
(*t).table.borrow().set(index, val) (*t).table().borrow().set(index, val)
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_table_size(t: *const wasm_table_t) -> wasm_table_size_t { pub unsafe extern "C" fn wasm_table_size(t: *const wasm_table_t) -> wasm_table_size_t {
(*t).table.borrow().size() (*t).table().borrow().size()
} }
#[no_mangle] #[no_mangle]
@@ -1608,12 +1617,12 @@ pub unsafe extern "C" fn wasm_table_grow(
init: *mut wasm_ref_t, init: *mut wasm_ref_t,
) -> bool { ) -> bool {
let init = from_funcref(init); let init = from_funcref(init);
(*t).table.borrow_mut().grow(delta, init) (*t).table().borrow().grow(delta, init)
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_table_same(t1: *const wasm_table_t, t2: *const wasm_table_t) -> bool { pub unsafe extern "C" fn wasm_table_same(t1: *const wasm_table_t, t2: *const wasm_table_t) -> bool {
(*t1).table.ptr_eq(&(*t2).table) (*t1).table().ptr_eq((*t2).table())
} }
#[no_mangle] #[no_mangle]

View File

@@ -42,23 +42,23 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> {
let module = Module::new(&store, &wasm)?; let module = Module::new(&store, &wasm)?;
let imports = [ let imports = [
HostRef::new(Func::new( Func::new(
&store, &store,
FuncType::new(Box::new([]), Box::new([ValType::I32])), FuncType::new(Box::new([]), Box::new([ValType::I32])),
Rc::new(Ret1), Rc::new(Ret1),
)) )
.into(), .into(),
HostRef::new(Func::new( Func::new(
&store, &store,
FuncType::new(Box::new([]), Box::new([ValType::F32])), FuncType::new(Box::new([]), Box::new([ValType::F32])),
Rc::new(Ret2), Rc::new(Ret2),
)) )
.into(), .into(),
]; ];
let instance = Instance::new(&store, &module, &imports)?; let instance = Instance::new(&store, &module, &imports)?;
let func = instance.find_export_by_name("foo").unwrap().func().unwrap(); let func = instance.find_export_by_name("foo").unwrap().func().unwrap();
let results = func.borrow().call(&[])?; let results = func.call(&[])?;
assert_eq!(results.len(), 1); assert_eq!(results.len(), 1);
match results[0] { match results[0] {
Val::I32(n) => assert_eq!(n, 3), Val::I32(n) => assert_eq!(n, 3),

View File

@@ -1,4 +1,4 @@
use std::cell::{Ref, RefCell}; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use wasmtime::*; use wasmtime::*;
@@ -16,7 +16,7 @@ fn test_import_calling_export() {
"#; "#;
struct Callback { struct Callback {
pub other: RefCell<Option<HostRef<Func>>>, pub other: RefCell<Option<Func>>,
} }
impl Callable for Callback { impl Callable for Callback {
@@ -25,7 +25,6 @@ fn test_import_calling_export() {
.borrow() .borrow()
.as_ref() .as_ref()
.expect("expected a function ref") .expect("expected a function ref")
.borrow()
.call(&[]) .call(&[])
.expect("expected function not to trap"); .expect("expected function not to trap");
Ok(()) Ok(())
@@ -40,18 +39,17 @@ fn test_import_calling_export() {
other: RefCell::new(None), other: RefCell::new(None),
}); });
let callback_func = HostRef::new(Func::new( let callback_func = Func::new(
&store, &store,
FuncType::new(Box::new([]), Box::new([])), FuncType::new(Box::new([]), Box::new([])),
callback.clone(), callback.clone(),
));
let imports = vec![callback_func.into()];
let instance = HostRef::new(
Instance::new(&store, &module, imports.as_slice()).expect("failed to instantiate module"),
); );
let exports = Ref::map(instance.borrow(), |instance| instance.exports()); let imports = vec![callback_func.into()];
let instance =
Instance::new(&store, &module, imports.as_slice()).expect("failed to instantiate module");
let exports = instance.exports();
assert!(!exports.is_empty()); assert!(!exports.is_empty());
let run_func = exports[0] let run_func = exports[0]
@@ -65,8 +63,5 @@ fn test_import_calling_export() {
.clone(), .clone(),
); );
run_func run_func.call(&[]).expect("expected function not to trap");
.borrow()
.call(&[])
.expect("expected function not to trap");
} }

View File

@@ -26,20 +26,16 @@ fn test_trap_return() -> Result<(), String> {
let module = let module =
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?; Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?;
let hello_type = FuncType::new(Box::new([]), Box::new([])); let hello_type = FuncType::new(Box::new([]), Box::new([]));
let hello_func = HostRef::new(Func::new(&store, hello_type, Rc::new(HelloCallback))); let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback));
let imports = vec![hello_func.into()]; let imports = vec![hello_func.into()];
let instance = Instance::new(&store, &module, imports.as_slice()) let instance = Instance::new(&store, &module, &imports)
.map_err(|e| format!("failed to instantiate module: {:?}", e))?; .map_err(|e| format!("failed to instantiate module: {:?}", e))?;
let run_func = instance.exports()[0] let run_func = instance.exports()[0]
.func() .func()
.expect("expected function export"); .expect("expected function export");
let e = run_func let e = run_func.call(&[]).err().expect("error calling function");
.borrow()
.call(&[])
.err()
.expect("error calling function");
assert_eq!(e.message(), "test 123"); assert_eq!(e.message(), "test 123");

View File

@@ -96,7 +96,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
let mut engine: Option<Engine> = None; let mut engine: Option<Engine> = None;
let mut store: Option<Store> = None; let mut store: Option<Store> = None;
let mut modules: HashMap<usize, Module> = Default::default(); let mut modules: HashMap<usize, Module> = Default::default();
let mut instances: HashMap<usize, HostRef<Instance>> = Default::default(); let mut instances: HashMap<usize, Instance> = Default::default();
for call in api.calls { for call in api.calls {
match call { match call {
@@ -153,7 +153,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
// table might not have room for an element segment that we want to // table might not have room for an element segment that we want to
// initialize into it. // initialize into it.
if let Ok(instance) = Instance::new(store.as_ref().unwrap(), &module, &imports) { if let Ok(instance) = Instance::new(store.as_ref().unwrap(), &module, &imports) {
instances.insert(id, HostRef::new(instance)); instances.insert(id, instance);
} }
} }
@@ -175,25 +175,22 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
} }
}; };
let funcs = { let funcs = instance
let instance = instance.borrow();
instance
.exports() .exports()
.iter() .iter()
.filter_map(|e| match e { .filter_map(|e| match e {
Extern::Func(f) => Some(f.clone()), Extern::Func(f) => Some(f.clone()),
_ => None, _ => None,
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>();
};
if funcs.is_empty() { if funcs.is_empty() {
continue; continue;
} }
let nth = nth % funcs.len(); let nth = nth % funcs.len();
let f = funcs[nth].borrow(); let f = &funcs[nth];
let ty = f.r#type(); let ty = f.ty();
let params = match ty let params = match ty
.params() .params()
.iter() .iter()

View File

@@ -2,7 +2,7 @@
use std::rc::Rc; use std::rc::Rc;
use wasmtime::{ use wasmtime::{
Callable, Extern, ExternType, Func, FuncType, Global, GlobalType, HostRef, ImportType, Memory, Callable, Extern, ExternType, Func, FuncType, Global, GlobalType, ImportType, Memory,
MemoryType, Store, Table, TableType, Trap, Val, ValType, MemoryType, Store, Table, TableType, Trap, Val, ValType,
}; };
@@ -11,18 +11,12 @@ pub fn dummy_imports(store: &Store, import_tys: &[ImportType]) -> Result<Vec<Ext
let mut imports = Vec::with_capacity(import_tys.len()); let mut imports = Vec::with_capacity(import_tys.len());
for imp in import_tys { for imp in import_tys {
imports.push(match imp.ty() { imports.push(match imp.ty() {
ExternType::Func(func_ty) => { ExternType::Func(func_ty) => Extern::Func(DummyFunc::new(&store, func_ty.clone())),
Extern::Func(HostRef::new(DummyFunc::new(&store, func_ty.clone())))
}
ExternType::Global(global_ty) => { ExternType::Global(global_ty) => {
Extern::Global(HostRef::new(dummy_global(&store, global_ty.clone())?)) Extern::Global(dummy_global(&store, global_ty.clone())?)
}
ExternType::Table(table_ty) => {
Extern::Table(HostRef::new(dummy_table(&store, table_ty.clone())?))
}
ExternType::Memory(mem_ty) => {
Extern::Memory(HostRef::new(dummy_memory(&store, mem_ty.clone())))
} }
ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_ty.clone())?),
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(&store, mem_ty.clone())),
}); });
} }
Ok(imports) Ok(imports)

View File

@@ -125,18 +125,17 @@ impl ModuleData {
/// wasm interface types. /// wasm interface types.
pub fn invoke_export( pub fn invoke_export(
&self, &self,
instance: &wasmtime::HostRef<wasmtime::Instance>, instance: &wasmtime::Instance,
export: &str, export: &str,
args: &[Value], args: &[Value],
) -> Result<Vec<Value>> { ) -> Result<Vec<Value>> {
let mut handle = instance.borrow().handle().clone(); let mut handle = instance.handle().clone();
let binding = self.binding_for_export(&mut handle, export)?; let binding = self.binding_for_export(&mut handle, export)?;
let incoming = binding.param_bindings()?; let incoming = binding.param_bindings()?;
let outgoing = binding.result_bindings()?; let outgoing = binding.result_bindings()?;
let f = instance let f = instance
.borrow()
.find_export_by_name(export) .find_export_by_name(export)
.ok_or_else(|| format_err!("failed to find export `{}`", export))? .ok_or_else(|| format_err!("failed to find export `{}`", export))?
.func() .func()
@@ -148,7 +147,7 @@ impl ModuleData {
.into_iter() .into_iter()
.map(|rv| rv.into()) .map(|rv| rv.into())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let wasm_results = match f.borrow().call(&wasm_args) { let wasm_results = match f.call(&wasm_args) {
Ok(values) => values Ok(values) => values
.to_vec() .to_vec()
.into_iter() .into_iter()
@@ -322,20 +321,19 @@ trait TranslateContext {
unsafe fn get_memory(&mut self) -> Result<&mut [u8]>; unsafe fn get_memory(&mut self) -> Result<&mut [u8]>;
} }
struct InstanceTranslateContext(pub wasmtime::HostRef<wasmtime::Instance>); struct InstanceTranslateContext(pub wasmtime::Instance);
impl TranslateContext for InstanceTranslateContext { impl TranslateContext for InstanceTranslateContext {
fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result<i32> { fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result<i32> {
let alloc = self let alloc = self
.0 .0
.borrow()
.find_export_by_name(alloc_func_name) .find_export_by_name(alloc_func_name)
.ok_or_else(|| format_err!("failed to find alloc function `{}`", alloc_func_name))? .ok_or_else(|| format_err!("failed to find alloc function `{}`", alloc_func_name))?
.func() .func()
.ok_or_else(|| format_err!("`{}` is not a (alloc) function", alloc_func_name))? .ok_or_else(|| format_err!("`{}` is not a (alloc) function", alloc_func_name))?
.clone(); .clone();
let alloc_args = vec![wasmtime::Val::I32(len)]; let alloc_args = vec![wasmtime::Val::I32(len)];
let results = match alloc.borrow().call(&alloc_args) { let results = match alloc.call(&alloc_args) {
Ok(values) => values, Ok(values) => values,
Err(trap) => bail!("trapped: {:?}", trap), Err(trap) => bail!("trapped: {:?}", trap),
}; };
@@ -350,14 +348,13 @@ impl TranslateContext for InstanceTranslateContext {
unsafe fn get_memory(&mut self) -> Result<&mut [u8]> { unsafe fn get_memory(&mut self) -> Result<&mut [u8]> {
let memory = self let memory = self
.0 .0
.borrow()
.find_export_by_name("memory") .find_export_by_name("memory")
.ok_or_else(|| format_err!("failed to find `memory` export"))? .ok_or_else(|| format_err!("failed to find `memory` export"))?
.memory() .memory()
.ok_or_else(|| format_err!("`memory` is not a memory"))? .ok_or_else(|| format_err!("`memory` is not a memory"))?
.clone(); .clone();
let ptr = memory.borrow().data_ptr(); let ptr = memory.data_ptr();
let len = memory.borrow().data_size(); let len = memory.data_size();
Ok(std::slice::from_raw_parts_mut(ptr, len)) Ok(std::slice::from_raw_parts_mut(ptr, len))
} }
} }

View File

@@ -10,17 +10,16 @@ use wasmtime_interface_types::ModuleData;
// TODO support non-export functions // TODO support non-export functions
#[pyclass] #[pyclass]
pub struct Function { pub struct Function {
pub instance: wasmtime::HostRef<wasmtime::Instance>, pub instance: wasmtime::Instance,
pub export_name: String, pub export_name: String,
pub args_types: Vec<wasmtime::ValType>, pub args_types: Vec<wasmtime::ValType>,
pub data: Rc<ModuleData>, pub data: Rc<ModuleData>,
} }
impl Function { impl Function {
pub fn func(&self) -> wasmtime::HostRef<wasmtime::Func> { pub fn func(&self) -> wasmtime::Func {
let e = self let e = self
.instance .instance
.borrow()
.find_export_by_name(&self.export_name) .find_export_by_name(&self.export_name)
.expect("named export") .expect("named export")
.clone(); .clone();
@@ -125,10 +124,7 @@ impl wasmtime::Callable for WrappedFn {
} }
} }
pub fn wrap_into_pyfunction( pub fn wrap_into_pyfunction(store: &wasmtime::Store, callable: &PyAny) -> PyResult<wasmtime::Func> {
store: &wasmtime::Store,
callable: &PyAny,
) -> PyResult<wasmtime::HostRef<wasmtime::Func>> {
if !callable.hasattr("__annotations__")? { if !callable.hasattr("__annotations__")? {
// TODO support calls without annotations? // TODO support calls without annotations?
return Err(PyErr::new::<Exception, _>( return Err(PyErr::new::<Exception, _>(
@@ -154,6 +150,5 @@ pub fn wrap_into_pyfunction(
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let wrapped = WrappedFn::new(callable.to_object(gil.python()), returns); let wrapped = WrappedFn::new(callable.to_object(gil.python()), returns);
let f = wasmtime::Func::new(store, ft, Rc::new(wrapped)); Ok(wasmtime::Func::new(store, ft, Rc::new(wrapped)))
Ok(wasmtime::HostRef::new(f))
} }

View File

@@ -9,7 +9,7 @@ use wasmtime_interface_types::ModuleData;
#[pyclass] #[pyclass]
pub struct Instance { pub struct Instance {
pub instance: wasmtime::HostRef<wasmtime::Instance>, pub instance: wasmtime::Instance,
pub data: Rc<ModuleData>, pub data: Rc<ModuleData>,
} }
@@ -20,7 +20,7 @@ impl Instance {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();
let exports = PyDict::new(py); let exports = PyDict::new(py);
let module = self.instance.borrow().module().clone(); let module = self.instance.module().clone();
for (i, e) in module.exports().iter().enumerate() { for (i, e) in module.exports().iter().enumerate() {
match e.ty() { match e.ty() {
wasmtime::ExternType::Func(ft) => { wasmtime::ExternType::Func(ft) => {
@@ -43,10 +43,7 @@ impl Instance {
let f = Py::new( let f = Py::new(
py, py,
Memory { Memory {
memory: self.instance.borrow().exports()[i] memory: self.instance.exports()[i].memory().unwrap().clone(),
.memory()
.unwrap()
.clone(),
}, },
)?; )?;
exports.set_item(e.name().to_string(), f)?; exports.set_item(e.name().to_string(), f)?;

View File

@@ -122,10 +122,8 @@ pub fn instantiate(
} }
} }
let instance = wasmtime::HostRef::new( let instance = wasmtime::Instance::new(&store, &module, &imports)
wasmtime::Instance::new(&store, &module, &imports) .map_err(|t| PyErr::new::<Exception, _>(format!("instantiated with trap {:?}", t)))?;
.map_err(|t| PyErr::new::<Exception, _>(format!("instantiated with trap {:?}", t)))?,
);
let module = Py::new(py, Module { module })?; let module = Py::new(py, Module { module })?;

View File

@@ -10,14 +10,14 @@ use std::ptr;
#[pyclass] #[pyclass]
pub struct Memory { pub struct Memory {
pub memory: wasmtime::HostRef<wasmtime::Memory>, pub memory: wasmtime::Memory,
} }
#[pymethods] #[pymethods]
impl Memory { impl Memory {
#[getter(current)] #[getter(current)]
pub fn current(&self) -> u32 { pub fn current(&self) -> u32 {
self.memory.borrow().size() self.memory.size()
} }
pub fn grow(&self, _number: u32) -> u32 { pub fn grow(&self, _number: u32) -> u32 {
@@ -48,8 +48,8 @@ impl PyBufferProtocol for Memory {
}; };
unsafe { unsafe {
let base = self.memory.borrow().data_ptr(); let base = self.memory.data_ptr();
let current_length = self.memory.borrow().data_size(); let current_length = self.memory.data_size();
(*view).buf = base as *mut c_void; (*view).buf = base as *mut c_void;
(*view).len = current_length as isize; (*view).len = current_length as isize;

View File

@@ -34,7 +34,7 @@ fn generate_struct(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
let root = root(); let root = root();
Ok(quote! { Ok(quote! {
#vis struct #name { #vis struct #name {
instance: #root::wasmtime::HostRef<#root::wasmtime::Instance>, instance: #root::wasmtime::Instance,
data: #root::wasmtime_interface_types::ModuleData, data: #root::wasmtime_interface_types::ModuleData,
} }
}) })
@@ -48,7 +48,7 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
#vis fn load_file(path: impl AsRef<std::path::Path>) -> #root::anyhow::Result<#name> { #vis fn load_file(path: impl AsRef<std::path::Path>) -> #root::anyhow::Result<#name> {
let bytes = std::fs::read(path)?; let bytes = std::fs::read(path)?;
use #root::wasmtime::{HostRef, Config, Extern, Engine, Store, Instance, Module}; use #root::wasmtime::{Config, Extern, Engine, Store, Instance, Module};
use #root::anyhow::{bail, format_err}; use #root::anyhow::{bail, format_err};
let engine = Engine::new(Config::new().wasm_multi_value(true)); let engine = Engine::new(Config::new().wasm_multi_value(true));
@@ -74,9 +74,8 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
} }
} }
} }
let instance = HostRef::new( let instance =
Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))? Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?;
);
Ok(#name { instance, data }) Ok(#name { instance, data })
} }

View File

@@ -1,7 +1,7 @@
use anyhow::{bail, Context}; use anyhow::{bail, Context};
use std::fs::File; use std::fs::File;
use std::path::Path; use std::path::Path;
use wasmtime::{HostRef, Instance, Module, Store}; use wasmtime::{Instance, Module, Store};
pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> { pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> {
let store = Store::default(); let store = Store::default();
@@ -61,13 +61,12 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let instance = HostRef::new(Instance::new(&store, &module, &imports).context(format!( let instance = Instance::new(&store, &module, &imports).context(format!(
"error while instantiating Wasm module '{}'", "error while instantiating Wasm module '{}'",
bin_name, bin_name,
))?); ))?;
let export = instance let export = instance
.borrow()
.find_export_by_name("_start") .find_export_by_name("_start")
.context("expected a _start export")? .context("expected a _start export")?
.clone(); .clone();
@@ -75,7 +74,6 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
if let Err(trap) = export if let Err(trap) = export
.func() .func()
.context("expected export to be a func")? .context("expected export to be a func")?
.borrow()
.call(&[]) .call(&[])
{ {
bail!("trapped: {:?}", trap); bail!("trapped: {:?}", trap);

View File

@@ -31,35 +31,35 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
let ty = FuncType::new(Box::new([]), Box::new([])); let ty = FuncType::new(Box::new([]), Box::new([]));
let func = wrap(store, ty, |_params, _results| Ok(())); let func = wrap(store, ty, |_params, _results| Ok(()));
ret.insert("print", Extern::Func(HostRef::new(func))); ret.insert("print", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::I32]), Box::new([])); let ty = FuncType::new(Box::new([ValType::I32]), Box::new([]));
let func = wrap(store, ty, |params, _results| { let func = wrap(store, ty, |params, _results| {
println!("{}: i32", params[0].unwrap_i32()); println!("{}: i32", params[0].unwrap_i32());
Ok(()) Ok(())
}); });
ret.insert("print_i32", Extern::Func(HostRef::new(func))); ret.insert("print_i32", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::I64]), Box::new([])); let ty = FuncType::new(Box::new([ValType::I64]), Box::new([]));
let func = wrap(store, ty, |params, _results| { let func = wrap(store, ty, |params, _results| {
println!("{}: i64", params[0].unwrap_i64()); println!("{}: i64", params[0].unwrap_i64());
Ok(()) Ok(())
}); });
ret.insert("print_i64", Extern::Func(HostRef::new(func))); ret.insert("print_i64", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::F32]), Box::new([])); let ty = FuncType::new(Box::new([ValType::F32]), Box::new([]));
let func = wrap(store, ty, |params, _results| { let func = wrap(store, ty, |params, _results| {
println!("{}: f32", params[0].unwrap_f32()); println!("{}: f32", params[0].unwrap_f32());
Ok(()) Ok(())
}); });
ret.insert("print_f32", Extern::Func(HostRef::new(func))); ret.insert("print_f32", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::F64]), Box::new([])); let ty = FuncType::new(Box::new([ValType::F64]), Box::new([]));
let func = wrap(store, ty, |params, _results| { let func = wrap(store, ty, |params, _results| {
println!("{}: f64", params[0].unwrap_f64()); println!("{}: f64", params[0].unwrap_f64());
Ok(()) Ok(())
}); });
ret.insert("print_f64", Extern::Func(HostRef::new(func))); ret.insert("print_f64", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::I32, ValType::F32]), Box::new([])); let ty = FuncType::new(Box::new([ValType::I32, ValType::F32]), Box::new([]));
let func = wrap(store, ty, |params, _results| { let func = wrap(store, ty, |params, _results| {
@@ -67,7 +67,7 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
println!("{}: f32", params[1].unwrap_f32()); println!("{}: f32", params[1].unwrap_f32());
Ok(()) Ok(())
}); });
ret.insert("print_i32_f32", Extern::Func(HostRef::new(func))); ret.insert("print_i32_f32", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::F64, ValType::F64]), Box::new([])); let ty = FuncType::new(Box::new([ValType::F64, ValType::F64]), Box::new([]));
let func = wrap(store, ty, |params, _results| { let func = wrap(store, ty, |params, _results| {
@@ -75,31 +75,31 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
println!("{}: f64", params[1].unwrap_f64()); println!("{}: f64", params[1].unwrap_f64());
Ok(()) Ok(())
}); });
ret.insert("print_f64_f64", Extern::Func(HostRef::new(func))); ret.insert("print_f64_f64", Extern::Func(func));
let ty = GlobalType::new(ValType::I32, Mutability::Const); let ty = GlobalType::new(ValType::I32, Mutability::Const);
let g = Global::new(store, ty, Val::I32(666)); let g = Global::new(store, ty, Val::I32(666));
ret.insert("global_i32", Extern::Global(HostRef::new(g))); ret.insert("global_i32", Extern::Global(g));
let ty = GlobalType::new(ValType::I64, Mutability::Const); let ty = GlobalType::new(ValType::I64, Mutability::Const);
let g = Global::new(store, ty, Val::I64(666)); let g = Global::new(store, ty, Val::I64(666));
ret.insert("global_i64", Extern::Global(HostRef::new(g))); ret.insert("global_i64", Extern::Global(g));
let ty = GlobalType::new(ValType::F32, Mutability::Const); let ty = GlobalType::new(ValType::F32, Mutability::Const);
let g = Global::new(store, ty, Val::F32(0x4426_8000)); let g = Global::new(store, ty, Val::F32(0x4426_8000));
ret.insert("global_f32", Extern::Global(HostRef::new(g))); ret.insert("global_f32", Extern::Global(g));
let ty = GlobalType::new(ValType::F64, Mutability::Const); let ty = GlobalType::new(ValType::F64, Mutability::Const);
let g = Global::new(store, ty, Val::F64(0x4084_d000_0000_0000)); let g = Global::new(store, ty, Val::F64(0x4084_d000_0000_0000));
ret.insert("global_f64", Extern::Global(HostRef::new(g))); ret.insert("global_f64", Extern::Global(g));
let ty = TableType::new(ValType::FuncRef, Limits::new(10, Some(20))); let ty = TableType::new(ValType::FuncRef, Limits::new(10, Some(20)));
let table = Table::new(store, ty, Val::AnyRef(AnyRef::Null)); let table = Table::new(store, ty, Val::AnyRef(AnyRef::Null));
ret.insert("table", Extern::Table(HostRef::new(table))); ret.insert("table", Extern::Table(table));
let ty = MemoryType::new(Limits::new(1, Some(2))); let ty = MemoryType::new(Limits::new(1, Some(2)));
let memory = Memory::new(store, ty); let memory = Memory::new(store, ty);
ret.insert("memory", Extern::Memory(HostRef::new(memory))); ret.insert("memory", Extern::Memory(memory));
return ret; return ret;
} }

View File

@@ -27,9 +27,9 @@ fn runtime_value(v: &wast::Expression<'_>) -> Result<Val> {
pub struct WastContext { pub struct WastContext {
/// Wast files have a concept of a "current" module, which is the most /// Wast files have a concept of a "current" module, which is the most
/// recently defined. /// recently defined.
current: Option<HostRef<Instance>>, current: Option<Instance>,
instances: HashMap<String, HostRef<Instance>>, instances: HashMap<String, Instance>,
store: Store, store: Store,
spectest: Option<HashMap<&'static str, Extern>>, spectest: Option<HashMap<&'static str, Extern>>,
} }
@@ -50,7 +50,7 @@ impl WastContext {
} }
} }
fn get_instance(&self, instance_name: Option<&str>) -> Result<HostRef<Instance>> { fn get_instance(&self, instance_name: Option<&str>) -> Result<Instance> {
match instance_name { match instance_name {
Some(name) => self Some(name) => self
.instances .instances
@@ -64,7 +64,7 @@ impl WastContext {
} }
} }
fn instantiate(&self, module: &[u8]) -> Result<Outcome<HostRef<Instance>>> { fn instantiate(&self, module: &[u8]) -> Result<Outcome<Instance>> {
let module = Module::new(&self.store, module)?; let module = Module::new(&self.store, module)?;
let mut imports = Vec::new(); let mut imports = Vec::new();
for import in module.imports() { for import in module.imports() {
@@ -85,7 +85,6 @@ impl WastContext {
.get(import.module()) .get(import.module())
.ok_or_else(|| anyhow!("no module named `{}`", import.module()))?; .ok_or_else(|| anyhow!("no module named `{}`", import.module()))?;
let export = instance let export = instance
.borrow()
.find_export_by_name(import.name()) .find_export_by_name(import.name())
.ok_or_else(|| anyhow!("unknown import `{}::{}`", import.name(), import.module()))? .ok_or_else(|| anyhow!("unknown import `{}::{}`", import.name(), import.module()))?
.clone(); .clone();
@@ -101,7 +100,7 @@ impl WastContext {
return Err(e); return Err(e);
} }
}; };
Ok(Outcome::Ok(HostRef::new(instance))) Ok(Outcome::Ok(instance))
} }
/// Register "spectest" which is used by the spec testsuite. /// Register "spectest" which is used by the spec testsuite.
@@ -159,12 +158,11 @@ impl WastContext {
) -> Result<Outcome> { ) -> Result<Outcome> {
let values = args.iter().map(runtime_value).collect::<Result<Vec<_>>>()?; let values = args.iter().map(runtime_value).collect::<Result<Vec<_>>>()?;
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
let instance = instance.borrow();
let export = instance let export = instance
.find_export_by_name(field) .find_export_by_name(field)
.ok_or_else(|| anyhow!("no global named `{}`", field))?; .ok_or_else(|| anyhow!("no global named `{}`", field))?;
let func = match export { let func = match export {
Extern::Func(f) => f.borrow(), Extern::Func(f) => f,
_ => bail!("export of `{}` wasn't a global", field), _ => bail!("export of `{}` wasn't a global", field),
}; };
Ok(match func.call(&values) { Ok(match func.call(&values) {
@@ -176,12 +174,11 @@ impl WastContext {
/// Get the value of an exported global from an instance. /// Get the value of an exported global from an instance.
fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result<Outcome> { fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result<Outcome> {
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
let instance = instance.borrow();
let export = instance let export = instance
.find_export_by_name(field) .find_export_by_name(field)
.ok_or_else(|| anyhow!("no global named `{}`", field))?; .ok_or_else(|| anyhow!("no global named `{}`", field))?;
let global = match export { let global = match export {
Extern::Global(g) => g.borrow(), Extern::Global(g) => g,
_ => bail!("export of `{}` wasn't a global", field), _ => bail!("export of `{}` wasn't a global", field),
}; };
Ok(Outcome::Ok(vec![global.get()])) Ok(Outcome::Ok(vec![global.get()]))

View File

@@ -11,7 +11,7 @@ use std::{
}; };
use structopt::{clap::AppSettings, StructOpt}; use structopt::{clap::AppSettings, StructOpt};
use wasi_common::preopen_dir; use wasi_common::preopen_dir;
use wasmtime::{Config, Engine, HostRef, Instance, Module, Store}; use wasmtime::{Config, Engine, Instance, Module, Store};
use wasmtime_environ::cache_init; use wasmtime_environ::cache_init;
use wasmtime_interface_types::ModuleData; use wasmtime_interface_types::ModuleData;
use wasmtime_wasi::{ use wasmtime_wasi::{
@@ -148,7 +148,7 @@ impl RunCommand {
let preopen_dirs = self.compute_preopen_dirs()?; let preopen_dirs = self.compute_preopen_dirs()?;
let argv = self.compute_argv(); let argv = self.compute_argv();
let wasi_unstable = HostRef::new(if self.enable_wasi_c { let wasi_unstable = if self.enable_wasi_c {
#[cfg(feature = "wasi-c")] #[cfg(feature = "wasi-c")]
{ {
let global_exports = store.global_exports().clone(); let global_exports = store.global_exports().clone();
@@ -161,14 +161,10 @@ impl RunCommand {
} }
} else { } else {
create_wasi_instance_snapshot_0(&store, &preopen_dirs, &argv, &self.vars)? create_wasi_instance_snapshot_0(&store, &preopen_dirs, &argv, &self.vars)?
}); };
let wasi_snapshot_preview1 = HostRef::new(create_wasi_instance( let wasi_snapshot_preview1 =
&store, create_wasi_instance(&store, &preopen_dirs, &argv, &self.vars)?;
&preopen_dirs,
&argv,
&self.vars,
)?);
module_registry.insert("wasi_unstable".to_owned(), wasi_unstable); module_registry.insert("wasi_unstable".to_owned(), wasi_unstable);
module_registry.insert("wasi_snapshot_preview1".to_owned(), wasi_snapshot_preview1); module_registry.insert("wasi_snapshot_preview1".to_owned(), wasi_snapshot_preview1);
@@ -232,9 +228,9 @@ impl RunCommand {
fn instantiate_module( fn instantiate_module(
store: &Store, store: &Store,
module_registry: &HashMap<String, HostRef<Instance>>, module_registry: &HashMap<String, Instance>,
path: &Path, path: &Path,
) -> Result<(HostRef<Instance>, Module, Vec<u8>)> { ) -> Result<(Instance, Module, Vec<u8>)> {
// Read the wasm module binary either as `*.wat` or a raw binary // Read the wasm module binary either as `*.wat` or a raw binary
let data = wat::parse_file(path)?; let data = wat::parse_file(path)?;
@@ -248,7 +244,7 @@ impl RunCommand {
let module_name = i.module(); let module_name = i.module();
if let Some(instance) = module_registry.get(module_name) { if let Some(instance) = module_registry.get(module_name) {
let field_name = i.name(); let field_name = i.name();
if let Some(export) = instance.borrow().find_export_by_name(field_name) { if let Some(export) = instance.find_export_by_name(field_name) {
Ok(export.clone()) Ok(export.clone())
} else { } else {
bail!( bail!(
@@ -263,10 +259,8 @@ impl RunCommand {
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let instance = HostRef::new( let instance = Instance::new(store, &module, &imports)
Instance::new(store, &module, &imports) .context(format!("failed to instantiate {:?}", path))?;
.context(format!("failed to instantiate {:?}", path))?,
);
Ok((instance, module, data)) Ok((instance, module, data))
} }
@@ -274,7 +268,7 @@ impl RunCommand {
fn handle_module( fn handle_module(
&self, &self,
store: &Store, store: &Store,
module_registry: &HashMap<String, HostRef<Instance>>, module_registry: &HashMap<String, Instance>,
) -> Result<()> { ) -> Result<()> {
let (instance, module, data) = let (instance, module, data) =
Self::instantiate_module(store, module_registry, &self.module)?; Self::instantiate_module(store, module_registry, &self.module)?;
@@ -301,16 +295,11 @@ impl RunCommand {
Ok(()) Ok(())
} }
fn invoke_export( fn invoke_export(&self, instance: Instance, data: &ModuleData, name: &str) -> Result<()> {
&self,
instance: HostRef<Instance>,
data: &ModuleData,
name: &str,
) -> Result<()> {
use wasm_webidl_bindings::ast; use wasm_webidl_bindings::ast;
use wasmtime_interface_types::Value; use wasmtime_interface_types::Value;
let mut handle = instance.borrow().handle().clone(); let mut handle = instance.handle().clone();
// Use the binding information in `ModuleData` to figure out what arguments // Use the binding information in `ModuleData` to figure out what arguments
// need to be passed to the function that we're invoking. Currently we take // need to be passed to the function that we're invoking. Currently we take

View File

@@ -1,6 +1,5 @@
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
mod tests { mod tests {
use core::cell::Ref;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use wasmtime::*; use wasmtime::*;
@@ -38,7 +37,7 @@ mod tests {
"#; "#;
fn invoke_export( fn invoke_export(
instance: &HostRef<Instance>, instance: &Instance,
data: &[u8], data: &[u8],
func_name: &str, func_name: &str,
) -> Result<Vec<Value>, anyhow::Error> { ) -> Result<Vec<Value>, anyhow::Error> {
@@ -46,8 +45,8 @@ mod tests {
} }
// Locate "memory" export, get base address and size and set memory protection to PROT_NONE // Locate "memory" export, get base address and size and set memory protection to PROT_NONE
fn set_up_memory(instance: &HostRef<Instance>) -> (*mut u8, usize) { fn set_up_memory(instance: &Instance) -> (*mut u8, usize) {
let mem_export = instance.borrow().get_wasmtime_memory().expect("memory"); let mem_export = instance.get_wasmtime_memory().expect("memory");
let (base, length) = if let wasmtime_runtime::Export::Memory { let (base, length) = if let wasmtime_runtime::Export::Memory {
definition, definition,
@@ -107,16 +106,14 @@ mod tests {
let store = Store::new(&engine); let store = Store::new(&engine);
let data = wat::parse_str(WAT1)?; let data = wat::parse_str(WAT1)?;
let module = Module::new(&store, &data)?; let module = Module::new(&store, &data)?;
let instance = HostRef::new(Instance::new(&store, &module, &[])?); let instance = Instance::new(&store, &module, &[])?;
let (base, length) = set_up_memory(&instance); let (base, length) = set_up_memory(&instance);
instance instance.set_signal_handler(move |signum, siginfo, _| {
.borrow_mut()
.set_signal_handler(move |signum, siginfo, _| {
handle_sigsegv(base, length, signum, siginfo) handle_sigsegv(base, length, signum, siginfo)
}); });
let exports = Ref::map(instance.borrow(), |instance| instance.exports()); let exports = instance.exports();
assert!(!exports.is_empty()); assert!(!exports.is_empty());
// these invoke wasmtime_call_trampoline from action.rs // these invoke wasmtime_call_trampoline from action.rs
@@ -140,10 +137,7 @@ mod tests {
.func() .func()
.expect("expected a 'read' func in the module"); .expect("expected a 'read' func in the module");
println!("calling read..."); println!("calling read...");
let result = read_func let result = read_func.call(&[]).expect("expected function not to trap");
.borrow()
.call(&[])
.expect("expected function not to trap");
assert_eq!(123i32, result[0].clone().unwrap_i32()); assert_eq!(123i32, result[0].clone().unwrap_i32());
} }
@@ -152,7 +146,7 @@ mod tests {
.func() .func()
.expect("expected a 'read_out_of_bounds' func in the module"); .expect("expected a 'read_out_of_bounds' func in the module");
println!("calling read_out_of_bounds..."); println!("calling read_out_of_bounds...");
let trap = read_out_of_bounds_func.borrow().call(&[]).unwrap_err(); let trap = read_out_of_bounds_func.call(&[]).unwrap_err();
assert!(trap assert!(trap
.message() .message()
.starts_with("call error: wasm trap: out of bounds memory access")); .starts_with("call error: wasm trap: out of bounds memory access"));
@@ -169,13 +163,13 @@ mod tests {
// Set up multiple instances // Set up multiple instances
let instance1 = HostRef::new(Instance::new(&store, &module, &[])?); let instance1 = Instance::new(&store, &module, &[])?;
let instance1_handler_triggered = Rc::new(AtomicBool::new(false)); let instance1_handler_triggered = Rc::new(AtomicBool::new(false));
{ {
let (base1, length1) = set_up_memory(&instance1); let (base1, length1) = set_up_memory(&instance1);
instance1.borrow_mut().set_signal_handler({ instance1.set_signal_handler({
let instance1_handler_triggered = instance1_handler_triggered.clone(); let instance1_handler_triggered = instance1_handler_triggered.clone();
move |_signum, _siginfo, _context| { move |_signum, _siginfo, _context| {
// Remove protections so the execution may resume // Remove protections so the execution may resume
@@ -196,15 +190,13 @@ mod tests {
}); });
} }
let instance2 = HostRef::new( let instance2 = Instance::new(&store, &module, &[]).expect("failed to instantiate module");
Instance::new(&store, &module, &[]).expect("failed to instantiate module"),
);
let instance2_handler_triggered = Rc::new(AtomicBool::new(false)); let instance2_handler_triggered = Rc::new(AtomicBool::new(false));
{ {
let (base2, length2) = set_up_memory(&instance2); let (base2, length2) = set_up_memory(&instance2);
instance2.borrow_mut().set_signal_handler({ instance2.set_signal_handler({
let instance2_handler_triggered = instance2_handler_triggered.clone(); let instance2_handler_triggered = instance2_handler_triggered.clone();
move |_signum, _siginfo, _context| { move |_signum, _siginfo, _context| {
// Remove protections so the execution may resume // Remove protections so the execution may resume
@@ -229,7 +221,7 @@ mod tests {
// First instance1 // First instance1
{ {
let exports1 = Ref::map(instance1.borrow(), |i| i.exports()); let exports1 = instance1.exports();
assert!(!exports1.is_empty()); assert!(!exports1.is_empty());
println!("calling instance1.read..."); println!("calling instance1.read...");
@@ -244,7 +236,7 @@ mod tests {
// And then instance2 // And then instance2
{ {
let exports2 = Ref::map(instance2.borrow(), |i| i.exports()); let exports2 = instance2.exports();
assert!(!exports2.is_empty()); assert!(!exports2.is_empty());
println!("calling instance2.read..."); println!("calling instance2.read...");
@@ -267,28 +259,24 @@ mod tests {
// instance1 which defines 'read' // instance1 which defines 'read'
let data1 = wat::parse_str(WAT1)?; let data1 = wat::parse_str(WAT1)?;
let module1 = Module::new(&store, &data1)?; let module1 = Module::new(&store, &data1)?;
let instance1: HostRef<Instance> = HostRef::new(Instance::new(&store, &module1, &[])?); let instance1 = Instance::new(&store, &module1, &[])?;
let (base1, length1) = set_up_memory(&instance1); let (base1, length1) = set_up_memory(&instance1);
instance1 instance1.set_signal_handler(move |signum, siginfo, _| {
.borrow_mut()
.set_signal_handler(move |signum, siginfo, _| {
println!("instance1"); println!("instance1");
handle_sigsegv(base1, length1, signum, siginfo) handle_sigsegv(base1, length1, signum, siginfo)
}); });
let instance1_exports = Ref::map(instance1.borrow(), |i| i.exports()); let instance1_exports = instance1.exports();
assert!(!instance1_exports.is_empty()); assert!(!instance1_exports.is_empty());
let instance1_read = instance1_exports[0].clone(); let instance1_read = instance1_exports[0].clone();
// instance2 wich calls 'instance1.read' // instance2 wich calls 'instance1.read'
let data2 = wat::parse_str(WAT2)?; let data2 = wat::parse_str(WAT2)?;
let module2 = Module::new(&store, &data2)?; let module2 = Module::new(&store, &data2)?;
let instance2 = HostRef::new(Instance::new(&store, &module2, &[instance1_read])?); let instance2 = Instance::new(&store, &module2, &[instance1_read])?;
// since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle // since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle
// SIGSEGV originating from within the memory of instance1 // SIGSEGV originating from within the memory of instance1
instance2 instance2.set_signal_handler(move |signum, siginfo, _| {
.borrow_mut()
.set_signal_handler(move |signum, siginfo, _| {
handle_sigsegv(base1, length1, signum, siginfo) handle_sigsegv(base1, length1, signum, siginfo)
}); });