Add examples; refactor HostRef

This commit is contained in:
Yury Delendik
2019-08-28 11:19:40 -05:00
committed by Dan Gohman
parent 042c87763e
commit 6a41417b52
19 changed files with 712 additions and 240 deletions

View File

@@ -36,17 +36,15 @@ use docopt::Docopt;
use failure::{bail, Error, ResultExt};
use pretty_env_logger;
use serde::Deserialize;
use std::cell::RefCell;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::File;
use std::path::Component;
use std::path::{Path, PathBuf};
use std::process::exit;
use std::rc::Rc;
use wabt;
use wasi_common::preopen_dir;
use wasmtime_api::{Config, Engine, Instance, Module, Store};
use wasmtime_api::{Config, Engine, HostRef, Instance, Module, Store};
use wasmtime_environ::cache_config;
use wasmtime_interface_types::ModuleData;
use wasmtime_jit::Features;
@@ -258,8 +256,8 @@ fn rmain() -> Result<(), Error> {
}
let config = Config::new(settings::Flags::new(flag_builder), features, debug_info);
let engine = Rc::new(RefCell::new(Engine::new(config)));
let store = Rc::new(RefCell::new(Store::new(engine)));
let engine = HostRef::new(Engine::new(config));
let store = HostRef::new(Store::new(engine));
let mut module_registry = HashMap::new();
@@ -308,14 +306,14 @@ fn rmain() -> Result<(), Error> {
}
fn instantiate_module(
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
module_registry: &HashMap<String, (Instance, HashMap<String, usize>)>,
path: &Path,
) -> Result<(Rc<RefCell<Instance>>, Rc<RefCell<Module>>, Vec<u8>), Error> {
) -> Result<(HostRef<Instance>, HostRef<Module>, Vec<u8>), Error> {
// Read the wasm module binary.
let data = read_wasm(path.to_path_buf())?;
let module = Rc::new(RefCell::new(Module::new(store.clone(), &data)?));
let module = HostRef::new(Module::new(store.clone(), &data)?);
// Resolve import using module_registry.
let imports = module
@@ -341,17 +339,13 @@ fn instantiate_module(
})
.collect::<Result<Vec<_>, _>>()?;
let instance = Rc::new(RefCell::new(Instance::new(
store.clone(),
module.clone(),
&imports,
)?));
let instance = HostRef::new(Instance::new(store.clone(), module.clone(), &imports)?);
Ok((instance, module, data))
}
fn handle_module(
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
module_registry: &HashMap<String, (Instance, HashMap<String, usize>)>,
args: &Args,
path: &Path,
@@ -368,8 +362,8 @@ fn handle_module(
}
fn invoke_export(
store: Rc<RefCell<Store>>,
instance: Rc<RefCell<Instance>>,
store: HostRef<Store>,
instance: HostRef<Instance>,
data: &ModuleData,
name: &str,
args: &Args,

View File

@@ -2,20 +2,18 @@
//! invoking its exported function.
use failure::{format_err, Error};
use std::cell::RefCell;
use std::fs::read;
use std::rc::Rc;
use wasmtime_api::*;
fn main() -> Result<(), Error> {
let wasm = read("examples/gcd.wasm")?;
// Instantiate engine and store.
let engine = Rc::new(RefCell::new(Engine::default()));
let store = Rc::new(RefCell::new(Store::new(engine)));
let engine = HostRef::new(Engine::default());
let store = HostRef::new(Store::new(engine));
// Load a module.
let module = Rc::new(RefCell::new(Module::new(store.clone(), &wasm)?));
let module = HostRef::new(Module::new(store.clone(), &wasm)?);
// Find index of the `gcd` export.
let gcd_index = module
@@ -28,12 +26,12 @@ fn main() -> Result<(), Error> {
.0;
// Instantiate the module.
let instance = Rc::new(RefCell::new(Instance::new(store.clone(), module, &[])?));
let instance = HostRef::new(Instance::new(store.clone(), module, &[])?);
// Invoke `gcd` export
let gcd = instance.borrow().exports()[gcd_index]
.borrow()
.func()
.expect("gcd")
.clone();
let result = gcd
.borrow()

View File

@@ -0,0 +1,72 @@
//! Translation of hello example
use failure::{bail, format_err, Error};
use std::cell::Ref;
use std::fs::read;
use std::rc::Rc;
use wasmtime_api::*;
struct HelloCallback;
impl Callable for HelloCallback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
println!("Calling back...");
println!("> Hello World!");
Ok(())
}
}
fn main() -> Result<(), Error> {
// Initialize.
println!("Initializing...");
let engine = HostRef::new(Engine::new(Config::default()));
let store = HostRef::new(Store::new(engine));
// Load binary.
println!("Loading binary...");
let binary = read("examples/hello.wasm")?;
// Compile.
println!("Compiling module...");
let module = HostRef::new(
Module::new(store.clone(), &binary)
.map_err(|_| format_err!("> Error compiling module!"))?,
);
// Create external print functions.
println!("Creating callback...");
let hello_type = FuncType::new(Box::new([]), Box::new([]));
let hello_func = HostRef::new(Func::new(store.clone(), hello_type, Rc::new(HelloCallback)));
// Instantiate.
println!("Instantiating module...");
let imports = vec![hello_func.into()];
let instance = HostRef::new(
Instance::new(store.clone(), module, imports.as_slice())
.map_err(|_| format_err!("> Error instantiating module!"))?,
);
// Extract export.
println!("Extracting export...");
let exports = Ref::map(instance.borrow(), |instance| instance.exports());
if exports.len() == 0 {
bail!("> Error accessing exports!");
}
let run_func = exports[0]
.func()
.ok_or_else(|| format_err!("> Error accessing exports!"))?;
// Call.
println!("Calling export...");
if let Err(_) = run_func.borrow().call(&[]) {
bail!("> Error calling function!");
}
// Shut down.
println!("Shutting down...");
drop(store);
// All done.
println!("Done.");
Ok(())
}

Binary file not shown.

View File

@@ -0,0 +1,4 @@
(module
(func $hello (import "" "hello"))
(func (export "run") (call $hello))
)

View File

@@ -0,0 +1,158 @@
//! Translation of the memory example
use failure::{bail, format_err, Error};
use std::cell::Ref;
use std::fs::read;
use wasmtime_api::*;
fn get_export_memory(exports: &[Extern], i: usize) -> Result<HostRef<Memory>, Error> {
if exports.len() <= i {
bail!("> Error accessing memory export {}!", i);
}
Ok(exports[i]
.memory()
.ok_or_else(|| format_err!("> Error accessing memory export {}!", i))?
.clone())
}
fn get_export_func(exports: &[Extern], i: usize) -> Result<HostRef<Func>, Error> {
if exports.len() <= i {
bail!("> Error accessing function export {}!", i);
}
Ok(exports[i]
.func()
.ok_or_else(|| format_err!("> Error accessing function export {}!", i))?
.clone())
}
macro_rules! check {
($actual:expr, $expected:expr) => {
if $actual != $expected {
bail!("> Error on result, expected {}, got {}", $expected, $actual);
}
};
}
macro_rules! check_ok {
($func:expr, $($p:expr),*) => {
if let Err(_) = $func.borrow().call(&[$($p.into()),*]) {
bail!("> Error on result, expected return");
}
}
}
macro_rules! check_trap {
($func:expr, $($p:expr),*) => {
if let Ok(_) = $func.borrow().call(&[$($p.into()),*]) {
bail!("> Error on result, expected trap");
}
}
}
macro_rules! call {
($func:expr, $($p:expr),*) => {
match $func.borrow().call(&[$($p.into()),*]) {
Ok(result) => {
let result: i32 = result[0].clone().into();
result
}
Err(_) => { bail!("> Error on result, expected return"); }
}
}
}
fn main() -> Result<(), Error> {
// Initialize.
println!("Initializing...");
let engine = HostRef::new(Engine::new(Config::default()));
let store = HostRef::new(Store::new(engine));
// Load binary.
println!("Loading binary...");
let binary = read("examples/memory.wasm")?;
// Compile.
println!("Compiling module...");
let module = HostRef::new(
Module::new(store.clone(), &binary)
.map_err(|_| format_err!("> Error compiling module!"))?,
);
// Instantiate.
println!("Instantiating module...");
let instance = HostRef::new(
Instance::new(store.clone(), module, &[])
.map_err(|_| format_err!("> Error instantiating module!"))?,
);
// Extract export.
println!("Extracting export...");
let exports = Ref::map(instance.borrow(), |instance| instance.exports());
if exports.len() == 0 {
bail!("> Error accessing exports!");
}
let memory = get_export_memory(&exports, 0)?;
let size_func = get_export_func(&exports, 1)?;
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!(memory.borrow().data()[0], 0);
check!(memory.borrow().data()[0x1000], 1);
check!(memory.borrow().data()[0x1003], 4);
check!(call!(size_func,), 2);
check!(call!(load_func, 0), 0);
check!(call!(load_func, 0x1000), 1);
check!(call!(load_func, 0x1003), 4);
check!(call!(load_func, 0x1ffff), 0);
check_trap!(load_func, 0x20000);
// Mutate memory.
println!("Mutating memory...");
memory.borrow_mut().data()[0x1003] = 5;
check_ok!(store_func, 0x1002, 6);
check_trap!(store_func, 0x20000, 0);
check!(memory.borrow().data()[0x1002], 6);
check!(memory.borrow().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!(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);
// 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, 5));
let mut memory2 = Memory::new(store.clone(), memorytype);
check!(memory2.size(), 5u32);
check!(memory2.grow(1), false);
check!(memory2.grow(0), true);
// Shut down.
println!("Shutting down...");
drop(store);
println!("Done.");
Ok(())
}

Binary file not shown.

View File

@@ -0,0 +1,11 @@
(module
(memory (export "memory") 2 3)
(func (export "size") (result i32) (memory.size))
(func (export "load") (param i32) (result i32) (i32.load8_s (local.get 0)))
(func (export "store") (param i32 i32)
(i32.store8 (local.get 0) (local.get 1))
)
(data (i32.const 0x1000) "\01\02\03\04")
)

View File

@@ -1,8 +1,8 @@
use crate::r#ref::HostRef;
use crate::runtime::Store;
use crate::trap::Trap;
use crate::types::FuncType;
use crate::values::Val;
use std::cell::RefCell;
use std::rc::Rc;
use crate::trampoline::generate_func_export;
@@ -11,11 +11,11 @@ use wasmtime_jit::InstanceHandle;
use wasmtime_runtime::Export;
pub trait Callable {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>>;
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>>;
}
pub(crate) trait WrappedCallable {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>>;
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>>;
fn signature(&self) -> &ir::Signature {
match self.wasmtime_export() {
Export::Function { signature, .. } => signature,
@@ -27,13 +27,13 @@ pub(crate) trait WrappedCallable {
}
pub(crate) struct WasmtimeFn {
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
instance: InstanceHandle,
export: Export,
}
impl WasmtimeFn {
pub fn new(store: Rc<RefCell<Store>>, instance: InstanceHandle, export: Export) -> WasmtimeFn {
pub fn new(store: HostRef<Store>, instance: InstanceHandle, export: Export) -> WasmtimeFn {
WasmtimeFn {
store,
instance,
@@ -43,7 +43,7 @@ impl WasmtimeFn {
}
impl WrappedCallable for WasmtimeFn {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
use core::cmp::max;
use core::{mem, ptr};
@@ -81,7 +81,7 @@ impl WrappedCallable for WasmtimeFn {
let exec_code_buf = context
.compiler()
.get_published_trampoline(body, &signature, value_size)
.map_err(|_| Rc::new(RefCell::new(Trap::fake())))?; //was ActionError::Setup)?;
.map_err(|_| HostRef::new(Trap::fake()))?; //was ActionError::Setup)?;
// Call the trampoline.
if let Err(message) = unsafe {
@@ -91,7 +91,7 @@ impl WrappedCallable for WasmtimeFn {
values_vec.as_mut_ptr() as *mut u8,
)
} {
return Err(Rc::new(RefCell::new(Trap::new(message))));
return Err(HostRef::new(Trap::new(message)));
}
// Load the return values out of `values_vec`.
@@ -129,7 +129,7 @@ impl NativeCallable {
pub(crate) fn new(
callable: Rc<dyn Callable + 'static>,
ft: &FuncType,
store: &Rc<RefCell<Store>>,
store: &HostRef<Store>,
) -> Self {
let (instance, export) =
generate_func_export(ft, &callable, store).expect("generated func");
@@ -142,7 +142,7 @@ impl NativeCallable {
}
impl WrappedCallable for NativeCallable {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
self.callable.call(params, results)
}
fn wasmtime_handle(&self) -> &InstanceHandle {

View File

@@ -1,46 +1,48 @@
use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable};
use crate::r#ref::{AnyRef, HostRef};
use crate::runtime::Store;
use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export};
use crate::trap::Trap;
use crate::types::{ExternType, FuncType, GlobalType, MemoryType, TableType, ValType};
use crate::values::{from_checked_anyfunc, into_checked_anyfunc, AnyRef, Val};
use std::cell::RefCell;
use crate::values::{from_checked_anyfunc, into_checked_anyfunc, Val};
use std::rc::Rc;
use std::result::Result;
use std::slice;
use wasmtime_runtime::InstanceHandle;
// Externals
#[derive(Clone)]
pub enum Extern {
Func(Rc<RefCell<Func>>),
Global(Rc<RefCell<Global>>),
Table(Rc<RefCell<Table>>),
Memory(Rc<RefCell<Memory>>),
Func(HostRef<Func>),
Global(HostRef<Global>),
Table(HostRef<Table>),
Memory(HostRef<Memory>),
}
impl Extern {
pub fn func(&self) -> &Rc<RefCell<Func>> {
pub fn func(&self) -> Option<&HostRef<Func>> {
match self {
Extern::Func(func) => func,
_ => panic!("Extern::Func expected"),
Extern::Func(func) => Some(func),
_ => None,
}
}
pub fn global(&self) -> &Rc<RefCell<Global>> {
pub fn global(&self) -> Option<&HostRef<Global>> {
match self {
Extern::Global(global) => global,
_ => panic!("Extern::Global expected"),
Extern::Global(global) => Some(global),
_ => None,
}
}
pub fn table(&self) -> &Rc<RefCell<Table>> {
pub fn table(&self) -> Option<&HostRef<Table>> {
match self {
Extern::Table(table) => table,
_ => panic!("Extern::Table expected"),
Extern::Table(table) => Some(table),
_ => None,
}
}
pub fn memory(&self) -> &Rc<RefCell<Memory>> {
pub fn memory(&self) -> Option<&HostRef<Memory>> {
match self {
Extern::Memory(memory) => memory,
_ => panic!("Extern::Memory expected"),
Extern::Memory(memory) => Some(memory),
_ => None,
}
}
@@ -63,45 +65,65 @@ impl Extern {
}
pub(crate) fn from_wasmtime_export(
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
instance_handle: InstanceHandle,
export: wasmtime_runtime::Export,
) -> Extern {
match export {
wasmtime_runtime::Export::Function { .. } => Extern::Func(Rc::new(RefCell::new(
wasmtime_runtime::Export::Function { .. } => Extern::Func(HostRef::new(
Func::from_wasmtime_function(export, store, instance_handle),
))),
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(Rc::new(RefCell::new(
)),
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(HostRef::new(
Memory::from_wasmtime_memory(export, store, instance_handle),
))),
wasmtime_runtime::Export::Global { .. } => Extern::Global(Rc::new(RefCell::new(
Global::from_wasmtime_global(export, store),
))),
wasmtime_runtime::Export::Table { .. } => Extern::Table(Rc::new(RefCell::new(
)),
wasmtime_runtime::Export::Global { .. } => {
Extern::Global(HostRef::new(Global::from_wasmtime_global(export, store)))
}
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 {
Extern::Func(r)
}
}
impl From<HostRef<Global>> for Extern {
fn from(r: HostRef<Global>) -> Self {
Extern::Global(r)
}
}
impl From<HostRef<Memory>> for Extern {
fn from(r: HostRef<Memory>) -> Self {
Extern::Memory(r)
}
}
impl From<HostRef<Table>> for Extern {
fn from(r: HostRef<Table>) -> Self {
Extern::Table(r)
}
}
pub struct Func {
_store: Rc<RefCell<Store>>,
_store: HostRef<Store>,
callable: Rc<dyn WrappedCallable + 'static>,
r#type: FuncType,
}
impl Func {
pub fn new(
store: Rc<RefCell<Store>>,
ty: FuncType,
callable: Rc<dyn Callable + 'static>,
) -> Self {
pub fn new(store: HostRef<Store>, ty: FuncType, callable: Rc<dyn Callable + 'static>) -> Self {
let callable = Rc::new(NativeCallable::new(callable, &ty, &store));
Func::from_wrapped(store, ty, callable)
}
fn from_wrapped(
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
r#type: FuncType,
callable: Rc<dyn WrappedCallable + 'static>,
) -> Func {
@@ -116,11 +138,6 @@ impl Func {
&self.r#type
}
#[cfg(feature = "wasm-c-api")]
pub(crate) fn callable(&self) -> &Rc<dyn WrappedCallable + 'static> {
&self.callable
}
pub fn param_arity(&self) -> usize {
self.r#type.params().len()
}
@@ -129,19 +146,19 @@ impl Func {
self.r#type.results().len()
}
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Rc<RefCell<Trap>>> {
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, HostRef<Trap>> {
let mut results = vec![Val::default(); self.result_arity()];
self.callable.call(params, &mut results)?;
Ok(results.into_boxed_slice())
}
fn wasmtime_export(&self) -> &wasmtime_runtime::Export {
pub(crate) fn wasmtime_export(&self) -> &wasmtime_runtime::Export {
self.callable.wasmtime_export()
}
fn from_wasmtime_function(
pub(crate) fn from_wasmtime_function(
export: wasmtime_runtime::Export,
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
instance_handle: InstanceHandle,
) -> Self {
let ty = if let wasmtime_runtime::Export::Function { signature, .. } = &export {
@@ -154,8 +171,14 @@ impl Func {
}
}
impl std::fmt::Debug for Func {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Func")
}
}
pub struct Global {
_store: Rc<RefCell<Store>>,
_store: HostRef<Store>,
r#type: GlobalType,
wasmtime_export: wasmtime_runtime::Export,
#[allow(dead_code)]
@@ -163,7 +186,7 @@ pub struct Global {
}
impl Global {
pub fn new(store: Rc<RefCell<Store>>, r#type: GlobalType, val: Val) -> Global {
pub fn new(store: HostRef<Store>, r#type: GlobalType, val: Val) -> Global {
let (wasmtime_export, wasmtime_state) =
generate_global_export(&r#type, val).expect("generated global");
Global {
@@ -224,7 +247,7 @@ impl Global {
pub(crate) fn from_wasmtime_global(
export: wasmtime_runtime::Export,
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
) -> Global {
let global = if let wasmtime_runtime::Export::Global { ref global, .. } = export {
global
@@ -242,7 +265,7 @@ impl Global {
}
pub struct Table {
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
r#type: TableType,
wasmtime_handle: InstanceHandle,
wasmtime_export: wasmtime_runtime::Export,
@@ -250,7 +273,7 @@ pub struct Table {
fn get_table_item(
handle: &InstanceHandle,
store: &Rc<RefCell<Store>>,
store: &HostRef<Store>,
table_index: cranelift_wasm::DefinedTableIndex,
item_index: u32,
) -> Val {
@@ -263,7 +286,7 @@ fn get_table_item(
fn set_table_item(
handle: &mut InstanceHandle,
store: &Rc<RefCell<Store>>,
store: &HostRef<Store>,
table_index: cranelift_wasm::DefinedTableIndex,
item_index: u32,
val: Val,
@@ -278,7 +301,7 @@ fn set_table_item(
}
impl Table {
pub fn new(store: Rc<RefCell<Store>>, r#type: TableType, init: Val) -> Table {
pub fn new(store: HostRef<Store>, r#type: TableType, init: Val) -> Table {
match r#type.element() {
ValType::FuncRef => (),
_ => panic!("table is not for funcref"),
@@ -363,7 +386,7 @@ impl Table {
pub(crate) fn from_wasmtime_table(
export: wasmtime_runtime::Export,
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
instance_handle: wasmtime_runtime::InstanceHandle,
) -> Table {
let table = if let wasmtime_runtime::Export::Table { ref table, .. } = export {
@@ -382,14 +405,14 @@ impl Table {
}
pub struct Memory {
_store: Rc<RefCell<Store>>,
_store: HostRef<Store>,
r#type: MemoryType,
wasmtime_handle: InstanceHandle,
wasmtime_export: wasmtime_runtime::Export,
}
impl Memory {
pub fn new(store: Rc<RefCell<Store>>, r#type: MemoryType) -> Memory {
pub fn new(store: HostRef<Store>, r#type: MemoryType) -> Memory {
let (wasmtime_handle, wasmtime_export) =
generate_memory_export(&r#type).expect("generated memory");
Memory {
@@ -411,7 +434,14 @@ impl Memory {
}
}
pub fn data(&self) -> *mut u8 {
pub fn data(&self) -> &mut [u8] {
unsafe {
let definition = &*self.wasmtime_memory_definition();
slice::from_raw_parts_mut(definition.base, definition.current_length)
}
}
pub fn data_ptr(&self) -> *mut u8 {
unsafe { (*self.wasmtime_memory_definition()).base }
}
@@ -440,7 +470,7 @@ impl Memory {
pub(crate) fn from_wasmtime_memory(
export: wasmtime_runtime::Export,
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
instance_handle: wasmtime_runtime::InstanceHandle,
) -> Memory {
let memory = if let wasmtime_runtime::Export::Memory { ref memory, .. } = export {

View File

@@ -1,6 +1,7 @@
use crate::context::Context;
use crate::externals::Extern;
use crate::module::Module;
use crate::r#ref::HostRef;
use crate::runtime::Store;
use failure::Error;
use std::cell::RefCell;
@@ -11,22 +12,22 @@ use wasmtime_jit::{instantiate, Resolver};
use wasmtime_runtime::{Export, InstanceHandle};
struct SimpleResolver {
imports: Vec<(String, String, Rc<RefCell<Extern>>)>,
imports: Vec<(String, String, Extern)>,
}
impl Resolver for SimpleResolver {
fn resolve(&mut self, name: &str, field: &str) -> Option<Export> {
// TODO speedup lookup
self.imports
.iter()
.iter_mut()
.find(|(n, f, _)| name == n && field == f)
.map(|(_, _, e)| e.borrow_mut().get_wasmtime_export())
.map(|(_, _, e)| e.get_wasmtime_export())
}
}
pub fn instantiate_in_context(
data: &[u8],
imports: Vec<(String, String, Rc<RefCell<Extern>>)>,
imports: Vec<(String, String, Extern)>,
mut context: Context,
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
@@ -51,14 +52,14 @@ pub struct Instance {
// We need to keep CodeMemory alive.
contexts: HashSet<Context>,
exports: Box<[Rc<RefCell<Extern>>]>,
exports: Box<[Extern]>,
}
impl Instance {
pub fn new(
store: Rc<RefCell<Store>>,
module: Rc<RefCell<Module>>,
externs: &[Rc<RefCell<Extern>>],
store: HostRef<Store>,
module: HostRef<Module>,
externs: &[Extern],
) -> Result<Instance, Error> {
let context = store.borrow_mut().context().clone();
let exports = store.borrow_mut().global_exports().clone();
@@ -78,11 +79,11 @@ impl Instance {
for export in module.exports() {
let name = export.name().to_string();
let export = instance_handle.lookup(&name).expect("export");
exports.push(Rc::new(RefCell::new(Extern::from_wasmtime_export(
exports.push(Extern::from_wasmtime_export(
store.clone(),
instance_handle.clone(),
export,
))));
));
}
exports.into_boxed_slice()
};
@@ -93,12 +94,12 @@ impl Instance {
})
}
pub fn exports(&self) -> &[Rc<RefCell<Extern>>] {
pub fn exports(&self) -> &[Extern] {
&self.exports
}
pub fn from_handle(
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
instance_handle: InstanceHandle,
) -> Result<(Instance, HashMap<String, usize>), Error> {
let contexts = HashSet::new();
@@ -115,11 +116,11 @@ impl Instance {
let _ = store.borrow_mut().register_cranelift_signature(signature);
}
export_names_map.insert(name.to_owned(), exports.len());
exports.push(Rc::new(RefCell::new(Extern::from_wasmtime_export(
exports.push(Extern::from_wasmtime_export(
store.clone(),
instance_handle.clone(),
export.clone(),
))));
));
}
Ok((

View File

@@ -5,6 +5,7 @@ mod context;
mod externals;
mod instance;
mod module;
mod r#ref;
mod runtime;
mod trampoline;
mod trap;
@@ -21,6 +22,7 @@ pub use crate::callable::Callable;
pub use crate::externals::*;
pub use crate::instance::Instance;
pub use crate::module::Module;
pub use crate::r#ref::{AnyRef, HostInfo, HostRef};
pub use crate::runtime::{Config, Engine, Store};
pub use crate::trap::Trap;
pub use crate::types::*;

View File

@@ -1,11 +1,10 @@
use crate::r#ref::HostRef;
use crate::runtime::Store;
use crate::types::{
ExportType, ExternType, FuncType, GlobalType, ImportType, Limits, MemoryType, Mutability,
TableType, ValType,
};
use failure::Error;
use std::cell::RefCell;
use std::rc::Rc;
use wasmparser::{validate, ExternalKind, ImportSectionEntryType, ModuleReader, SectionCode};
@@ -170,14 +169,14 @@ fn read_imports_and_exports(
#[derive(Clone)]
pub struct Module {
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
binary: Box<[u8]>,
imports: Box<[ImportType]>,
exports: Box<[ExportType]>,
}
impl Module {
pub fn new(store: Rc<RefCell<Store>>, binary: &[u8]) -> Result<Module, Error> {
pub fn new(store: HostRef<Store>, binary: &[u8]) -> Result<Module, Error> {
let (imports, exports) = read_imports_and_exports(binary)?;
Ok(Module {
store,

210
wasmtime-api/src/ref.rs Normal file
View File

@@ -0,0 +1,210 @@
use std::any::Any;
use std::cell::{self, RefCell};
use std::fmt;
use std::rc::{Rc, Weak};
pub trait HostInfo {
fn finalize(&mut self) {}
}
trait InternalRefBase: Any {
fn as_any(&self) -> &dyn Any;
fn host_info(&self) -> Option<cell::RefMut<Box<dyn HostInfo>>>;
fn set_host_info(&self, info: Option<Box<dyn HostInfo>>);
fn ptr_eq(&self, other: &dyn InternalRefBase) -> bool;
}
#[derive(Clone)]
pub struct InternalRef(Rc<dyn InternalRefBase>);
impl InternalRef {
pub fn is_ref<T: 'static>(&self) -> bool {
let r = self.0.as_any();
Any::is::<HostRef<T>>(r)
}
pub fn get_ref<T: 'static>(&self) -> HostRef<T> {
let r = self.0.as_any();
r.downcast_ref::<HostRef<T>>()
.expect("reference is not T type")
.clone()
}
}
struct AnyAndHostInfo {
any: Box<dyn Any>,
host_info: Option<Box<dyn HostInfo>>,
}
impl Drop for AnyAndHostInfo {
fn drop(&mut self) {
if let Some(info) = &mut self.host_info {
info.finalize();
}
}
}
#[derive(Clone)]
pub struct OtherRef(Rc<RefCell<AnyAndHostInfo>>);
#[derive(Clone)]
pub enum AnyRef {
Null,
Ref(InternalRef),
Other(OtherRef),
}
impl AnyRef {
pub fn new(data: Box<dyn Any>) -> Self {
let info = AnyAndHostInfo {
any: data,
host_info: None,
};
AnyRef::Other(OtherRef(Rc::new(RefCell::new(info))))
}
pub fn null() -> Self {
AnyRef::Null
}
pub fn data(&self) -> cell::Ref<Box<dyn Any>> {
match self {
AnyRef::Other(OtherRef(r)) => cell::Ref::map(r.borrow(), |r| &r.any),
_ => panic!("expected AnyRef::Other"),
}
}
pub fn ptr_eq(&self, other: &AnyRef) -> bool {
match (self, other) {
(AnyRef::Null, AnyRef::Null) => true,
(AnyRef::Ref(InternalRef(ref a)), AnyRef::Ref(InternalRef(ref b))) => {
a.ptr_eq(b.as_ref())
}
(AnyRef::Other(OtherRef(ref a)), AnyRef::Other(OtherRef(ref b))) => Rc::ptr_eq(a, b),
_ => false,
}
}
pub fn host_info(&self) -> Option<cell::RefMut<Box<dyn HostInfo>>> {
match self {
AnyRef::Null => panic!("null"),
AnyRef::Ref(r) => r.0.host_info(),
AnyRef::Other(r) => {
let info = cell::RefMut::map(r.0.borrow_mut(), |b| &mut b.host_info);
if info.is_none() {
return None;
}
Some(cell::RefMut::map(info, |info| info.as_mut().unwrap()))
}
}
}
pub fn set_host_info(&self, info: Option<Box<dyn HostInfo>>) {
match self {
AnyRef::Null => panic!("null"),
AnyRef::Ref(r) => r.0.set_host_info(info),
AnyRef::Other(r) => {
r.0.borrow_mut().host_info = info;
}
}
}
}
impl fmt::Debug for AnyRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AnyRef::Null => write!(f, "null"),
AnyRef::Ref(_) => write!(f, "anyref"),
AnyRef::Other(_) => write!(f, "other ref"),
}
}
}
struct ContentBox<T> {
content: T,
host_info: Option<Box<dyn HostInfo>>,
anyref_data: Weak<dyn InternalRefBase>,
}
impl<T> Drop for ContentBox<T> {
fn drop(&mut self) {
if let Some(info) = &mut self.host_info {
info.finalize();
}
}
}
pub struct HostRef<T>(Rc<RefCell<ContentBox<T>>>);
impl<T: 'static> HostRef<T> {
pub fn new(item: T) -> HostRef<T> {
let anyref_data: Weak<HostRef<T>> = Weak::new();
let content = ContentBox {
content: item,
host_info: None,
anyref_data,
};
HostRef(Rc::new(RefCell::new(content)))
}
pub fn borrow(&self) -> cell::Ref<T> {
cell::Ref::map(self.0.borrow(), |b| &b.content)
}
pub fn borrow_mut(&self) -> cell::RefMut<T> {
cell::RefMut::map(self.0.borrow_mut(), |b| &mut b.content)
}
pub fn ptr_eq(&self, other: &HostRef<T>) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
pub fn anyref(&self) -> AnyRef {
let r = self.0.borrow_mut().anyref_data.upgrade();
if let Some(r) = r {
return AnyRef::Ref(InternalRef(r));
}
let anyref_data: Rc<dyn InternalRefBase> = Rc::new(self.clone());
self.0.borrow_mut().anyref_data = Rc::downgrade(&anyref_data);
AnyRef::Ref(InternalRef(anyref_data))
}
}
impl<T: 'static> InternalRefBase for HostRef<T> {
fn ptr_eq(&self, other: &dyn InternalRefBase) -> bool {
if let Some(other) = other.as_any().downcast_ref() {
self.ptr_eq(other)
} else {
false
}
}
fn as_any(&self) -> &dyn Any {
self
}
fn host_info(&self) -> Option<cell::RefMut<Box<dyn HostInfo>>> {
let info = cell::RefMut::map(self.0.borrow_mut(), |b| &mut b.host_info);
if info.is_none() {
return None;
}
Some(cell::RefMut::map(info, |info| info.as_mut().unwrap()))
}
fn set_host_info(&self, info: Option<Box<dyn HostInfo>>) {
self.0.borrow_mut().host_info = info;
}
}
impl<T> Clone for HostRef<T> {
fn clone(&self) -> HostRef<T> {
HostRef(self.0.clone())
}
}
impl<T: fmt::Debug> fmt::Debug for HostRef<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Ref(")?;
self.0.borrow().content.fmt(f)?;
write!(f, ")")
}
}

View File

@@ -3,6 +3,7 @@ use std::collections::HashMap;
use std::rc::Rc;
use crate::context::{create_compiler, Context};
use crate::r#ref::HostRef;
use cranelift_codegen::{ir, settings};
use wasmtime_jit::Features;
@@ -80,14 +81,14 @@ impl Engine {
// Store
pub struct Store {
engine: Rc<RefCell<Engine>>,
engine: HostRef<Engine>,
context: Context,
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
signature_cache: HashMap<wasmtime_runtime::VMSharedSignatureIndex, ir::Signature>,
}
impl Store {
pub fn new(engine: Rc<RefCell<Engine>>) -> Store {
pub fn new(engine: HostRef<Engine>) -> Store {
let flags = engine.borrow().config().flags().clone();
let features = engine.borrow().config().features().clone();
let debug_info = engine.borrow().config().debug_info();
@@ -99,7 +100,7 @@ impl Store {
}
}
pub fn engine(&self) -> &Rc<RefCell<Engine>> {
pub fn engine(&self) -> &HostRef<Engine> {
&self.engine
}

View File

@@ -1,5 +1,6 @@
//! Support for a calling of an imported function.
use crate::r#ref::HostRef;
use crate::trampoline::code_memory::CodeMemory;
use cranelift_codegen::ir::types;
use cranelift_codegen::ir::{InstBuilder, StackSlotData, StackSlotKind, TrapCode};
@@ -14,7 +15,6 @@ use wasmtime_environ::{Export, Module};
use wasmtime_runtime::{InstanceHandle, VMContext, VMFunctionBody};
use core::cmp;
use std::cell::RefCell;
use std::rc::Rc;
use crate::{Callable, FuncType, Store, Trap, Val};
@@ -23,7 +23,7 @@ use super::create_handle::create_handle;
struct TrampolineState {
func: Rc<dyn Callable + 'static>,
trap: Option<Rc<RefCell<Trap>>>,
trap: Option<HostRef<Trap>>,
#[allow(dead_code)]
code_memory: CodeMemory,
}
@@ -191,7 +191,7 @@ fn make_trampoline(
pub fn create_handle_with_function(
ft: &FuncType,
func: &Rc<dyn Callable + 'static>,
store: &Rc<RefCell<Store>>,
store: &HostRef<Store>,
) -> Result<InstanceHandle, Error> {
let sig = ft.get_cranelift_signature().clone();

View File

@@ -7,8 +7,8 @@ mod global;
mod memory;
mod table;
use crate::r#ref::HostRef;
use failure::Error;
use std::cell::RefCell;
use std::rc::Rc;
use self::func::create_handle_with_function;
@@ -22,7 +22,7 @@ pub use self::global::GlobalState;
pub fn generate_func_export(
ft: &FuncType,
func: &Rc<dyn Callable + 'static>,
store: &Rc<RefCell<Store>>,
store: &HostRef<Store>,
) -> Result<(wasmtime_runtime::InstanceHandle, wasmtime_runtime::Export), Error> {
let mut instance = create_handle_with_function(ft, func, store)?;
let export = instance.lookup("trampoline").expect("trampoline export");

View File

@@ -1,63 +1,12 @@
use crate::callable::{WasmtimeFn, WrappedCallable};
use crate::externals::Func;
use crate::r#ref::{AnyRef, HostRef};
use crate::runtime::Store;
use crate::types::ValType;
use std::any::Any;
use std::cell::RefCell;
use std::fmt;
use std::ptr;
use std::rc::Rc;
use cranelift_codegen::ir;
use wasmtime_jit::RuntimeValue;
#[derive(Clone)]
pub enum AnyRef {
Null,
Rc(Rc<dyn Any>),
Func(FuncRef),
}
impl AnyRef {
pub fn null() -> AnyRef {
AnyRef::Null
}
}
impl fmt::Debug for AnyRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AnyRef::Null => write!(f, "null"),
AnyRef::Rc(_) => write!(f, "anyref"),
AnyRef::Func(func) => func.fmt(f),
}
}
}
#[derive(Clone)]
pub struct FuncRef(pub(crate) Rc<dyn WrappedCallable + 'static>);
impl fmt::Debug for FuncRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "funcref")
}
}
impl From<AnyRef> for FuncRef {
fn from(anyref: AnyRef) -> FuncRef {
match anyref {
AnyRef::Func(f) => f,
AnyRef::Rc(_) => unimplemented!("try to unwrap?"),
AnyRef::Null => panic!("null anyref"),
}
}
}
impl Into<AnyRef> for FuncRef {
fn into(self) -> AnyRef {
AnyRef::Func(self)
}
}
#[derive(Debug, Clone)]
pub enum Val {
I32(i32),
@@ -65,7 +14,7 @@ pub enum Val {
F32(u32),
F64(u64),
AnyRef(AnyRef),
FuncRef(FuncRef),
FuncRef(HostRef<Func>),
}
impl Val {
@@ -179,15 +128,21 @@ impl Into<f64> for Val {
impl From<AnyRef> for Val {
fn from(val: AnyRef) -> Val {
match val {
AnyRef::Func(f) => Val::FuncRef(f),
_ => 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<FuncRef> for Val {
fn from(val: FuncRef) -> Val {
impl From<HostRef<Func>> for Val {
fn from(val: HostRef<Func>) -> Val {
Val::FuncRef(val)
}
}
@@ -196,7 +151,7 @@ impl Into<AnyRef> for Val {
fn into(self) -> AnyRef {
match self {
Val::AnyRef(r) => r,
Val::FuncRef(f) => AnyRef::Func(f),
Val::FuncRef(f) => f.anyref(),
_ => panic!("Invalid conversion of {:?} to anyref.", self),
}
}
@@ -204,7 +159,7 @@ impl Into<AnyRef> for Val {
pub(crate) fn into_checked_anyfunc(
val: Val,
store: &Rc<RefCell<Store>>,
store: &HostRef<Store>,
) -> wasmtime_runtime::VMCallerCheckedAnyfunc {
match val {
Val::AnyRef(AnyRef::Null) => wasmtime_runtime::VMCallerCheckedAnyfunc {
@@ -212,8 +167,9 @@ pub(crate) fn into_checked_anyfunc(
type_index: wasmtime_runtime::VMSharedSignatureIndex::default(),
vmctx: ptr::null_mut(),
},
Val::AnyRef(AnyRef::Func(f)) | Val::FuncRef(f) => {
let (vmctx, func_ptr, signature) = match f.0.wasmtime_export() {
Val::FuncRef(f) => {
let f = f.borrow();
let (vmctx, func_ptr, signature) = match f.wasmtime_export() {
wasmtime_runtime::Export::Function {
vmctx,
address,
@@ -234,7 +190,7 @@ pub(crate) fn into_checked_anyfunc(
pub(crate) fn from_checked_anyfunc(
item: &wasmtime_runtime::VMCallerCheckedAnyfunc,
store: &Rc<RefCell<Store>>,
store: &HostRef<Store>,
) -> Val {
if item.type_index == wasmtime_runtime::VMSharedSignatureIndex::default() {
return Val::AnyRef(AnyRef::Null);
@@ -250,6 +206,6 @@ pub(crate) fn from_checked_anyfunc(
signature,
vmctx: item.vmctx,
};
let f = WasmtimeFn::new(store.clone(), instance_handle, export);
Val::FuncRef(FuncRef(Rc::new(f)))
let f = Func::from_wasmtime_function(export, store.clone(), instance_handle);
Val::FuncRef(HostRef::new(f))
}

View File

@@ -6,12 +6,11 @@
// TODO complete the C API
use super::{
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncRef, FuncType, Global,
GlobalType, ImportType, Instance, Limits, Memory, MemoryType, Module, Name, Store, Table,
TableType, Trap, Val, ValType,
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Name, Store,
Table, TableType, Trap, Val, ValType,
};
use std::boxed::Box;
use std::cell::RefCell;
use std::mem;
use std::ptr;
use std::rc::Rc;
@@ -166,12 +165,12 @@ pub struct wasm_config_t {
#[repr(C)]
#[derive(Clone)]
pub struct wasm_engine_t {
engine: Rc<RefCell<Engine>>,
engine: HostRef<Engine>,
}
#[repr(C)]
#[derive(Clone)]
pub struct wasm_store_t {
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
}
#[doc = ""]
pub type wasm_mutability_t = u8;
@@ -312,13 +311,13 @@ declare_vec!(wasm_frame_vec_t, *mut wasm_frame_t);
#[repr(C)]
#[derive(Clone)]
pub struct wasm_instance_t {
instance: Rc<RefCell<Instance>>,
instance: HostRef<Instance>,
}
pub type wasm_message_t = wasm_name_t;
#[repr(C)]
#[derive(Clone)]
pub struct wasm_trap_t {
trap: Rc<RefCell<Trap>>,
trap: HostRef<Trap>,
}
#[repr(C)]
#[derive(Clone)]
@@ -328,7 +327,7 @@ pub struct wasm_foreign_t {
#[repr(C)]
#[derive(Clone)]
pub struct wasm_module_t {
module: Rc<RefCell<Module>>,
module: HostRef<Module>,
imports: Vec<wasm_importtype_t>,
exports: Vec<wasm_exporttype_t>,
}
@@ -340,7 +339,7 @@ pub struct wasm_shared_module_t {
#[repr(C)]
#[derive(Clone)]
pub struct wasm_func_t {
func: Rc<RefCell<Func>>,
func: HostRef<Func>,
}
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,
@@ -355,24 +354,24 @@ pub type wasm_func_callback_with_env_t = ::std::option::Option<
#[repr(C)]
#[derive(Clone)]
pub struct wasm_global_t {
global: Rc<RefCell<Global>>,
global: HostRef<Global>,
}
#[repr(C)]
#[derive(Clone)]
pub struct wasm_table_t {
table: Rc<RefCell<Table>>,
table: HostRef<Table>,
}
pub type wasm_table_size_t = u32;
#[repr(C)]
#[derive(Clone)]
pub struct wasm_memory_t {
memory: Rc<RefCell<Memory>>,
memory: HostRef<Memory>,
}
pub type wasm_memory_pages_t = u32;
#[repr(C)]
#[derive(Clone)]
pub struct wasm_extern_t {
ext: Rc<RefCell<Extern>>,
ext: Extern,
}
declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t);
@@ -395,14 +394,18 @@ pub unsafe extern "C" fn wasm_engine_delete(engine: *mut wasm_engine_t) {
#[no_mangle]
pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t {
let engine = Box::new(wasm_engine_t {
engine: Rc::new(RefCell::new(Engine::default())),
engine: HostRef::new(Engine::default()),
});
Box::into_raw(engine)
}
#[no_mangle]
pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t {
let func = (*e).ext.borrow().func().clone();
let func = if let Some(f) = (*e).ext.func() {
f.clone()
} else {
return ptr::null_mut();
};
let func = Box::new(wasm_func_t { func });
Box::into_raw(func)
}
@@ -415,9 +418,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 {
let ext = Extern::Func((*f).func.clone());
let ext = Box::new(wasm_extern_t {
ext: Rc::new(RefCell::new(ext)),
});
let ext = Box::new(wasm_extern_t { ext });
Box::into_raw(ext)
}
@@ -512,7 +513,7 @@ impl wasm_val_t {
}
impl Callable for wasm_func_callback_t {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
let params = params
.iter()
.map(|p| wasm_val_t::from_val(p))
@@ -531,8 +532,8 @@ impl Callable for wasm_func_callback_t {
}
}
impl Into<Rc<RefCell<Trap>>> for wasm_trap_t {
fn into(self) -> Rc<RefCell<Trap>> {
impl Into<HostRef<Trap>> for wasm_trap_t {
fn into(self) -> HostRef<Trap> {
self.trap
}
}
@@ -544,7 +545,7 @@ struct CallbackWithEnv {
}
impl Callable for CallbackWithEnv {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>> {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
let params = params
.iter()
.map(|p| wasm_val_t::from_val(p))
@@ -583,7 +584,7 @@ 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: Rc::new(RefCell::new(Func::new(store, ty, callback))),
func: HostRef::new(Func::new(store, ty, callback)),
});
Box::into_raw(func)
}
@@ -633,7 +634,7 @@ pub unsafe extern "C" fn wasm_instance_new(
result: *mut *mut wasm_trap_t,
) -> *mut wasm_instance_t {
let store = (*store).store.clone();
let mut externs: Vec<Rc<RefCell<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() {
let import = *imports.offset(i as isize);
externs.push((*import).ext.clone());
@@ -642,7 +643,7 @@ pub unsafe extern "C" fn wasm_instance_new(
match Instance::new(store, module, &externs) {
Ok(instance) => {
let instance = Box::new(wasm_instance_t {
instance: Rc::new(RefCell::new(instance)),
instance: HostRef::new(instance),
});
if !result.is_null() {
(*result) = ptr::null_mut();
@@ -653,9 +654,7 @@ pub unsafe extern "C" fn wasm_instance_new(
if !result.is_null() {
// TODO Unwrap trap from failure::Error
let trap = Box::new(wasm_trap_t {
trap: Rc::new(RefCell::new(Trap::new(
"trap during instantiation".to_string(),
))),
trap: HostRef::new(Trap::new("trap during instantiation".to_string())),
});
(*result) = Box::into_raw(trap);
}
@@ -715,7 +714,7 @@ pub unsafe extern "C" fn wasm_module_new(
})
.collect::<Vec<_>>();
let module = Box::new(wasm_module_t {
module: Rc::new(RefCell::new(module)),
module: HostRef::new(module),
imports,
exports,
});
@@ -731,7 +730,7 @@ pub unsafe extern "C" fn wasm_store_delete(store: *mut wasm_store_t) {
pub unsafe extern "C" fn wasm_store_new(engine: *mut wasm_engine_t) -> *mut wasm_store_t {
let engine = (*engine).engine.clone();
let store = Box::new(wasm_store_t {
store: Rc::new(RefCell::new(Store::new(engine))),
store: HostRef::new(Store::new(engine)),
});
Box::into_raw(store)
}
@@ -757,7 +756,7 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
finalizer,
});
let func = Box::new(wasm_func_t {
func: Rc::new(RefCell::new(Func::new(store, ty, callback))),
func: HostRef::new(Func::new(store, ty, callback)),
});
Box::into_raw(func)
}
@@ -867,7 +866,7 @@ pub unsafe extern "C" fn wasm_trap_new(
}
let message = String::from_utf8_lossy(message).to_string();
let trap = Box::new(wasm_trap_t {
trap: Rc::new(RefCell::new(Trap::new(message))),
trap: HostRef::new(Trap::new(message)),
});
Box::into_raw(trap)
}
@@ -927,13 +926,13 @@ fn from_externtype(ty: &ExternType) -> wasm_externkind_t {
#[no_mangle]
pub unsafe extern "C" fn wasm_extern_kind(e: *const wasm_extern_t) -> wasm_externkind_t {
from_externtype(&(*e).ext.borrow().r#type())
from_externtype(&(*e).ext.r#type())
}
#[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.borrow().r#type(),
ty: (*e).ext.r#type(),
cache: wasm_externtype_t_type_cache::Empty,
});
Box::into_raw(et)
@@ -1175,15 +1174,18 @@ 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 {
let g = Box::new(wasm_global_t {
global: (*e).ext.borrow().global().clone(),
});
let global = if let Some(g) = (*e).ext.global() {
g.clone()
} else {
return ptr::null_mut();
};
let g = Box::new(wasm_global_t { global });
Box::into_raw(g)
}
#[no_mangle]
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
let ext = Rc::new(RefCell::new(Extern::Global((*g).global.clone())));
let ext = (*g).global.clone().into();
let ext = Box::new(wasm_extern_t { ext });
Box::into_raw(ext)
}
@@ -1203,7 +1205,7 @@ pub unsafe extern "C" fn wasm_global_same(
g1: *const wasm_global_t,
g2: *const wasm_global_t,
) -> bool {
(*g1).global.as_ptr() == (*g2).global.as_ptr()
(*g1).global.ptr_eq(&(*g2).global)
}
#[no_mangle]
@@ -1212,11 +1214,11 @@ pub unsafe extern "C" fn wasm_global_new(
gt: *const wasm_globaltype_t,
val: *const wasm_val_t,
) -> *mut wasm_global_t {
let global = Rc::new(RefCell::new(Global::new(
let global = HostRef::new(Global::new(
(*store).store.clone(),
(*gt).globaltype.clone(),
(*val).val(),
)));
));
let g = Box::new(wasm_global_t { global });
Box::into_raw(g)
}
@@ -1258,9 +1260,12 @@ 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 {
let g = Box::new(wasm_memory_t {
memory: (*e).ext.borrow().memory().clone(),
});
let memory = if let Some(m) = (*e).ext.memory() {
m.clone()
} else {
return ptr::null_mut();
};
let g = Box::new(wasm_memory_t { memory });
Box::into_raw(g)
}
@@ -1279,12 +1284,12 @@ pub unsafe extern "C" fn wasm_memory_same(
m1: *const wasm_memory_t,
m2: *const wasm_memory_t,
) -> bool {
(*m1).memory.as_ptr() == (*m2).memory.as_ptr()
(*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()
(*m).memory.borrow().data_ptr()
}
#[no_mangle]
@@ -1310,10 +1315,10 @@ pub unsafe extern "C" fn wasm_memory_new(
store: *mut wasm_store_t,
mt: *const wasm_memorytype_t,
) -> *mut wasm_memory_t {
let memory = Rc::new(RefCell::new(Memory::new(
let memory = HostRef::new(Memory::new(
(*store).store.clone(),
(*mt).memorytype.clone(),
)));
));
let m = Box::new(wasm_memory_t { memory });
Box::into_raw(m)
}
@@ -1337,18 +1342,19 @@ 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 {
let t = Box::new(wasm_table_t {
table: (*e).ext.borrow().table().clone(),
});
let table = if let Some(t) = (*e).ext.table() {
t.clone()
} else {
return ptr::null_mut();
};
let t = Box::new(wasm_table_t { table });
Box::into_raw(t)
}
#[no_mangle]
pub unsafe extern "C" fn wasm_func_as_ref(f: *mut wasm_func_t) -> *mut wasm_ref_t {
let callable = (*f).func.borrow().callable().clone();
let f = Box::new(wasm_ref_t {
r: AnyRef::Func(FuncRef(callable)),
});
let r = (*f).func.anyref();
let f = Box::new(wasm_ref_t { r });
Box::into_raw(f)
}
@@ -1381,11 +1387,11 @@ pub unsafe extern "C" fn wasm_table_new(
Val::AnyRef(AnyRef::Null)
};
let t = Box::new(wasm_table_t {
table: Rc::new(RefCell::new(Table::new(
table: HostRef::new(Table::new(
(*store).store.clone(),
(*tt).tabletype.clone(),
init,
))),
)),
});
Box::into_raw(t)
}
@@ -1442,7 +1448,7 @@ pub unsafe extern "C" fn wasm_table_grow(
#[no_mangle]
pub unsafe extern "C" fn wasm_table_same(t1: *const wasm_table_t, t2: *const wasm_table_t) -> bool {
(*t1).table.as_ptr() == (*t2).table.as_ptr()
(*t1).table.ptr_eq(&(*t2).table)
}
#[no_mangle]
@@ -1464,3 +1470,33 @@ pub unsafe extern "C" fn wasm_tabletype_new(
});
Box::into_raw(tt)
}
struct HostInfoState {
info: *mut ::std::os::raw::c_void,
finalizer: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
}
impl HostInfo for HostInfoState {
fn finalize(&mut self) {
if let Some(f) = &self.finalizer {
unsafe {
f(self.info);
}
}
}
}
#[no_mangle]
pub unsafe extern "C" fn wasm_instance_set_host_info_with_finalizer(
instance: *mut wasm_instance_t,
info: *mut ::std::os::raw::c_void,
finalizer: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
) {
let info = if info.is_null() && finalizer.is_none() {
None
} else {
let b: Box<dyn HostInfo> = Box::new(HostInfoState { info, finalizer });
Some(b)
};
(*instance).instance.anyref().set_host_info(info);
}