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:
@@ -54,7 +54,7 @@ fn main() -> anyhow::Result<()> {
|
||||
|
||||
// Invoke `gcd` export
|
||||
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);
|
||||
Ok(())
|
||||
|
||||
@@ -41,15 +41,15 @@ fn main() -> Result<()> {
|
||||
// `HelloCallback` type and its associated implementation of `Callback.
|
||||
println!("Creating callback...");
|
||||
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
|
||||
// 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.
|
||||
println!("Instantiating module...");
|
||||
let imports = vec![hello_func.into()];
|
||||
let instance = Instance::new(&store, &module, imports.as_slice())
|
||||
.context("> Error instantiating module!")?;
|
||||
let instance =
|
||||
Instance::new(&store, &module, &imports).context("> Error instantiating module!")?;
|
||||
|
||||
// Next we poke around a bit to extract the `run` function from the module.
|
||||
println!("Extracting export...");
|
||||
@@ -59,7 +59,7 @@ fn main() -> Result<()> {
|
||||
|
||||
// And last but not least we can call it!
|
||||
println!("Calling export...");
|
||||
run_func.borrow().call(&[])?;
|
||||
run_func.call(&[])?;
|
||||
|
||||
println!("Done.");
|
||||
Ok(())
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use anyhow::{bail, ensure, Context as _, Error};
|
||||
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 {
|
||||
bail!("> Error accessing memory export {}!", i);
|
||||
}
|
||||
@@ -13,7 +13,7 @@ fn get_export_memory(exports: &[Extern], i: usize) -> Result<HostRef<Memory>, Er
|
||||
.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 {
|
||||
bail!("> Error accessing function export {}!", i);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ macro_rules! check {
|
||||
|
||||
macro_rules! check_ok {
|
||||
($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");
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ macro_rules! check_ok {
|
||||
|
||||
macro_rules! check_trap {
|
||||
($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");
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ macro_rules! check_trap {
|
||||
|
||||
macro_rules! call {
|
||||
($func:expr, $($p:expr),*) => {
|
||||
match $func.borrow().call(&[$($p.into()),*]) {
|
||||
match $func.call(&[$($p.into()),*]) {
|
||||
Ok(result) => {
|
||||
let result: i32 = result[0].unwrap_i32();
|
||||
result
|
||||
@@ -101,16 +101,13 @@ fn main() -> Result<(), Error> {
|
||||
let load_func = get_export_func(&exports, 2)?;
|
||||
let store_func = get_export_func(&exports, 3)?;
|
||||
|
||||
// Try cloning.
|
||||
check!(memory.clone().ptr_eq(&memory), true);
|
||||
|
||||
// Check initial memory.
|
||||
println!("Checking memory...");
|
||||
check!(memory.borrow().size(), 2u32);
|
||||
check!(memory.borrow().data_size(), 0x20000usize);
|
||||
check!(unsafe { memory.borrow().data()[0] }, 0);
|
||||
check!(unsafe { memory.borrow().data()[0x1000] }, 1);
|
||||
check!(unsafe { memory.borrow().data()[0x1003] }, 4);
|
||||
check!(memory.size(), 2u32);
|
||||
check!(memory.data_size(), 0x20000usize);
|
||||
check!(unsafe { memory.data()[0] }, 0);
|
||||
check!(unsafe { memory.data()[0x1000] }, 1);
|
||||
check!(unsafe { memory.data()[0x1003] }, 4);
|
||||
|
||||
check!(call!(size_func,), 2);
|
||||
check!(call!(load_func, 0), 0);
|
||||
@@ -122,36 +119,36 @@ fn main() -> Result<(), Error> {
|
||||
// Mutate memory.
|
||||
println!("Mutating memory...");
|
||||
unsafe {
|
||||
memory.borrow_mut().data()[0x1003] = 5;
|
||||
memory.data()[0x1003] = 5;
|
||||
}
|
||||
|
||||
check_ok!(store_func, 0x1002, 6);
|
||||
check_trap!(store_func, 0x20000, 0);
|
||||
|
||||
check!(unsafe { memory.borrow().data()[0x1002] }, 6);
|
||||
check!(unsafe { memory.borrow().data()[0x1003] }, 5);
|
||||
check!(unsafe { memory.data()[0x1002] }, 6);
|
||||
check!(unsafe { memory.data()[0x1003] }, 5);
|
||||
check!(call!(load_func, 0x1002), 6);
|
||||
check!(call!(load_func, 0x1003), 5);
|
||||
|
||||
// Grow memory.
|
||||
println!("Growing memory...");
|
||||
check!(memory.borrow_mut().grow(1), true);
|
||||
check!(memory.borrow().size(), 3u32);
|
||||
check!(memory.borrow().data_size(), 0x30000usize);
|
||||
check!(memory.grow(1), true);
|
||||
check!(memory.size(), 3u32);
|
||||
check!(memory.data_size(), 0x30000usize);
|
||||
|
||||
check!(call!(load_func, 0x20000), 0);
|
||||
check_ok!(store_func, 0x20000, 0);
|
||||
check_trap!(load_func, 0x30000);
|
||||
check_trap!(store_func, 0x30000, 0);
|
||||
|
||||
check!(memory.borrow_mut().grow(1), false);
|
||||
check!(memory.borrow_mut().grow(0), true);
|
||||
check!(memory.grow(1), false);
|
||||
check!(memory.grow(0), true);
|
||||
|
||||
// Create stand-alone memory.
|
||||
// TODO(wasm+): Once Wasm allows multiple memories, turn this into import.
|
||||
println!("Creating stand-alone memory...");
|
||||
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.grow(1), false);
|
||||
check!(memory2.grow(0), true);
|
||||
|
||||
@@ -62,7 +62,7 @@ fn main() -> Result<()> {
|
||||
Box::new([ValType::I32, ValType::I64]),
|
||||
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.
|
||||
println!("Instantiating module...");
|
||||
@@ -83,7 +83,6 @@ fn main() -> Result<()> {
|
||||
println!("Calling export \"g\"...");
|
||||
let args = vec![Val::I32(1), Val::I64(3)];
|
||||
let results = g
|
||||
.borrow()
|
||||
.call(&args)
|
||||
.map_err(|e| format_err!("> Error calling g! {:?}", e))?;
|
||||
|
||||
@@ -108,7 +107,6 @@ fn main() -> Result<()> {
|
||||
Val::I64(9),
|
||||
];
|
||||
let results = round_trip_many
|
||||
.borrow()
|
||||
.call(&args)
|
||||
.map_err(|e| format_err!("> Error calling round_trip_many! {:?}", e))?;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ use wasmtime_runtime::Export;
|
||||
/// WebAssembly.
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use wasmtime::{HostRef, Val};
|
||||
/// use wasmtime::Val;
|
||||
///
|
||||
/// struct TimesTwo;
|
||||
///
|
||||
@@ -54,9 +54,8 @@ use wasmtime_runtime::Export;
|
||||
/// );
|
||||
///
|
||||
/// // Build a reference to the "times_two" function that can be used.
|
||||
/// let times_two_function = HostRef::new(
|
||||
/// wasmtime::Func::new(&store, times_two_type, std::rc::Rc::new(TimesTwo))
|
||||
/// );
|
||||
/// let times_two_function =
|
||||
/// wasmtime::Func::new(&store, times_two_type, std::rc::Rc::new(TimesTwo));
|
||||
///
|
||||
/// // Create module instance that imports our function
|
||||
/// 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.
|
||||
/// let original = 5i32;
|
||||
/// let results = run_function
|
||||
/// .borrow()
|
||||
/// .call(&[original.into()])
|
||||
/// .map_err(|trap| trap.to_string())?;
|
||||
///
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable};
|
||||
use crate::r#ref::{AnyRef, HostRef};
|
||||
use crate::r#ref::AnyRef;
|
||||
use crate::runtime::Store;
|
||||
use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export};
|
||||
use crate::trap::Trap;
|
||||
@@ -15,53 +15,53 @@ use wasmtime_runtime::InstanceHandle;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Extern {
|
||||
Func(HostRef<Func>),
|
||||
Global(HostRef<Global>),
|
||||
Table(HostRef<Table>),
|
||||
Memory(HostRef<Memory>),
|
||||
Func(Func),
|
||||
Global(Global),
|
||||
Table(Table),
|
||||
Memory(Memory),
|
||||
}
|
||||
|
||||
impl Extern {
|
||||
pub fn func(&self) -> Option<&HostRef<Func>> {
|
||||
pub fn func(&self) -> Option<&Func> {
|
||||
match self {
|
||||
Extern::Func(func) => Some(func),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn global(&self) -> Option<&HostRef<Global>> {
|
||||
pub fn global(&self) -> Option<&Global> {
|
||||
match self {
|
||||
Extern::Global(global) => Some(global),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn table(&self) -> Option<&HostRef<Table>> {
|
||||
pub fn table(&self) -> Option<&Table> {
|
||||
match self {
|
||||
Extern::Table(table) => Some(table),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn memory(&self) -> Option<&HostRef<Memory>> {
|
||||
pub fn memory(&self) -> Option<&Memory> {
|
||||
match self {
|
||||
Extern::Memory(memory) => Some(memory),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> ExternType {
|
||||
pub fn ty(&self) -> ExternType {
|
||||
match self {
|
||||
Extern::Func(ft) => ExternType::Func(ft.borrow().r#type().clone()),
|
||||
Extern::Memory(ft) => ExternType::Memory(ft.borrow().r#type().clone()),
|
||||
Extern::Table(tt) => ExternType::Table(tt.borrow().r#type().clone()),
|
||||
Extern::Global(gt) => ExternType::Global(gt.borrow().r#type().clone()),
|
||||
Extern::Func(ft) => ExternType::Func(ft.ty().clone()),
|
||||
Extern::Memory(ft) => ExternType::Memory(ft.ty().clone()),
|
||||
Extern::Table(tt) => ExternType::Table(tt.ty().clone()),
|
||||
Extern::Global(gt) => ExternType::Global(gt.ty().clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_wasmtime_export(&self) -> wasmtime_runtime::Export {
|
||||
match self {
|
||||
Extern::Func(f) => f.borrow().wasmtime_export().clone(),
|
||||
Extern::Global(g) => g.borrow().wasmtime_export().clone(),
|
||||
Extern::Memory(m) => m.borrow().wasmtime_export().clone(),
|
||||
Extern::Table(t) => t.borrow().wasmtime_export().clone(),
|
||||
Extern::Func(f) => f.wasmtime_export().clone(),
|
||||
Extern::Global(g) => g.wasmtime_export().clone(),
|
||||
Extern::Memory(m) => m.wasmtime_export().clone(),
|
||||
Extern::Table(t) => t.wasmtime_export().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,50 +71,51 @@ impl Extern {
|
||||
export: wasmtime_runtime::Export,
|
||||
) -> Extern {
|
||||
match export {
|
||||
wasmtime_runtime::Export::Function { .. } => Extern::Func(HostRef::new(
|
||||
Func::from_wasmtime_function(export, store, instance_handle),
|
||||
)),
|
||||
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(HostRef::new(
|
||||
Memory::from_wasmtime_memory(export, store, instance_handle),
|
||||
)),
|
||||
wasmtime_runtime::Export::Global { .. } => {
|
||||
Extern::Global(HostRef::new(Global::from_wasmtime_global(export, store)))
|
||||
wasmtime_runtime::Export::Function { .. } => {
|
||||
Extern::Func(Func::from_wasmtime_function(export, store, instance_handle))
|
||||
}
|
||||
wasmtime_runtime::Export::Memory { .. } => {
|
||||
Extern::Memory(Memory::from_wasmtime_memory(export, store, instance_handle))
|
||||
}
|
||||
wasmtime_runtime::Export::Global { .. } => {
|
||||
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 {
|
||||
fn from(r: HostRef<Func>) -> Self {
|
||||
impl From<Func> for Extern {
|
||||
fn from(r: Func) -> Self {
|
||||
Extern::Func(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HostRef<Global>> for Extern {
|
||||
fn from(r: HostRef<Global>) -> Self {
|
||||
impl From<Global> for Extern {
|
||||
fn from(r: Global) -> Self {
|
||||
Extern::Global(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HostRef<Memory>> for Extern {
|
||||
fn from(r: HostRef<Memory>) -> Self {
|
||||
impl From<Memory> for Extern {
|
||||
fn from(r: Memory) -> Self {
|
||||
Extern::Memory(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HostRef<Table>> for Extern {
|
||||
fn from(r: HostRef<Table>) -> Self {
|
||||
impl From<Table> for Extern {
|
||||
fn from(r: Table) -> Self {
|
||||
Extern::Table(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Func {
|
||||
_store: Store,
|
||||
callable: Rc<dyn WrappedCallable + 'static>,
|
||||
r#type: FuncType,
|
||||
ty: FuncType,
|
||||
}
|
||||
|
||||
impl Func {
|
||||
@@ -125,26 +126,26 @@ impl Func {
|
||||
|
||||
fn from_wrapped(
|
||||
store: &Store,
|
||||
r#type: FuncType,
|
||||
ty: FuncType,
|
||||
callable: Rc<dyn WrappedCallable + 'static>,
|
||||
) -> Func {
|
||||
Func {
|
||||
_store: store.clone(),
|
||||
callable,
|
||||
r#type,
|
||||
ty,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> &FuncType {
|
||||
&self.r#type
|
||||
pub fn ty(&self) -> &FuncType {
|
||||
&self.ty
|
||||
}
|
||||
|
||||
pub fn param_arity(&self) -> usize {
|
||||
self.r#type.params().len()
|
||||
self.ty.params().len()
|
||||
}
|
||||
|
||||
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> {
|
||||
@@ -178,32 +179,39 @@ impl fmt::Debug for Func {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Global {
|
||||
inner: Rc<GlobalInner>,
|
||||
}
|
||||
|
||||
struct GlobalInner {
|
||||
_store: Store,
|
||||
r#type: GlobalType,
|
||||
ty: GlobalType,
|
||||
wasmtime_export: wasmtime_runtime::Export,
|
||||
#[allow(dead_code)]
|
||||
wasmtime_state: Option<crate::trampoline::GlobalState>,
|
||||
}
|
||||
|
||||
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) =
|
||||
generate_global_export(&r#type, val).expect("generated global");
|
||||
generate_global_export(&ty, val).expect("generated global");
|
||||
Global {
|
||||
inner: Rc::new(GlobalInner {
|
||||
_store: store.clone(),
|
||||
r#type,
|
||||
ty,
|
||||
wasmtime_export,
|
||||
wasmtime_state: Some(wasmtime_state),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> &GlobalType {
|
||||
&self.r#type
|
||||
pub fn ty(&self) -> &GlobalType {
|
||||
&self.inner.ty
|
||||
}
|
||||
|
||||
fn wasmtime_global_definition(&self) -> *mut wasmtime_runtime::VMGlobalDefinition {
|
||||
match self.wasmtime_export {
|
||||
match self.inner.wasmtime_export {
|
||||
wasmtime_runtime::Export::Global { definition, .. } => definition,
|
||||
_ => panic!("global definition not found"),
|
||||
}
|
||||
@@ -212,22 +220,22 @@ impl Global {
|
||||
pub fn get(&self) -> Val {
|
||||
let definition = unsafe { &mut *self.wasmtime_global_definition() };
|
||||
unsafe {
|
||||
match self.r#type().content() {
|
||||
match self.ty().content() {
|
||||
ValType::I32 => Val::from(*definition.as_i32()),
|
||||
ValType::I64 => Val::from(*definition.as_i64()),
|
||||
ValType::F32 => Val::F32(*definition.as_u32()),
|
||||
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) {
|
||||
if val.r#type() != *self.r#type().content() {
|
||||
pub fn set(&self, val: Val) {
|
||||
if val.ty() != *self.ty().content() {
|
||||
panic!(
|
||||
"global of type {:?} cannot be set to {:?}",
|
||||
self.r#type().content(),
|
||||
val.r#type()
|
||||
self.ty().content(),
|
||||
val.ty()
|
||||
);
|
||||
}
|
||||
let definition = unsafe { &mut *self.wasmtime_global_definition() };
|
||||
@@ -237,13 +245,13 @@ impl Global {
|
||||
Val::I64(i) => *definition.as_i64_mut() = i,
|
||||
Val::F32(f) => *definition.as_u32_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 {
|
||||
&self.wasmtime_export
|
||||
&self.inner.wasmtime_export
|
||||
}
|
||||
|
||||
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);
|
||||
Global {
|
||||
inner: Rc::new(GlobalInner {
|
||||
_store: store.clone(),
|
||||
r#type: ty,
|
||||
ty: ty,
|
||||
wasmtime_export: export,
|
||||
wasmtime_state: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Table {
|
||||
store: Store,
|
||||
r#type: TableType,
|
||||
ty: TableType,
|
||||
wasmtime_handle: InstanceHandle,
|
||||
wasmtime_export: wasmtime_runtime::Export,
|
||||
}
|
||||
@@ -299,13 +310,13 @@ fn set_table_item(
|
||||
}
|
||||
|
||||
impl Table {
|
||||
pub fn new(store: &Store, r#type: TableType, init: Val) -> Table {
|
||||
match r#type.element() {
|
||||
pub fn new(store: &Store, ty: TableType, init: Val) -> Table {
|
||||
match ty.element() {
|
||||
ValType::FuncRef => (),
|
||||
_ => panic!("table is not for funcref"),
|
||||
}
|
||||
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.
|
||||
match wasmtime_export {
|
||||
@@ -323,14 +334,14 @@ impl Table {
|
||||
|
||||
Table {
|
||||
store: store.clone(),
|
||||
r#type,
|
||||
ty,
|
||||
wasmtime_handle,
|
||||
wasmtime_export,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> &TableType {
|
||||
&self.r#type
|
||||
pub fn ty(&self) -> &TableType {
|
||||
&self.ty
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
for i in 0..delta {
|
||||
let i = len - (delta - i);
|
||||
@@ -395,34 +406,35 @@ impl Table {
|
||||
let ty = TableType::from_wasmtime_table(&table.table);
|
||||
Table {
|
||||
store: store.clone(),
|
||||
r#type: ty,
|
||||
ty: ty,
|
||||
wasmtime_handle: instance_handle,
|
||||
wasmtime_export: export,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Memory {
|
||||
_store: Store,
|
||||
r#type: MemoryType,
|
||||
ty: MemoryType,
|
||||
wasmtime_handle: InstanceHandle,
|
||||
wasmtime_export: wasmtime_runtime::Export,
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
pub fn new(store: &Store, r#type: MemoryType) -> Memory {
|
||||
pub fn new(store: &Store, ty: MemoryType) -> Memory {
|
||||
let (wasmtime_handle, wasmtime_export) =
|
||||
generate_memory_export(&r#type).expect("generated memory");
|
||||
generate_memory_export(&ty).expect("generated memory");
|
||||
Memory {
|
||||
_store: store.clone(),
|
||||
r#type,
|
||||
ty,
|
||||
wasmtime_handle,
|
||||
wasmtime_export,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> &MemoryType {
|
||||
&self.r#type
|
||||
pub fn ty(&self) -> &MemoryType {
|
||||
&self.ty
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
pub fn grow(&mut self, delta: u32) -> bool {
|
||||
pub fn grow(&self, delta: u32) -> bool {
|
||||
match self.wasmtime_export {
|
||||
wasmtime_runtime::Export::Memory { definition, .. } => {
|
||||
let definition = unsafe { &(*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"),
|
||||
}
|
||||
@@ -481,7 +496,7 @@ impl Memory {
|
||||
let ty = MemoryType::from_wasmtime_memory(&memory.memory);
|
||||
Memory {
|
||||
_store: store.clone(),
|
||||
r#type: ty,
|
||||
ty: ty,
|
||||
wasmtime_handle: instance_handle,
|
||||
wasmtime_export: export,
|
||||
}
|
||||
|
||||
@@ -167,29 +167,29 @@ cfg_if::cfg_if! {
|
||||
impl Instance {
|
||||
/// The signal handler must be
|
||||
/// [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
|
||||
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")] {
|
||||
impl Instance {
|
||||
pub fn set_signal_handler<H>(&mut self, handler: H)
|
||||
pub fn set_signal_handler<H>(&self, handler: H)
|
||||
where
|
||||
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")] {
|
||||
impl Instance {
|
||||
pub fn set_signal_handler<H>(&mut self, handler: H)
|
||||
pub fn set_signal_handler<H>(&self, handler: H)
|
||||
where
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::externals::Func;
|
||||
use crate::r#ref::{AnyRef, HostRef};
|
||||
use crate::r#ref::AnyRef;
|
||||
use crate::runtime::Store;
|
||||
use crate::types::ValType;
|
||||
use std::ptr;
|
||||
@@ -34,7 +34,7 @@ pub enum Val {
|
||||
AnyRef(AnyRef),
|
||||
|
||||
/// A first-class reference to a WebAssembly function.
|
||||
FuncRef(HostRef<Func>),
|
||||
FuncRef(Func),
|
||||
|
||||
/// A 128-bit number
|
||||
V128(u128),
|
||||
@@ -71,7 +71,7 @@ impl Val {
|
||||
}
|
||||
|
||||
/// Returns the corresponding [`ValType`] for this `Val`.
|
||||
pub fn r#type(&self) -> ValType {
|
||||
pub fn ty(&self) -> ValType {
|
||||
match self {
|
||||
Val::I32(_) => ValType::I32,
|
||||
Val::I64(_) => ValType::I64,
|
||||
@@ -111,7 +111,7 @@ impl Val {
|
||||
(I64(i64) i64 unwrap_i64 *e)
|
||||
(F32(f32) f32 unwrap_f32 f32::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)
|
||||
}
|
||||
|
||||
@@ -122,7 +122,6 @@ impl Val {
|
||||
pub fn anyref(&self) -> Option<AnyRef> {
|
||||
match self {
|
||||
Val::AnyRef(e) => Some(e.clone()),
|
||||
Val::FuncRef(e) => Some(e.anyref()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -164,21 +163,12 @@ impl From<f64> for Val {
|
||||
|
||||
impl From<AnyRef> for 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)
|
||||
}
|
||||
}
|
||||
_ => unimplemented!("AnyRef::Other"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HostRef<Func>> for Val {
|
||||
fn from(val: HostRef<Func>) -> Val {
|
||||
impl From<Func> for Val {
|
||||
fn from(val: Func) -> Val {
|
||||
Val::FuncRef(val)
|
||||
}
|
||||
}
|
||||
@@ -206,7 +196,6 @@ pub(crate) fn into_checked_anyfunc(
|
||||
vmctx: ptr::null_mut(),
|
||||
},
|
||||
Val::FuncRef(f) => {
|
||||
let f = f.borrow();
|
||||
let (vmctx, func_ptr, signature) = match f.wasmtime_export() {
|
||||
wasmtime_runtime::Export::Function {
|
||||
vmctx,
|
||||
@@ -243,5 +232,5 @@ pub(crate) fn from_checked_anyfunc(
|
||||
vmctx: item.vmctx,
|
||||
};
|
||||
let f = Func::from_wasmtime_function(export, store, instance_handle);
|
||||
Val::FuncRef(HostRef::new(f))
|
||||
Val::FuncRef(f)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use super::{
|
||||
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table,
|
||||
TableType, Trap, Val, ValType,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
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);
|
||||
|
||||
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)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_importtype_t {
|
||||
@@ -312,6 +319,7 @@ declare_vec!(wasm_frame_vec_t, *mut wasm_frame_t);
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_instance_t {
|
||||
instance: HostRef<Instance>,
|
||||
exports_cache: RefCell<Option<Vec<ExternHost>>>,
|
||||
}
|
||||
pub type wasm_message_t = wasm_name_t;
|
||||
#[repr(C)]
|
||||
@@ -336,12 +344,22 @@ pub struct wasm_module_t {
|
||||
pub struct wasm_shared_module_t {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
#[repr(C)]
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_func_t {
|
||||
func: HostRef<Func>,
|
||||
ext: Option<Box<wasm_extern_t>>,
|
||||
ext: 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<
|
||||
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,
|
||||
) -> *mut wasm_trap_t,
|
||||
>;
|
||||
#[repr(C)]
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_global_t {
|
||||
global: HostRef<Global>,
|
||||
ext: Option<Box<wasm_extern_t>>,
|
||||
ext: wasm_extern_t,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_table_t {
|
||||
table: HostRef<Table>,
|
||||
ext: Option<Box<wasm_extern_t>>,
|
||||
}
|
||||
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,
|
||||
|
||||
impl wasm_global_t {
|
||||
fn global(&self) -> &HostRef<Global> {
|
||||
match &self.ext.which {
|
||||
ExternHost::Global(g) => g,
|
||||
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum wasm_extern_t_type_cache {
|
||||
Empty,
|
||||
Func(wasm_func_t),
|
||||
Global(wasm_global_t),
|
||||
Memory(wasm_memory_t),
|
||||
Table(wasm_table_t),
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_table_t {
|
||||
ext: wasm_extern_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);
|
||||
@@ -415,16 +460,9 @@ pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t {
|
||||
|
||||
#[no_mangle]
|
||||
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 {
|
||||
(*e).cache = wasm_extern_t_type_cache::Func(wasm_func_t {
|
||||
func: (*e).ext.func().unwrap().clone(),
|
||||
ext: None,
|
||||
});
|
||||
}
|
||||
|
||||
match &mut (*e).cache {
|
||||
wasm_extern_t_type_cache::Func(f) => f,
|
||||
_ => panic!("wasm_extern_as_func"),
|
||||
match &(*e).which {
|
||||
ExternHost::Func(_) => e.cast(),
|
||||
_ => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,17 +473,7 @@ pub unsafe extern "C" fn wasm_extern_vec_delete(v: *mut wasm_extern_vec_t) {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t {
|
||||
if (*f).ext.is_none() {
|
||||
(*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"),
|
||||
}
|
||||
&mut (*f).ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -454,7 +482,7 @@ pub unsafe extern "C" fn wasm_func_call(
|
||||
args: *const wasm_val_t,
|
||||
results: *mut wasm_val_t,
|
||||
) -> *mut wasm_trap_t {
|
||||
let func = (*func).func.borrow();
|
||||
let func = (*func).func().borrow();
|
||||
let mut params = Vec::with_capacity(func.param_arity());
|
||||
for i in 0..func.param_arity() {
|
||||
let val = &(*args.add(i));
|
||||
@@ -606,8 +634,9 @@ pub unsafe extern "C" fn wasm_func_new(
|
||||
let ty = (*ty).functype.clone();
|
||||
let callback = Rc::new(callback);
|
||||
let func = Box::new(wasm_func_t {
|
||||
func: HostRef::new(Func::new(store, ty, callback)),
|
||||
ext: None,
|
||||
ext: wasm_extern_t {
|
||||
which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))),
|
||||
},
|
||||
});
|
||||
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());
|
||||
for i in 0..(*module).imports.len() {
|
||||
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();
|
||||
match Instance::new(store, module, &externs) {
|
||||
Ok(instance) => {
|
||||
let instance = Box::new(wasm_instance_t {
|
||||
instance: HostRef::new(instance),
|
||||
exports_cache: RefCell::new(None),
|
||||
});
|
||||
if !result.is_null() {
|
||||
(*result) = ptr::null_mut();
|
||||
@@ -694,14 +729,23 @@ pub unsafe extern "C" fn wasm_instance_exports(
|
||||
instance: *const wasm_instance_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 exports = instance.exports();
|
||||
let mut buffer = Vec::with_capacity(exports.len());
|
||||
for e in exports.iter() {
|
||||
let ext = Box::new(wasm_extern_t {
|
||||
ext: e.clone(),
|
||||
cache: wasm_extern_t_type_cache::Empty,
|
||||
instance
|
||||
.exports()
|
||||
.iter()
|
||||
.map(|e| match e {
|
||||
Extern::Func(f) => ExternHost::Func(HostRef::new(f.clone())),
|
||||
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));
|
||||
}
|
||||
(*out).set_buffer(buffer);
|
||||
@@ -817,8 +861,9 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
|
||||
finalizer,
|
||||
});
|
||||
let func = Box::new(wasm_func_t {
|
||||
func: HostRef::new(Func::new(store, ty, callback)),
|
||||
ext: None,
|
||||
ext: wasm_extern_t {
|
||||
which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))),
|
||||
},
|
||||
});
|
||||
Box::into_raw(func)
|
||||
}
|
||||
@@ -1012,24 +1057,25 @@ pub unsafe extern "C" fn wasm_exporttype_vec_delete(et: *mut wasm_exporttype_vec
|
||||
(*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]
|
||||
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]
|
||||
pub unsafe extern "C" fn wasm_extern_type(e: *const wasm_extern_t) -> *mut 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,
|
||||
});
|
||||
Box::into_raw(et)
|
||||
@@ -1120,17 +1166,22 @@ pub unsafe extern "C" fn wasm_externtype_delete(et: *mut wasm_externtype_t) {
|
||||
|
||||
#[no_mangle]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
@@ -1279,32 +1330,15 @@ pub unsafe extern "C" fn wasm_valtype_kind(vt: *const wasm_valtype_t) -> wasm_va
|
||||
|
||||
#[no_mangle]
|
||||
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 {
|
||||
(*e).cache = wasm_extern_t_type_cache::Global(wasm_global_t {
|
||||
global: (*e).ext.global().unwrap().clone(),
|
||||
ext: None,
|
||||
});
|
||||
}
|
||||
|
||||
match &mut (*e).cache {
|
||||
wasm_extern_t_type_cache::Global(g) => g,
|
||||
_ => panic!("wasm_extern_as_global"),
|
||||
match &(*e).which {
|
||||
ExternHost::Global(_) => e.cast(),
|
||||
_ => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
|
||||
if (*g).ext.is_none() {
|
||||
(*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"),
|
||||
}
|
||||
&mut (*g).ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1322,7 +1356,7 @@ pub unsafe extern "C" fn wasm_global_same(
|
||||
g1: *const wasm_global_t,
|
||||
g2: *const wasm_global_t,
|
||||
) -> bool {
|
||||
(*g1).global.ptr_eq(&(*g2).global)
|
||||
(*g1).global().ptr_eq(&(*g2).global())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1336,18 +1370,22 @@ pub unsafe extern "C" fn wasm_global_new(
|
||||
(*gt).globaltype.clone(),
|
||||
(*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)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
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]
|
||||
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]
|
||||
@@ -1377,32 +1415,15 @@ pub unsafe extern "C" fn wasm_globaltype_new(
|
||||
|
||||
#[no_mangle]
|
||||
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 {
|
||||
(*e).cache = wasm_extern_t_type_cache::Memory(wasm_memory_t {
|
||||
memory: (*e).ext.memory().unwrap().clone(),
|
||||
ext: None,
|
||||
});
|
||||
}
|
||||
|
||||
match &mut (*e).cache {
|
||||
wasm_extern_t_type_cache::Memory(m) => m,
|
||||
_ => panic!("wasm_extern_as_memory"),
|
||||
match &(*e).which {
|
||||
ExternHost::Memory(_) => e.cast(),
|
||||
_ => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memory_as_extern(m: *mut wasm_memory_t) -> *mut wasm_extern_t {
|
||||
if (*m).ext.is_none() {
|
||||
(*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"),
|
||||
}
|
||||
&mut (*m).ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1420,22 +1441,22 @@ pub unsafe extern "C" fn wasm_memory_same(
|
||||
m1: *const wasm_memory_t,
|
||||
m2: *const wasm_memory_t,
|
||||
) -> bool {
|
||||
(*m1).memory.ptr_eq(&(*m2).memory)
|
||||
(*m1).memory().ptr_eq(&(*m2).memory())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
@@ -1443,7 +1464,7 @@ pub unsafe extern "C" fn wasm_memory_grow(
|
||||
m: *mut wasm_memory_t,
|
||||
delta: wasm_memory_pages_t,
|
||||
) -> bool {
|
||||
(*m).memory.borrow_mut().grow(delta)
|
||||
(*m).memory().borrow().grow(delta)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1455,7 +1476,11 @@ pub unsafe extern "C" fn wasm_memory_new(
|
||||
&(*store).store.borrow(),
|
||||
(*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)
|
||||
}
|
||||
|
||||
@@ -1483,37 +1508,20 @@ pub unsafe extern "C" fn wasm_memorytype_new(
|
||||
|
||||
#[no_mangle]
|
||||
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 {
|
||||
(*e).cache = wasm_extern_t_type_cache::Table(wasm_table_t {
|
||||
table: (*e).ext.table().unwrap().clone(),
|
||||
ext: None,
|
||||
});
|
||||
}
|
||||
|
||||
match &mut (*e).cache {
|
||||
wasm_extern_t_type_cache::Table(t) => t,
|
||||
_ => panic!("wasm_extern_as_table"),
|
||||
match &(*e).which {
|
||||
ExternHost::Table(_) => e.cast(),
|
||||
_ => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_table_as_extern(t: *mut wasm_table_t) -> *mut wasm_extern_t {
|
||||
if (*t).ext.is_none() {
|
||||
(*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"),
|
||||
}
|
||||
&mut (*t).ext
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
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 });
|
||||
Box::into_raw(f)
|
||||
}
|
||||
@@ -1547,12 +1555,13 @@ pub unsafe extern "C" fn wasm_table_new(
|
||||
Val::AnyRef(AnyRef::Null)
|
||||
};
|
||||
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(),
|
||||
(*tt).tabletype.clone(),
|
||||
init,
|
||||
)),
|
||||
ext: None,
|
||||
))),
|
||||
},
|
||||
});
|
||||
Box::into_raw(t)
|
||||
}
|
||||
@@ -1582,7 +1591,7 @@ pub unsafe extern "C" fn wasm_table_get(
|
||||
t: *const wasm_table_t,
|
||||
index: wasm_table_size_t,
|
||||
) -> *mut wasm_ref_t {
|
||||
let val = (*t).table.borrow().get(index);
|
||||
let val = (*t).table().borrow().get(index);
|
||||
into_funcref(val)
|
||||
}
|
||||
|
||||
@@ -1593,12 +1602,12 @@ pub unsafe extern "C" fn wasm_table_set(
|
||||
r: *mut wasm_ref_t,
|
||||
) -> bool {
|
||||
let val = from_funcref(r);
|
||||
(*t).table.borrow().set(index, val)
|
||||
(*t).table().borrow().set(index, val)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
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]
|
||||
@@ -1608,12 +1617,12 @@ pub unsafe extern "C" fn wasm_table_grow(
|
||||
init: *mut wasm_ref_t,
|
||||
) -> bool {
|
||||
let init = from_funcref(init);
|
||||
(*t).table.borrow_mut().grow(delta, init)
|
||||
(*t).table().borrow().grow(delta, init)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
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]
|
||||
|
||||
@@ -42,23 +42,23 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> {
|
||||
let module = Module::new(&store, &wasm)?;
|
||||
|
||||
let imports = [
|
||||
HostRef::new(Func::new(
|
||||
Func::new(
|
||||
&store,
|
||||
FuncType::new(Box::new([]), Box::new([ValType::I32])),
|
||||
Rc::new(Ret1),
|
||||
))
|
||||
)
|
||||
.into(),
|
||||
HostRef::new(Func::new(
|
||||
Func::new(
|
||||
&store,
|
||||
FuncType::new(Box::new([]), Box::new([ValType::F32])),
|
||||
Rc::new(Ret2),
|
||||
))
|
||||
)
|
||||
.into(),
|
||||
];
|
||||
let instance = Instance::new(&store, &module, &imports)?;
|
||||
|
||||
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);
|
||||
match results[0] {
|
||||
Val::I32(n) => assert_eq!(n, 3),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use wasmtime::*;
|
||||
|
||||
@@ -16,7 +16,7 @@ fn test_import_calling_export() {
|
||||
"#;
|
||||
|
||||
struct Callback {
|
||||
pub other: RefCell<Option<HostRef<Func>>>,
|
||||
pub other: RefCell<Option<Func>>,
|
||||
}
|
||||
|
||||
impl Callable for Callback {
|
||||
@@ -25,7 +25,6 @@ fn test_import_calling_export() {
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.expect("expected a function ref")
|
||||
.borrow()
|
||||
.call(&[])
|
||||
.expect("expected function not to trap");
|
||||
Ok(())
|
||||
@@ -40,18 +39,17 @@ fn test_import_calling_export() {
|
||||
other: RefCell::new(None),
|
||||
});
|
||||
|
||||
let callback_func = HostRef::new(Func::new(
|
||||
let callback_func = Func::new(
|
||||
&store,
|
||||
FuncType::new(Box::new([]), Box::new([])),
|
||||
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());
|
||||
|
||||
let run_func = exports[0]
|
||||
@@ -65,8 +63,5 @@ fn test_import_calling_export() {
|
||||
.clone(),
|
||||
);
|
||||
|
||||
run_func
|
||||
.borrow()
|
||||
.call(&[])
|
||||
.expect("expected function not to trap");
|
||||
run_func.call(&[]).expect("expected function not to trap");
|
||||
}
|
||||
|
||||
@@ -26,20 +26,16 @@ fn test_trap_return() -> Result<(), String> {
|
||||
let module =
|
||||
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?;
|
||||
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 instance = Instance::new(&store, &module, imports.as_slice())
|
||||
let instance = Instance::new(&store, &module, &imports)
|
||||
.map_err(|e| format!("failed to instantiate module: {:?}", e))?;
|
||||
let run_func = instance.exports()[0]
|
||||
.func()
|
||||
.expect("expected function export");
|
||||
|
||||
let e = run_func
|
||||
.borrow()
|
||||
.call(&[])
|
||||
.err()
|
||||
.expect("error calling function");
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
|
||||
assert_eq!(e.message(), "test 123");
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
|
||||
let mut engine: Option<Engine> = None;
|
||||
let mut store: Option<Store> = None;
|
||||
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 {
|
||||
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
|
||||
// initialize into it.
|
||||
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 instance = instance.borrow();
|
||||
instance
|
||||
let funcs = instance
|
||||
.exports()
|
||||
.iter()
|
||||
.filter_map(|e| match e {
|
||||
Extern::Func(f) => Some(f.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if funcs.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let nth = nth % funcs.len();
|
||||
let f = funcs[nth].borrow();
|
||||
let ty = f.r#type();
|
||||
let f = &funcs[nth];
|
||||
let ty = f.ty();
|
||||
let params = match ty
|
||||
.params()
|
||||
.iter()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use std::rc::Rc;
|
||||
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,
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
for imp in import_tys {
|
||||
imports.push(match imp.ty() {
|
||||
ExternType::Func(func_ty) => {
|
||||
Extern::Func(HostRef::new(DummyFunc::new(&store, func_ty.clone())))
|
||||
}
|
||||
ExternType::Func(func_ty) => Extern::Func(DummyFunc::new(&store, func_ty.clone())),
|
||||
ExternType::Global(global_ty) => {
|
||||
Extern::Global(HostRef::new(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())))
|
||||
Extern::Global(dummy_global(&store, global_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)
|
||||
|
||||
@@ -125,18 +125,17 @@ impl ModuleData {
|
||||
/// wasm interface types.
|
||||
pub fn invoke_export(
|
||||
&self,
|
||||
instance: &wasmtime::HostRef<wasmtime::Instance>,
|
||||
instance: &wasmtime::Instance,
|
||||
export: &str,
|
||||
args: &[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 incoming = binding.param_bindings()?;
|
||||
let outgoing = binding.result_bindings()?;
|
||||
|
||||
let f = instance
|
||||
.borrow()
|
||||
.find_export_by_name(export)
|
||||
.ok_or_else(|| format_err!("failed to find export `{}`", export))?
|
||||
.func()
|
||||
@@ -148,7 +147,7 @@ impl ModuleData {
|
||||
.into_iter()
|
||||
.map(|rv| rv.into())
|
||||
.collect::<Vec<_>>();
|
||||
let wasm_results = match f.borrow().call(&wasm_args) {
|
||||
let wasm_results = match f.call(&wasm_args) {
|
||||
Ok(values) => values
|
||||
.to_vec()
|
||||
.into_iter()
|
||||
@@ -322,20 +321,19 @@ trait TranslateContext {
|
||||
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 {
|
||||
fn invoke_alloc(&mut self, alloc_func_name: &str, len: i32) -> Result<i32> {
|
||||
let alloc = self
|
||||
.0
|
||||
.borrow()
|
||||
.find_export_by_name(alloc_func_name)
|
||||
.ok_or_else(|| format_err!("failed to find alloc function `{}`", alloc_func_name))?
|
||||
.func()
|
||||
.ok_or_else(|| format_err!("`{}` is not a (alloc) function", alloc_func_name))?
|
||||
.clone();
|
||||
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,
|
||||
Err(trap) => bail!("trapped: {:?}", trap),
|
||||
};
|
||||
@@ -350,14 +348,13 @@ impl TranslateContext for InstanceTranslateContext {
|
||||
unsafe fn get_memory(&mut self) -> Result<&mut [u8]> {
|
||||
let memory = self
|
||||
.0
|
||||
.borrow()
|
||||
.find_export_by_name("memory")
|
||||
.ok_or_else(|| format_err!("failed to find `memory` export"))?
|
||||
.memory()
|
||||
.ok_or_else(|| format_err!("`memory` is not a memory"))?
|
||||
.clone();
|
||||
let ptr = memory.borrow().data_ptr();
|
||||
let len = memory.borrow().data_size();
|
||||
let ptr = memory.data_ptr();
|
||||
let len = memory.data_size();
|
||||
Ok(std::slice::from_raw_parts_mut(ptr, len))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,17 +10,16 @@ use wasmtime_interface_types::ModuleData;
|
||||
// TODO support non-export functions
|
||||
#[pyclass]
|
||||
pub struct Function {
|
||||
pub instance: wasmtime::HostRef<wasmtime::Instance>,
|
||||
pub instance: wasmtime::Instance,
|
||||
pub export_name: String,
|
||||
pub args_types: Vec<wasmtime::ValType>,
|
||||
pub data: Rc<ModuleData>,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn func(&self) -> wasmtime::HostRef<wasmtime::Func> {
|
||||
pub fn func(&self) -> wasmtime::Func {
|
||||
let e = self
|
||||
.instance
|
||||
.borrow()
|
||||
.find_export_by_name(&self.export_name)
|
||||
.expect("named export")
|
||||
.clone();
|
||||
@@ -125,10 +124,7 @@ impl wasmtime::Callable for WrappedFn {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wrap_into_pyfunction(
|
||||
store: &wasmtime::Store,
|
||||
callable: &PyAny,
|
||||
) -> PyResult<wasmtime::HostRef<wasmtime::Func>> {
|
||||
pub fn wrap_into_pyfunction(store: &wasmtime::Store, callable: &PyAny) -> PyResult<wasmtime::Func> {
|
||||
if !callable.hasattr("__annotations__")? {
|
||||
// TODO support calls without annotations?
|
||||
return Err(PyErr::new::<Exception, _>(
|
||||
@@ -154,6 +150,5 @@ pub fn wrap_into_pyfunction(
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let wrapped = WrappedFn::new(callable.to_object(gil.python()), returns);
|
||||
let f = wasmtime::Func::new(store, ft, Rc::new(wrapped));
|
||||
Ok(wasmtime::HostRef::new(f))
|
||||
Ok(wasmtime::Func::new(store, ft, Rc::new(wrapped)))
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use wasmtime_interface_types::ModuleData;
|
||||
|
||||
#[pyclass]
|
||||
pub struct Instance {
|
||||
pub instance: wasmtime::HostRef<wasmtime::Instance>,
|
||||
pub instance: wasmtime::Instance,
|
||||
pub data: Rc<ModuleData>,
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ impl Instance {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
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() {
|
||||
match e.ty() {
|
||||
wasmtime::ExternType::Func(ft) => {
|
||||
@@ -43,10 +43,7 @@ impl Instance {
|
||||
let f = Py::new(
|
||||
py,
|
||||
Memory {
|
||||
memory: self.instance.borrow().exports()[i]
|
||||
.memory()
|
||||
.unwrap()
|
||||
.clone(),
|
||||
memory: self.instance.exports()[i].memory().unwrap().clone(),
|
||||
},
|
||||
)?;
|
||||
exports.set_item(e.name().to_string(), f)?;
|
||||
|
||||
@@ -122,10 +122,8 @@ pub fn instantiate(
|
||||
}
|
||||
}
|
||||
|
||||
let instance = wasmtime::HostRef::new(
|
||||
wasmtime::Instance::new(&store, &module, &imports)
|
||||
.map_err(|t| PyErr::new::<Exception, _>(format!("instantiated with trap {:?}", t)))?,
|
||||
);
|
||||
let instance = wasmtime::Instance::new(&store, &module, &imports)
|
||||
.map_err(|t| PyErr::new::<Exception, _>(format!("instantiated with trap {:?}", t)))?;
|
||||
|
||||
let module = Py::new(py, Module { module })?;
|
||||
|
||||
|
||||
@@ -10,14 +10,14 @@ use std::ptr;
|
||||
|
||||
#[pyclass]
|
||||
pub struct Memory {
|
||||
pub memory: wasmtime::HostRef<wasmtime::Memory>,
|
||||
pub memory: wasmtime::Memory,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl Memory {
|
||||
#[getter(current)]
|
||||
pub fn current(&self) -> u32 {
|
||||
self.memory.borrow().size()
|
||||
self.memory.size()
|
||||
}
|
||||
|
||||
pub fn grow(&self, _number: u32) -> u32 {
|
||||
@@ -48,8 +48,8 @@ impl PyBufferProtocol for Memory {
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let base = self.memory.borrow().data_ptr();
|
||||
let current_length = self.memory.borrow().data_size();
|
||||
let base = self.memory.data_ptr();
|
||||
let current_length = self.memory.data_size();
|
||||
|
||||
(*view).buf = base as *mut c_void;
|
||||
(*view).len = current_length as isize;
|
||||
|
||||
@@ -34,7 +34,7 @@ fn generate_struct(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
|
||||
let root = root();
|
||||
Ok(quote! {
|
||||
#vis struct #name {
|
||||
instance: #root::wasmtime::HostRef<#root::wasmtime::Instance>,
|
||||
instance: #root::wasmtime::Instance,
|
||||
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> {
|
||||
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};
|
||||
|
||||
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(
|
||||
Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?
|
||||
);
|
||||
let instance =
|
||||
Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?;
|
||||
|
||||
Ok(#name { instance, data })
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{bail, Context};
|
||||
use std::fs::File;
|
||||
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<()> {
|
||||
let store = Store::default();
|
||||
@@ -61,13 +61,12 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
|
||||
})
|
||||
.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 '{}'",
|
||||
bin_name,
|
||||
))?);
|
||||
))?;
|
||||
|
||||
let export = instance
|
||||
.borrow()
|
||||
.find_export_by_name("_start")
|
||||
.context("expected a _start export")?
|
||||
.clone();
|
||||
@@ -75,7 +74,6 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
|
||||
if let Err(trap) = export
|
||||
.func()
|
||||
.context("expected export to be a func")?
|
||||
.borrow()
|
||||
.call(&[])
|
||||
{
|
||||
bail!("trapped: {:?}", trap);
|
||||
|
||||
@@ -31,35 +31,35 @@ pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
|
||||
|
||||
let ty = FuncType::new(Box::new([]), Box::new([]));
|
||||
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 func = wrap(store, ty, |params, _results| {
|
||||
println!("{}: i32", params[0].unwrap_i32());
|
||||
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 func = wrap(store, ty, |params, _results| {
|
||||
println!("{}: i64", params[0].unwrap_i64());
|
||||
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 func = wrap(store, ty, |params, _results| {
|
||||
println!("{}: f32", params[0].unwrap_f32());
|
||||
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 func = wrap(store, ty, |params, _results| {
|
||||
println!("{}: f64", params[0].unwrap_f64());
|
||||
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 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());
|
||||
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 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());
|
||||
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 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 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 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 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 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 memory = Memory::new(store, ty);
|
||||
ret.insert("memory", Extern::Memory(HostRef::new(memory)));
|
||||
ret.insert("memory", Extern::Memory(memory));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ fn runtime_value(v: &wast::Expression<'_>) -> Result<Val> {
|
||||
pub struct WastContext {
|
||||
/// Wast files have a concept of a "current" module, which is the most
|
||||
/// recently defined.
|
||||
current: Option<HostRef<Instance>>,
|
||||
current: Option<Instance>,
|
||||
|
||||
instances: HashMap<String, HostRef<Instance>>,
|
||||
instances: HashMap<String, Instance>,
|
||||
store: Store,
|
||||
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 {
|
||||
Some(name) => self
|
||||
.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 mut imports = Vec::new();
|
||||
for import in module.imports() {
|
||||
@@ -85,7 +85,6 @@ impl WastContext {
|
||||
.get(import.module())
|
||||
.ok_or_else(|| anyhow!("no module named `{}`", import.module()))?;
|
||||
let export = instance
|
||||
.borrow()
|
||||
.find_export_by_name(import.name())
|
||||
.ok_or_else(|| anyhow!("unknown import `{}::{}`", import.name(), import.module()))?
|
||||
.clone();
|
||||
@@ -101,7 +100,7 @@ impl WastContext {
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
Ok(Outcome::Ok(HostRef::new(instance)))
|
||||
Ok(Outcome::Ok(instance))
|
||||
}
|
||||
|
||||
/// Register "spectest" which is used by the spec testsuite.
|
||||
@@ -159,12 +158,11 @@ impl WastContext {
|
||||
) -> Result<Outcome> {
|
||||
let values = args.iter().map(runtime_value).collect::<Result<Vec<_>>>()?;
|
||||
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
|
||||
let instance = instance.borrow();
|
||||
let export = instance
|
||||
.find_export_by_name(field)
|
||||
.ok_or_else(|| anyhow!("no global named `{}`", field))?;
|
||||
let func = match export {
|
||||
Extern::Func(f) => f.borrow(),
|
||||
Extern::Func(f) => f,
|
||||
_ => bail!("export of `{}` wasn't a global", field),
|
||||
};
|
||||
Ok(match func.call(&values) {
|
||||
@@ -176,12 +174,11 @@ impl WastContext {
|
||||
/// Get the value of an exported global from an instance.
|
||||
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 = instance.borrow();
|
||||
let export = instance
|
||||
.find_export_by_name(field)
|
||||
.ok_or_else(|| anyhow!("no global named `{}`", field))?;
|
||||
let global = match export {
|
||||
Extern::Global(g) => g.borrow(),
|
||||
Extern::Global(g) => g,
|
||||
_ => bail!("export of `{}` wasn't a global", field),
|
||||
};
|
||||
Ok(Outcome::Ok(vec![global.get()]))
|
||||
|
||||
@@ -11,7 +11,7 @@ use std::{
|
||||
};
|
||||
use structopt::{clap::AppSettings, StructOpt};
|
||||
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_interface_types::ModuleData;
|
||||
use wasmtime_wasi::{
|
||||
@@ -148,7 +148,7 @@ impl RunCommand {
|
||||
let preopen_dirs = self.compute_preopen_dirs()?;
|
||||
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")]
|
||||
{
|
||||
let global_exports = store.global_exports().clone();
|
||||
@@ -161,14 +161,10 @@ impl RunCommand {
|
||||
}
|
||||
} else {
|
||||
create_wasi_instance_snapshot_0(&store, &preopen_dirs, &argv, &self.vars)?
|
||||
});
|
||||
};
|
||||
|
||||
let wasi_snapshot_preview1 = HostRef::new(create_wasi_instance(
|
||||
&store,
|
||||
&preopen_dirs,
|
||||
&argv,
|
||||
&self.vars,
|
||||
)?);
|
||||
let wasi_snapshot_preview1 =
|
||||
create_wasi_instance(&store, &preopen_dirs, &argv, &self.vars)?;
|
||||
|
||||
module_registry.insert("wasi_unstable".to_owned(), wasi_unstable);
|
||||
module_registry.insert("wasi_snapshot_preview1".to_owned(), wasi_snapshot_preview1);
|
||||
@@ -232,9 +228,9 @@ impl RunCommand {
|
||||
|
||||
fn instantiate_module(
|
||||
store: &Store,
|
||||
module_registry: &HashMap<String, HostRef<Instance>>,
|
||||
module_registry: &HashMap<String, Instance>,
|
||||
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
|
||||
let data = wat::parse_file(path)?;
|
||||
|
||||
@@ -248,7 +244,7 @@ impl RunCommand {
|
||||
let module_name = i.module();
|
||||
if let Some(instance) = module_registry.get(module_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())
|
||||
} else {
|
||||
bail!(
|
||||
@@ -263,10 +259,8 @@ impl RunCommand {
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let instance = HostRef::new(
|
||||
Instance::new(store, &module, &imports)
|
||||
.context(format!("failed to instantiate {:?}", path))?,
|
||||
);
|
||||
let instance = Instance::new(store, &module, &imports)
|
||||
.context(format!("failed to instantiate {:?}", path))?;
|
||||
|
||||
Ok((instance, module, data))
|
||||
}
|
||||
@@ -274,7 +268,7 @@ impl RunCommand {
|
||||
fn handle_module(
|
||||
&self,
|
||||
store: &Store,
|
||||
module_registry: &HashMap<String, HostRef<Instance>>,
|
||||
module_registry: &HashMap<String, Instance>,
|
||||
) -> Result<()> {
|
||||
let (instance, module, data) =
|
||||
Self::instantiate_module(store, module_registry, &self.module)?;
|
||||
@@ -301,16 +295,11 @@ impl RunCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn invoke_export(
|
||||
&self,
|
||||
instance: HostRef<Instance>,
|
||||
data: &ModuleData,
|
||||
name: &str,
|
||||
) -> Result<()> {
|
||||
fn invoke_export(&self, instance: Instance, data: &ModuleData, name: &str) -> Result<()> {
|
||||
use wasm_webidl_bindings::ast;
|
||||
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
|
||||
// need to be passed to the function that we're invoking. Currently we take
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
mod tests {
|
||||
use core::cell::Ref;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use wasmtime::*;
|
||||
@@ -38,7 +37,7 @@ mod tests {
|
||||
"#;
|
||||
|
||||
fn invoke_export(
|
||||
instance: &HostRef<Instance>,
|
||||
instance: &Instance,
|
||||
data: &[u8],
|
||||
func_name: &str,
|
||||
) -> 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
|
||||
fn set_up_memory(instance: &HostRef<Instance>) -> (*mut u8, usize) {
|
||||
let mem_export = instance.borrow().get_wasmtime_memory().expect("memory");
|
||||
fn set_up_memory(instance: &Instance) -> (*mut u8, usize) {
|
||||
let mem_export = instance.get_wasmtime_memory().expect("memory");
|
||||
|
||||
let (base, length) = if let wasmtime_runtime::Export::Memory {
|
||||
definition,
|
||||
@@ -107,16 +106,14 @@ mod tests {
|
||||
let store = Store::new(&engine);
|
||||
let data = wat::parse_str(WAT1)?;
|
||||
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);
|
||||
instance
|
||||
.borrow_mut()
|
||||
.set_signal_handler(move |signum, siginfo, _| {
|
||||
instance.set_signal_handler(move |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());
|
||||
|
||||
// these invoke wasmtime_call_trampoline from action.rs
|
||||
@@ -140,10 +137,7 @@ mod tests {
|
||||
.func()
|
||||
.expect("expected a 'read' func in the module");
|
||||
println!("calling read...");
|
||||
let result = read_func
|
||||
.borrow()
|
||||
.call(&[])
|
||||
.expect("expected function not to trap");
|
||||
let result = read_func.call(&[]).expect("expected function not to trap");
|
||||
assert_eq!(123i32, result[0].clone().unwrap_i32());
|
||||
}
|
||||
|
||||
@@ -152,7 +146,7 @@ mod tests {
|
||||
.func()
|
||||
.expect("expected a 'read_out_of_bounds' func in the module");
|
||||
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
|
||||
.message()
|
||||
.starts_with("call error: wasm trap: out of bounds memory access"));
|
||||
@@ -169,13 +163,13 @@ mod tests {
|
||||
|
||||
// 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 (base1, length1) = set_up_memory(&instance1);
|
||||
|
||||
instance1.borrow_mut().set_signal_handler({
|
||||
instance1.set_signal_handler({
|
||||
let instance1_handler_triggered = instance1_handler_triggered.clone();
|
||||
move |_signum, _siginfo, _context| {
|
||||
// Remove protections so the execution may resume
|
||||
@@ -196,15 +190,13 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
let instance2 = HostRef::new(
|
||||
Instance::new(&store, &module, &[]).expect("failed to instantiate module"),
|
||||
);
|
||||
let instance2 = Instance::new(&store, &module, &[]).expect("failed to instantiate module");
|
||||
let instance2_handler_triggered = Rc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
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();
|
||||
move |_signum, _siginfo, _context| {
|
||||
// Remove protections so the execution may resume
|
||||
@@ -229,7 +221,7 @@ mod tests {
|
||||
|
||||
// First instance1
|
||||
{
|
||||
let exports1 = Ref::map(instance1.borrow(), |i| i.exports());
|
||||
let exports1 = instance1.exports();
|
||||
assert!(!exports1.is_empty());
|
||||
|
||||
println!("calling instance1.read...");
|
||||
@@ -244,7 +236,7 @@ mod tests {
|
||||
|
||||
// And then instance2
|
||||
{
|
||||
let exports2 = Ref::map(instance2.borrow(), |i| i.exports());
|
||||
let exports2 = instance2.exports();
|
||||
assert!(!exports2.is_empty());
|
||||
|
||||
println!("calling instance2.read...");
|
||||
@@ -267,28 +259,24 @@ mod tests {
|
||||
// instance1 which defines 'read'
|
||||
let data1 = wat::parse_str(WAT1)?;
|
||||
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);
|
||||
instance1
|
||||
.borrow_mut()
|
||||
.set_signal_handler(move |signum, siginfo, _| {
|
||||
instance1.set_signal_handler(move |signum, siginfo, _| {
|
||||
println!("instance1");
|
||||
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());
|
||||
let instance1_read = instance1_exports[0].clone();
|
||||
|
||||
// instance2 wich calls 'instance1.read'
|
||||
let data2 = wat::parse_str(WAT2)?;
|
||||
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
|
||||
// SIGSEGV originating from within the memory of instance1
|
||||
instance2
|
||||
.borrow_mut()
|
||||
.set_signal_handler(move |signum, siginfo, _| {
|
||||
instance2.set_signal_handler(move |signum, siginfo, _| {
|
||||
handle_sigsegv(base1, length1, signum, siginfo)
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user