Add examples; refactor HostRef
This commit is contained in:
committed by
Dan Gohman
parent
042c87763e
commit
6a41417b52
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
72
wasmtime-api/examples/hello.rs
Normal file
72
wasmtime-api/examples/hello.rs
Normal 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(())
|
||||
}
|
||||
BIN
wasmtime-api/examples/hello.wasm
Normal file
BIN
wasmtime-api/examples/hello.wasm
Normal file
Binary file not shown.
4
wasmtime-api/examples/hello.wat
Normal file
4
wasmtime-api/examples/hello.wat
Normal file
@@ -0,0 +1,4 @@
|
||||
(module
|
||||
(func $hello (import "" "hello"))
|
||||
(func (export "run") (call $hello))
|
||||
)
|
||||
158
wasmtime-api/examples/memory.rs
Normal file
158
wasmtime-api/examples/memory.rs
Normal 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(())
|
||||
}
|
||||
BIN
wasmtime-api/examples/memory.wasm
Normal file
BIN
wasmtime-api/examples/memory.wasm
Normal file
Binary file not shown.
11
wasmtime-api/examples/memory.wat
Normal file
11
wasmtime-api/examples/memory.wat
Normal 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")
|
||||
)
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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((
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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
210
wasmtime-api/src/ref.rs
Normal 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, ")")
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user