Remove the need for HostRef<Store> (#771)
* Remove the need for `HostRef<Store>` This commit goes through the public API of the `wasmtime` crate and removes the need for `HostRef<Store>`, as discussed in #708. This commit is accompanied with a few changes: * The `Store` type now also implements `Default`, creating a new `Engine` with default settings and returning that. * The `Store` type now implements `Clone`, and is documented as being a "cheap clone" aka being reference counted. As before there is no supported way to create a deep clone of a `Store`. * All APIs take/return `&Store` or `Store` instead of `HostRef<Store>`, and `HostRef<T>` is left as purely a detail of the C API. * The `global_exports` function is tagged as `#[doc(hidden)]` for now while we await its removal. * The `Store` type is not yet `Send` nor `Sync` due to the usage of `global_exports`, but it is intended to become so eventually. * Touch up comments on some examples * Run rustfmt
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
//! Example of instantiating of the WebAssembly module and
|
//! Example of instantiating of the WebAssembly module and
|
||||||
//! invoking its exported function.
|
//! invoking its exported function.
|
||||||
|
|
||||||
use anyhow::{format_err, Result};
|
|
||||||
use wasmtime::*;
|
use wasmtime::*;
|
||||||
|
|
||||||
const WAT: &str = r#"
|
const WAT: &str = r#"
|
||||||
@@ -34,14 +33,11 @@ const WAT: &str = r#"
|
|||||||
)
|
)
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
|
// Load our WebAssembly (parsed WAT in our case), and then load it into a
|
||||||
|
// `Module` which is attached to a `Store` cache.
|
||||||
let wasm = wat::parse_str(WAT)?;
|
let wasm = wat::parse_str(WAT)?;
|
||||||
|
let store = Store::default();
|
||||||
// Instantiate engine and store.
|
|
||||||
let engine = Engine::default();
|
|
||||||
let store = HostRef::new(Store::new(&engine));
|
|
||||||
|
|
||||||
// Load a module.
|
|
||||||
let module = HostRef::new(Module::new(&store, &wasm)?);
|
let module = HostRef::new(Module::new(&store, &wasm)?);
|
||||||
|
|
||||||
// Find index of the `gcd` export.
|
// Find index of the `gcd` export.
|
||||||
@@ -59,10 +55,7 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
// Invoke `gcd` export
|
// Invoke `gcd` export
|
||||||
let gcd = instance.exports()[gcd_index].func().expect("gcd");
|
let gcd = instance.exports()[gcd_index].func().expect("gcd");
|
||||||
let result = gcd
|
let result = gcd.borrow().call(&[Val::from(6i32), Val::from(27i32)])?;
|
||||||
.borrow()
|
|
||||||
.call(&[Val::from(6i32), Val::from(27i32)])
|
|
||||||
.map_err(|e| format_err!("call error: {:?}", e))?;
|
|
||||||
|
|
||||||
println!("{:?}", result);
|
println!("{:?}", result);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Translation of hello example
|
//! Translation of hello example
|
||||||
|
|
||||||
use anyhow::{ensure, format_err, Context as _, Result};
|
use anyhow::{ensure, Context as _, Result};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wasmtime::*;
|
use wasmtime::*;
|
||||||
|
|
||||||
@@ -15,11 +15,11 @@ impl Callable for HelloCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
// Configure the initial compilation environment, creating more global
|
// Configure the initial compilation environment, creating the global
|
||||||
// structures such as an `Engine` and a `Store`.
|
// `Store` structure. Note that you can also tweak configuration settings
|
||||||
|
// with a `Config` and an `Engine` if desired.
|
||||||
println!("Initializing...");
|
println!("Initializing...");
|
||||||
let engine = Engine::default();
|
let store = Store::default();
|
||||||
let store = HostRef::new(Store::new(&engine));
|
|
||||||
|
|
||||||
// Next upload the `*.wasm` binary file, which in this case we're going to
|
// Next upload the `*.wasm` binary file, which in this case we're going to
|
||||||
// be parsing an inline text format into a binary.
|
// be parsing an inline text format into a binary.
|
||||||
@@ -59,10 +59,7 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
// And last but not least we can call it!
|
// And last but not least we can call it!
|
||||||
println!("Calling export...");
|
println!("Calling export...");
|
||||||
run_func
|
run_func.borrow().call(&[])?;
|
||||||
.borrow()
|
|
||||||
.call(&[])
|
|
||||||
.map_err(|e| format_err!("> Error calling function: {:?}", e))?;
|
|
||||||
|
|
||||||
println!("Done.");
|
println!("Done.");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -62,8 +62,7 @@ macro_rules! call {
|
|||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
// Initialize.
|
// Initialize.
|
||||||
println!("Initializing...");
|
println!("Initializing...");
|
||||||
let engine = Engine::default();
|
let store = Store::default();
|
||||||
let store = HostRef::new(Store::new(&engine));
|
|
||||||
|
|
||||||
// Load binary.
|
// Load binary.
|
||||||
println!("Loading binary...");
|
println!("Loading binary...");
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ fn main() -> Result<()> {
|
|||||||
// Initialize.
|
// Initialize.
|
||||||
println!("Initializing...");
|
println!("Initializing...");
|
||||||
let engine = Engine::new(Config::new().wasm_multi_value(true));
|
let engine = Engine::new(Config::new().wasm_multi_value(true));
|
||||||
let store = HostRef::new(Store::new(&engine));
|
let store = Store::new(&engine);
|
||||||
|
|
||||||
// Load binary.
|
// Load binary.
|
||||||
println!("Loading binary...");
|
println!("Loading binary...");
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ use wasmtime_runtime::Export;
|
|||||||
/// "#)?;
|
/// "#)?;
|
||||||
///
|
///
|
||||||
/// // Initialise environment and our module.
|
/// // Initialise environment and our module.
|
||||||
/// let engine = wasmtime::Engine::default();
|
/// let store = wasmtime::Store::default();
|
||||||
/// let store = HostRef::new(wasmtime::Store::new(&engine));
|
|
||||||
/// let module = HostRef::new(wasmtime::Module::new(&store, &binary)?);
|
/// let module = HostRef::new(wasmtime::Module::new(&store, &binary)?);
|
||||||
///
|
///
|
||||||
/// // Define the type of the function we're going to call.
|
/// // Define the type of the function we're going to call.
|
||||||
@@ -103,13 +102,13 @@ pub(crate) trait WrappedCallable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct WasmtimeFn {
|
pub(crate) struct WasmtimeFn {
|
||||||
store: HostRef<Store>,
|
store: Store,
|
||||||
instance: InstanceHandle,
|
instance: InstanceHandle,
|
||||||
export: Export,
|
export: Export,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmtimeFn {
|
impl WasmtimeFn {
|
||||||
pub fn new(store: &HostRef<Store>, instance: InstanceHandle, export: Export) -> WasmtimeFn {
|
pub fn new(store: &Store, instance: InstanceHandle, export: Export) -> WasmtimeFn {
|
||||||
WasmtimeFn {
|
WasmtimeFn {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
instance,
|
instance,
|
||||||
@@ -146,7 +145,6 @@ impl WrappedCallable for WasmtimeFn {
|
|||||||
// Get the trampoline to call for this function.
|
// Get the trampoline to call for this function.
|
||||||
let exec_code_buf = self
|
let exec_code_buf = self
|
||||||
.store
|
.store
|
||||||
.borrow_mut()
|
|
||||||
.context()
|
.context()
|
||||||
.compiler()
|
.compiler()
|
||||||
.get_published_trampoline(body, &signature, value_size)
|
.get_published_trampoline(body, &signature, value_size)
|
||||||
@@ -191,11 +189,7 @@ pub struct NativeCallable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NativeCallable {
|
impl NativeCallable {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(callable: Rc<dyn Callable + 'static>, ft: &FuncType, store: &Store) -> Self {
|
||||||
callable: Rc<dyn Callable + 'static>,
|
|
||||||
ft: &FuncType,
|
|
||||||
store: &HostRef<Store>,
|
|
||||||
) -> Self {
|
|
||||||
let (instance, export) =
|
let (instance, export) =
|
||||||
generate_func_export(ft, &callable, store).expect("generated func");
|
generate_func_export(ft, &callable, store).expect("generated func");
|
||||||
NativeCallable {
|
NativeCallable {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ impl Context {
|
|||||||
self.debug_info
|
self.debug_info
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compiler(&mut self) -> RefMut<Compiler> {
|
pub(crate) fn compiler(&self) -> RefMut<Compiler> {
|
||||||
self.compiler.borrow_mut()
|
self.compiler.borrow_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ impl Extern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_wasmtime_export(
|
pub(crate) fn from_wasmtime_export(
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
instance_handle: InstanceHandle,
|
instance_handle: InstanceHandle,
|
||||||
export: wasmtime_runtime::Export,
|
export: wasmtime_runtime::Export,
|
||||||
) -> Extern {
|
) -> Extern {
|
||||||
@@ -112,19 +112,19 @@ impl From<HostRef<Table>> for Extern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Func {
|
pub struct Func {
|
||||||
_store: HostRef<Store>,
|
_store: Store,
|
||||||
callable: Rc<dyn WrappedCallable + 'static>,
|
callable: Rc<dyn WrappedCallable + 'static>,
|
||||||
r#type: FuncType,
|
r#type: FuncType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Func {
|
impl Func {
|
||||||
pub fn new(store: &HostRef<Store>, ty: FuncType, callable: Rc<dyn Callable + 'static>) -> Self {
|
pub fn new(store: &Store, ty: FuncType, callable: Rc<dyn Callable + 'static>) -> Self {
|
||||||
let callable = Rc::new(NativeCallable::new(callable, &ty, &store));
|
let callable = Rc::new(NativeCallable::new(callable, &ty, &store));
|
||||||
Func::from_wrapped(store, ty, callable)
|
Func::from_wrapped(store, ty, callable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_wrapped(
|
fn from_wrapped(
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
r#type: FuncType,
|
r#type: FuncType,
|
||||||
callable: Rc<dyn WrappedCallable + 'static>,
|
callable: Rc<dyn WrappedCallable + 'static>,
|
||||||
) -> Func {
|
) -> Func {
|
||||||
@@ -159,7 +159,7 @@ impl Func {
|
|||||||
|
|
||||||
pub(crate) fn from_wasmtime_function(
|
pub(crate) fn from_wasmtime_function(
|
||||||
export: wasmtime_runtime::Export,
|
export: wasmtime_runtime::Export,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
instance_handle: InstanceHandle,
|
instance_handle: InstanceHandle,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let ty = if let wasmtime_runtime::Export::Function { signature, .. } = &export {
|
let ty = if let wasmtime_runtime::Export::Function { signature, .. } = &export {
|
||||||
@@ -179,7 +179,7 @@ impl fmt::Debug for Func {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Global {
|
pub struct Global {
|
||||||
_store: HostRef<Store>,
|
_store: Store,
|
||||||
r#type: GlobalType,
|
r#type: GlobalType,
|
||||||
wasmtime_export: wasmtime_runtime::Export,
|
wasmtime_export: wasmtime_runtime::Export,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -187,7 +187,7 @@ pub struct Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
pub fn new(store: &HostRef<Store>, r#type: GlobalType, val: Val) -> Global {
|
pub fn new(store: &Store, r#type: GlobalType, val: Val) -> Global {
|
||||||
let (wasmtime_export, wasmtime_state) =
|
let (wasmtime_export, wasmtime_state) =
|
||||||
generate_global_export(&r#type, val).expect("generated global");
|
generate_global_export(&r#type, val).expect("generated global");
|
||||||
Global {
|
Global {
|
||||||
@@ -246,10 +246,7 @@ impl Global {
|
|||||||
&self.wasmtime_export
|
&self.wasmtime_export
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_wasmtime_global(
|
pub(crate) fn from_wasmtime_global(export: wasmtime_runtime::Export, store: &Store) -> Global {
|
||||||
export: wasmtime_runtime::Export,
|
|
||||||
store: &HostRef<Store>,
|
|
||||||
) -> Global {
|
|
||||||
let global = if let wasmtime_runtime::Export::Global { ref global, .. } = export {
|
let global = if let wasmtime_runtime::Export::Global { ref global, .. } = export {
|
||||||
global
|
global
|
||||||
} else {
|
} else {
|
||||||
@@ -266,7 +263,7 @@ impl Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
store: HostRef<Store>,
|
store: Store,
|
||||||
r#type: TableType,
|
r#type: TableType,
|
||||||
wasmtime_handle: InstanceHandle,
|
wasmtime_handle: InstanceHandle,
|
||||||
wasmtime_export: wasmtime_runtime::Export,
|
wasmtime_export: wasmtime_runtime::Export,
|
||||||
@@ -274,7 +271,7 @@ pub struct Table {
|
|||||||
|
|
||||||
fn get_table_item(
|
fn get_table_item(
|
||||||
handle: &InstanceHandle,
|
handle: &InstanceHandle,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
table_index: wasm::DefinedTableIndex,
|
table_index: wasm::DefinedTableIndex,
|
||||||
item_index: u32,
|
item_index: u32,
|
||||||
) -> Val {
|
) -> Val {
|
||||||
@@ -287,7 +284,7 @@ fn get_table_item(
|
|||||||
|
|
||||||
fn set_table_item(
|
fn set_table_item(
|
||||||
handle: &mut InstanceHandle,
|
handle: &mut InstanceHandle,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
table_index: wasm::DefinedTableIndex,
|
table_index: wasm::DefinedTableIndex,
|
||||||
item_index: u32,
|
item_index: u32,
|
||||||
val: Val,
|
val: Val,
|
||||||
@@ -302,7 +299,7 @@ fn set_table_item(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Table {
|
impl Table {
|
||||||
pub fn new(store: &HostRef<Store>, r#type: TableType, init: Val) -> Table {
|
pub fn new(store: &Store, r#type: TableType, init: Val) -> Table {
|
||||||
match r#type.element() {
|
match r#type.element() {
|
||||||
ValType::FuncRef => (),
|
ValType::FuncRef => (),
|
||||||
_ => panic!("table is not for funcref"),
|
_ => panic!("table is not for funcref"),
|
||||||
@@ -387,7 +384,7 @@ impl Table {
|
|||||||
|
|
||||||
pub(crate) fn from_wasmtime_table(
|
pub(crate) fn from_wasmtime_table(
|
||||||
export: wasmtime_runtime::Export,
|
export: wasmtime_runtime::Export,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
instance_handle: wasmtime_runtime::InstanceHandle,
|
instance_handle: wasmtime_runtime::InstanceHandle,
|
||||||
) -> Table {
|
) -> Table {
|
||||||
let table = if let wasmtime_runtime::Export::Table { ref table, .. } = export {
|
let table = if let wasmtime_runtime::Export::Table { ref table, .. } = export {
|
||||||
@@ -406,14 +403,14 @@ impl Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
_store: HostRef<Store>,
|
_store: Store,
|
||||||
r#type: MemoryType,
|
r#type: MemoryType,
|
||||||
wasmtime_handle: InstanceHandle,
|
wasmtime_handle: InstanceHandle,
|
||||||
wasmtime_export: wasmtime_runtime::Export,
|
wasmtime_export: wasmtime_runtime::Export,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Memory {
|
impl Memory {
|
||||||
pub fn new(store: &HostRef<Store>, r#type: MemoryType) -> Memory {
|
pub fn new(store: &Store, r#type: MemoryType) -> Memory {
|
||||||
let (wasmtime_handle, wasmtime_export) =
|
let (wasmtime_handle, wasmtime_export) =
|
||||||
generate_memory_export(&r#type).expect("generated memory");
|
generate_memory_export(&r#type).expect("generated memory");
|
||||||
Memory {
|
Memory {
|
||||||
@@ -473,7 +470,7 @@ impl Memory {
|
|||||||
|
|
||||||
pub(crate) fn from_wasmtime_memory(
|
pub(crate) fn from_wasmtime_memory(
|
||||||
export: wasmtime_runtime::Export,
|
export: wasmtime_runtime::Export,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
instance_handle: wasmtime_runtime::InstanceHandle,
|
instance_handle: wasmtime_runtime::InstanceHandle,
|
||||||
) -> Memory {
|
) -> Memory {
|
||||||
let memory = if let wasmtime_runtime::Export::Memory { ref memory, .. } = export {
|
let memory = if let wasmtime_runtime::Export::Memory { ref memory, .. } = export {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ impl Resolver for SimpleResolver {
|
|||||||
pub fn instantiate_in_context(
|
pub fn instantiate_in_context(
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
imports: Vec<(String, String, Extern)>,
|
imports: Vec<(String, String, Extern)>,
|
||||||
mut context: Context,
|
context: Context,
|
||||||
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
||||||
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
|
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
|
||||||
let mut contexts = HashSet::new();
|
let mut contexts = HashSet::new();
|
||||||
@@ -70,12 +70,12 @@ pub struct Instance {
|
|||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
module: &HostRef<Module>,
|
module: &HostRef<Module>,
|
||||||
externs: &[Extern],
|
externs: &[Extern],
|
||||||
) -> Result<Instance, Error> {
|
) -> Result<Instance, Error> {
|
||||||
let context = store.borrow_mut().context().clone();
|
let context = store.context().clone();
|
||||||
let exports = store.borrow_mut().global_exports().clone();
|
let exports = store.global_exports().clone();
|
||||||
let imports = module
|
let imports = module
|
||||||
.borrow()
|
.borrow()
|
||||||
.imports()
|
.imports()
|
||||||
@@ -131,7 +131,7 @@ impl Instance {
|
|||||||
Some(&self.exports()[i])
|
Some(&self.exports()[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_handle(store: &HostRef<Store>, instance_handle: InstanceHandle) -> Instance {
|
pub fn from_handle(store: &Store, instance_handle: InstanceHandle) -> Instance {
|
||||||
let contexts = HashSet::new();
|
let contexts = HashSet::new();
|
||||||
|
|
||||||
let mut exports = Vec::new();
|
let mut exports = Vec::new();
|
||||||
@@ -143,7 +143,7 @@ impl Instance {
|
|||||||
// HACK ensure all handles, instantiated outside Store, present in
|
// HACK ensure all handles, instantiated outside Store, present in
|
||||||
// the store's SignatureRegistry, e.g. WASI instances that are
|
// the store's SignatureRegistry, e.g. WASI instances that are
|
||||||
// imported into this store using the from_handle() method.
|
// imported into this store using the from_handle() method.
|
||||||
let _ = store.borrow_mut().register_wasmtime_signature(signature);
|
let _ = store.register_wasmtime_signature(signature);
|
||||||
}
|
}
|
||||||
let extern_type = ExternType::from_wasmtime_export(&export);
|
let extern_type = ExternType::from_wasmtime_export(&export);
|
||||||
exports_types.push(ExportType::new(name, extern_type));
|
exports_types.push(ExportType::new(name, extern_type));
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::r#ref::HostRef;
|
|
||||||
use crate::runtime::Store;
|
use crate::runtime::Store;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ExportType, ExternType, FuncType, GlobalType, ImportType, Limits, MemoryType, Mutability,
|
ExportType, ExternType, FuncType, GlobalType, ImportType, Limits, MemoryType, Mutability,
|
||||||
@@ -173,7 +172,7 @@ pub(crate) enum ModuleCodeSource {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
store: HostRef<Store>,
|
store: Store,
|
||||||
source: ModuleCodeSource,
|
source: ModuleCodeSource,
|
||||||
imports: Box<[ImportType]>,
|
imports: Box<[ImportType]>,
|
||||||
exports: Box<[ExportType]>,
|
exports: Box<[ExportType]>,
|
||||||
@@ -182,13 +181,13 @@ pub struct Module {
|
|||||||
impl Module {
|
impl Module {
|
||||||
/// Validate and decode the raw wasm data in `binary` and create a new
|
/// Validate and decode the raw wasm data in `binary` and create a new
|
||||||
/// `Module` in the given `store`.
|
/// `Module` in the given `store`.
|
||||||
pub fn new(store: &HostRef<Store>, binary: &[u8]) -> Result<Module> {
|
pub fn new(store: &Store, binary: &[u8]) -> Result<Module> {
|
||||||
Self::validate(store, binary)?;
|
Self::validate(store, binary)?;
|
||||||
Self::new_unchecked(store, binary)
|
Self::new_unchecked(store, binary)
|
||||||
}
|
}
|
||||||
/// Similar to `new`, but does not perform any validation. Only use this
|
/// Similar to `new`, but does not perform any validation. Only use this
|
||||||
/// on modules which are known to have been validated already!
|
/// on modules which are known to have been validated already!
|
||||||
pub fn new_unchecked(store: &HostRef<Store>, binary: &[u8]) -> Result<Module> {
|
pub fn new_unchecked(store: &Store, binary: &[u8]) -> Result<Module> {
|
||||||
let (imports, exports) = read_imports_and_exports(binary)?;
|
let (imports, exports) = read_imports_and_exports(binary)?;
|
||||||
Ok(Module {
|
Ok(Module {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
@@ -203,8 +202,8 @@ impl Module {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn validate(store: &HostRef<Store>, binary: &[u8]) -> Result<()> {
|
pub fn validate(store: &Store, binary: &[u8]) -> Result<()> {
|
||||||
let features = store.borrow().engine().config.features.clone();
|
let features = store.engine().config.features.clone();
|
||||||
let config = ValidatingParserConfig {
|
let config = ValidatingParserConfig {
|
||||||
operator_config: OperatorValidatorConfig {
|
operator_config: OperatorValidatorConfig {
|
||||||
enable_threads: features.threads,
|
enable_threads: features.threads,
|
||||||
@@ -222,7 +221,7 @@ impl Module {
|
|||||||
pub fn exports(&self) -> &[ExportType] {
|
pub fn exports(&self) -> &[ExportType] {
|
||||||
&self.exports
|
&self.exports
|
||||||
}
|
}
|
||||||
pub fn from_exports(store: &HostRef<Store>, exports: Box<[ExportType]>) -> Self {
|
pub fn from_exports(store: &Store, exports: Box<[ExportType]>) -> Self {
|
||||||
Module {
|
Module {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
source: ModuleCodeSource::Unknown,
|
source: ModuleCodeSource::Unknown,
|
||||||
|
|||||||
@@ -288,12 +288,13 @@ pub enum OptLevel {
|
|||||||
///
|
///
|
||||||
/// Using `clone` on an `Engine` is a cheap operation. It will not create an
|
/// Using `clone` on an `Engine` is a cheap operation. It will not create an
|
||||||
/// entirely new engine, but rather just a new reference to the existing engine.
|
/// entirely new engine, but rather just a new reference to the existing engine.
|
||||||
|
/// In other words it's a shallow copy, not a deep copy.
|
||||||
///
|
///
|
||||||
/// ## Engines and `Default`
|
/// ## Engines and `Default`
|
||||||
///
|
///
|
||||||
/// You can create an engine with default settings using `Engine::default()`.
|
/// You can create an engine with default configuration settings using
|
||||||
/// This engine will not have any unstable wasm features enabled and will use
|
/// `Engine::default()`. Be sure to consult the documentation of [`Config`] for
|
||||||
/// the default compilation backend configured at this crate's compile time.
|
/// default settings.
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
pub(crate) config: Arc<Config>,
|
pub(crate) config: Arc<Config>,
|
||||||
@@ -311,45 +312,72 @@ impl Engine {
|
|||||||
|
|
||||||
// Store
|
// Store
|
||||||
|
|
||||||
|
/// A `Store` is a shared cache of information between WebAssembly modules.
|
||||||
|
///
|
||||||
|
/// Each `Module` is compiled into a `Store` and a `Store` is associated with an
|
||||||
|
/// [`Engine`]. You'll use a `Store` to attach to a number of global items in
|
||||||
|
/// the production of various items for wasm modules.
|
||||||
|
///
|
||||||
|
/// # Stores and `Clone`
|
||||||
|
///
|
||||||
|
/// Using `clone` on a `Store` is a cheap operation. It will not create an
|
||||||
|
/// entirely new store, but rather just a new reference to the existing object.
|
||||||
|
/// In other words it's a shallow copy, not a deep copy.
|
||||||
|
///
|
||||||
|
/// ## Stores and `Default`
|
||||||
|
///
|
||||||
|
/// You can create a store with default configuration settings using
|
||||||
|
/// `Store::default()`. This will create a brand new [`Engine`] with default
|
||||||
|
/// ocnfiguration (see [`Config`] for more information).
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Store {
|
pub struct Store {
|
||||||
|
inner: Rc<StoreInner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StoreInner {
|
||||||
engine: Engine,
|
engine: Engine,
|
||||||
context: Context,
|
context: Context,
|
||||||
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
||||||
signature_cache: HashMap<wasmtime_runtime::VMSharedSignatureIndex, ir::Signature>,
|
signature_cache: RefCell<HashMap<wasmtime_runtime::VMSharedSignatureIndex, ir::Signature>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Store {
|
impl Store {
|
||||||
|
/// Creates a new store to be associated with the given [`Engine`].
|
||||||
pub fn new(engine: &Engine) -> Store {
|
pub fn new(engine: &Engine) -> Store {
|
||||||
Store {
|
Store {
|
||||||
|
inner: Rc::new(StoreInner {
|
||||||
engine: engine.clone(),
|
engine: engine.clone(),
|
||||||
context: Context::new(&engine.config),
|
context: Context::new(&engine.config),
|
||||||
global_exports: Rc::new(RefCell::new(HashMap::new())),
|
global_exports: Rc::new(RefCell::new(HashMap::new())),
|
||||||
signature_cache: HashMap::new(),
|
signature_cache: RefCell::new(HashMap::new()),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [`Engine`] that this store is associated with.
|
||||||
pub fn engine(&self) -> &Engine {
|
pub fn engine(&self) -> &Engine {
|
||||||
&self.engine
|
&self.inner.engine
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn context(&mut self) -> &mut Context {
|
pub(crate) fn context(&self) -> &Context {
|
||||||
&mut self.context
|
&self.inner.context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specific to wasmtime: hack to pass memory around to wasi
|
// Specific to wasmtime: hack to pass memory around to wasi
|
||||||
|
#[doc(hidden)]
|
||||||
pub fn global_exports(
|
pub fn global_exports(
|
||||||
&self,
|
&self,
|
||||||
) -> &Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>> {
|
) -> &Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>> {
|
||||||
&self.global_exports
|
&self.inner.global_exports
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn register_wasmtime_signature(
|
pub(crate) fn register_wasmtime_signature(
|
||||||
&mut self,
|
&self,
|
||||||
signature: &ir::Signature,
|
signature: &ir::Signature,
|
||||||
) -> wasmtime_runtime::VMSharedSignatureIndex {
|
) -> wasmtime_runtime::VMSharedSignatureIndex {
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
let index = self.context().compiler().signatures().register(signature);
|
let index = self.context().compiler().signatures().register(signature);
|
||||||
match self.signature_cache.entry(index) {
|
match self.inner.signature_cache.borrow_mut().entry(index) {
|
||||||
Entry::Vacant(v) => {
|
Entry::Vacant(v) => {
|
||||||
v.insert(signature.clone());
|
v.insert(signature.clone());
|
||||||
}
|
}
|
||||||
@@ -361,8 +389,18 @@ impl Store {
|
|||||||
pub(crate) fn lookup_wasmtime_signature(
|
pub(crate) fn lookup_wasmtime_signature(
|
||||||
&self,
|
&self,
|
||||||
type_index: wasmtime_runtime::VMSharedSignatureIndex,
|
type_index: wasmtime_runtime::VMSharedSignatureIndex,
|
||||||
) -> Option<&ir::Signature> {
|
) -> Option<ir::Signature> {
|
||||||
self.signature_cache.get(&type_index)
|
self.inner
|
||||||
|
.signature_cache
|
||||||
|
.borrow()
|
||||||
|
.get(&type_index)
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Store {
|
||||||
|
fn default() -> Store {
|
||||||
|
Store::new(&Engine::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use crate::runtime::Store;
|
use crate::runtime::Store;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wasmtime_environ::entity::PrimaryMap;
|
use wasmtime_environ::entity::PrimaryMap;
|
||||||
@@ -13,7 +13,7 @@ use wasmtime_runtime::{Imports, InstanceHandle, VMFunctionBody};
|
|||||||
|
|
||||||
pub(crate) fn create_handle(
|
pub(crate) fn create_handle(
|
||||||
module: Module,
|
module: Module,
|
||||||
signature_registry: Option<RefMut<Store>>,
|
signature_registry: Option<&Store>,
|
||||||
finished_functions: PrimaryMap<DefinedFuncIndex, *const VMFunctionBody>,
|
finished_functions: PrimaryMap<DefinedFuncIndex, *const VMFunctionBody>,
|
||||||
state: Box<dyn Any>,
|
state: Box<dyn Any>,
|
||||||
) -> Result<InstanceHandle> {
|
) -> Result<InstanceHandle> {
|
||||||
@@ -31,7 +31,7 @@ pub(crate) fn create_handle(
|
|||||||
|
|
||||||
// Compute indices into the shared signature table.
|
// Compute indices into the shared signature table.
|
||||||
let signatures = signature_registry
|
let signatures = signature_registry
|
||||||
.map(|mut signature_registry| {
|
.map(|signature_registry| {
|
||||||
module
|
module
|
||||||
.signatures
|
.signatures
|
||||||
.values()
|
.values()
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
use super::create_handle::create_handle;
|
use super::create_handle::create_handle;
|
||||||
use super::trap::{record_api_trap, TrapSink, API_TRAP_CODE};
|
use super::trap::{record_api_trap, TrapSink, API_TRAP_CODE};
|
||||||
use crate::r#ref::HostRef;
|
|
||||||
use crate::{Callable, FuncType, Store, Val};
|
use crate::{Callable, FuncType, Store, Val};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@@ -234,7 +233,7 @@ fn make_trampoline(
|
|||||||
pub fn create_handle_with_function(
|
pub fn create_handle_with_function(
|
||||||
ft: &FuncType,
|
ft: &FuncType,
|
||||||
func: &Rc<dyn Callable + 'static>,
|
func: &Rc<dyn Callable + 'static>,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
) -> Result<InstanceHandle> {
|
) -> Result<InstanceHandle> {
|
||||||
let sig = ft.get_wasmtime_signature().clone();
|
let sig = ft.get_wasmtime_signature().clone();
|
||||||
|
|
||||||
@@ -270,7 +269,7 @@ pub fn create_handle_with_function(
|
|||||||
|
|
||||||
create_handle(
|
create_handle(
|
||||||
module,
|
module,
|
||||||
Some(store.borrow_mut()),
|
Some(store),
|
||||||
finished_functions,
|
finished_functions,
|
||||||
Box::new(trampoline_state),
|
Box::new(trampoline_state),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ use self::global::create_global;
|
|||||||
use self::memory::create_handle_with_memory;
|
use self::memory::create_handle_with_memory;
|
||||||
use self::table::create_handle_with_table;
|
use self::table::create_handle_with_table;
|
||||||
use super::{Callable, FuncType, GlobalType, MemoryType, Store, TableType, Val};
|
use super::{Callable, FuncType, GlobalType, MemoryType, Store, TableType, Val};
|
||||||
use crate::r#ref::HostRef;
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@@ -22,7 +21,7 @@ pub use self::trap::take_api_trap;
|
|||||||
pub fn generate_func_export(
|
pub fn generate_func_export(
|
||||||
ft: &FuncType,
|
ft: &FuncType,
|
||||||
func: &Rc<dyn Callable + 'static>,
|
func: &Rc<dyn Callable + 'static>,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
) -> Result<(wasmtime_runtime::InstanceHandle, wasmtime_runtime::Export)> {
|
) -> Result<(wasmtime_runtime::InstanceHandle, wasmtime_runtime::Export)> {
|
||||||
let mut instance = create_handle_with_function(ft, func, store)?;
|
let mut instance = create_handle_with_function(ft, func, store)?;
|
||||||
let export = instance.lookup("trampoline").expect("trampoline export");
|
let export = instance.lookup("trampoline").expect("trampoline export");
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ impl From<RuntimeValue> for Val {
|
|||||||
|
|
||||||
pub(crate) fn into_checked_anyfunc(
|
pub(crate) fn into_checked_anyfunc(
|
||||||
val: Val,
|
val: Val,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
) -> wasmtime_runtime::VMCallerCheckedAnyfunc {
|
) -> wasmtime_runtime::VMCallerCheckedAnyfunc {
|
||||||
match val {
|
match val {
|
||||||
Val::AnyRef(AnyRef::Null) => wasmtime_runtime::VMCallerCheckedAnyfunc {
|
Val::AnyRef(AnyRef::Null) => wasmtime_runtime::VMCallerCheckedAnyfunc {
|
||||||
@@ -215,7 +215,7 @@ pub(crate) fn into_checked_anyfunc(
|
|||||||
} => (*vmctx, *address, signature),
|
} => (*vmctx, *address, signature),
|
||||||
_ => panic!("expected function export"),
|
_ => panic!("expected function export"),
|
||||||
};
|
};
|
||||||
let type_index = store.borrow_mut().register_wasmtime_signature(signature);
|
let type_index = store.register_wasmtime_signature(signature);
|
||||||
wasmtime_runtime::VMCallerCheckedAnyfunc {
|
wasmtime_runtime::VMCallerCheckedAnyfunc {
|
||||||
func_ptr,
|
func_ptr,
|
||||||
type_index,
|
type_index,
|
||||||
@@ -228,16 +228,14 @@ pub(crate) fn into_checked_anyfunc(
|
|||||||
|
|
||||||
pub(crate) fn from_checked_anyfunc(
|
pub(crate) fn from_checked_anyfunc(
|
||||||
item: &wasmtime_runtime::VMCallerCheckedAnyfunc,
|
item: &wasmtime_runtime::VMCallerCheckedAnyfunc,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
) -> Val {
|
) -> Val {
|
||||||
if item.type_index == wasmtime_runtime::VMSharedSignatureIndex::default() {
|
if item.type_index == wasmtime_runtime::VMSharedSignatureIndex::default() {
|
||||||
return Val::AnyRef(AnyRef::Null);
|
return Val::AnyRef(AnyRef::Null);
|
||||||
}
|
}
|
||||||
let signature = store
|
let signature = store
|
||||||
.borrow()
|
|
||||||
.lookup_wasmtime_signature(item.type_index)
|
.lookup_wasmtime_signature(item.type_index)
|
||||||
.expect("signature")
|
.expect("signature");
|
||||||
.clone();
|
|
||||||
let instance_handle = unsafe { wasmtime_runtime::InstanceHandle::from_vmctx(item.vmctx) };
|
let instance_handle = unsafe { wasmtime_runtime::InstanceHandle::from_vmctx(item.vmctx) };
|
||||||
let export = wasmtime_runtime::Export::Function {
|
let export = wasmtime_runtime::Export::Function {
|
||||||
address: item.func_ptr,
|
address: item.func_ptr,
|
||||||
|
|||||||
@@ -609,7 +609,7 @@ pub unsafe extern "C" fn wasm_func_new(
|
|||||||
ty: *const wasm_functype_t,
|
ty: *const wasm_functype_t,
|
||||||
callback: wasm_func_callback_t,
|
callback: wasm_func_callback_t,
|
||||||
) -> *mut wasm_func_t {
|
) -> *mut wasm_func_t {
|
||||||
let store = &(*store).store;
|
let store = &(*store).store.borrow();
|
||||||
let ty = (*ty).functype.clone();
|
let ty = (*ty).functype.clone();
|
||||||
let callback = Rc::new(callback);
|
let callback = Rc::new(callback);
|
||||||
let func = Box::new(wasm_func_t {
|
let func = Box::new(wasm_func_t {
|
||||||
@@ -663,7 +663,7 @@ pub unsafe extern "C" fn wasm_instance_new(
|
|||||||
imports: *const *const wasm_extern_t,
|
imports: *const *const wasm_extern_t,
|
||||||
result: *mut *mut wasm_trap_t,
|
result: *mut *mut wasm_trap_t,
|
||||||
) -> *mut wasm_instance_t {
|
) -> *mut wasm_instance_t {
|
||||||
let store = &(*store).store;
|
let store = &(*store).store.borrow();
|
||||||
let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len());
|
let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len());
|
||||||
for i in 0..(*module).imports.len() {
|
for i in 0..(*module).imports.len() {
|
||||||
let import = *imports.add(i);
|
let import = *imports.add(i);
|
||||||
@@ -731,7 +731,7 @@ pub unsafe extern "C" fn wasm_module_new(
|
|||||||
binary: *const wasm_byte_vec_t,
|
binary: *const wasm_byte_vec_t,
|
||||||
) -> *mut wasm_module_t {
|
) -> *mut wasm_module_t {
|
||||||
let binary = (*binary).as_slice();
|
let binary = (*binary).as_slice();
|
||||||
let store = &(*store).store;
|
let store = &(*store).store.borrow();
|
||||||
let module = Module::new_unchecked(store, binary).expect("module");
|
let module = Module::new_unchecked(store, binary).expect("module");
|
||||||
let imports = module
|
let imports = module
|
||||||
.imports()
|
.imports()
|
||||||
@@ -765,7 +765,7 @@ pub unsafe extern "C" fn wasm_module_validate(
|
|||||||
binary: *const wasm_byte_vec_t,
|
binary: *const wasm_byte_vec_t,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let binary = (*binary).as_slice();
|
let binary = (*binary).as_slice();
|
||||||
let store = &(*store).store;
|
let store = &(*store).store.borrow();
|
||||||
Module::validate(store, binary).is_ok()
|
Module::validate(store, binary).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,7 +814,7 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
|
|||||||
env: *mut std::ffi::c_void,
|
env: *mut std::ffi::c_void,
|
||||||
finalizer: std::option::Option<unsafe extern "C" fn(arg1: *mut std::ffi::c_void)>,
|
finalizer: std::option::Option<unsafe extern "C" fn(arg1: *mut std::ffi::c_void)>,
|
||||||
) -> *mut wasm_func_t {
|
) -> *mut wasm_func_t {
|
||||||
let store = &(*store).store;
|
let store = &(*store).store.borrow();
|
||||||
let ty = (*ty).functype.clone();
|
let ty = (*ty).functype.clone();
|
||||||
let callback = Rc::new(CallbackWithEnv {
|
let callback = Rc::new(CallbackWithEnv {
|
||||||
callback,
|
callback,
|
||||||
@@ -1337,7 +1337,7 @@ pub unsafe extern "C" fn wasm_global_new(
|
|||||||
val: *const wasm_val_t,
|
val: *const wasm_val_t,
|
||||||
) -> *mut wasm_global_t {
|
) -> *mut wasm_global_t {
|
||||||
let global = HostRef::new(Global::new(
|
let global = HostRef::new(Global::new(
|
||||||
&(*store).store,
|
&(*store).store.borrow(),
|
||||||
(*gt).globaltype.clone(),
|
(*gt).globaltype.clone(),
|
||||||
(*val).val(),
|
(*val).val(),
|
||||||
));
|
));
|
||||||
@@ -1456,7 +1456,10 @@ pub unsafe extern "C" fn wasm_memory_new(
|
|||||||
store: *mut wasm_store_t,
|
store: *mut wasm_store_t,
|
||||||
mt: *const wasm_memorytype_t,
|
mt: *const wasm_memorytype_t,
|
||||||
) -> *mut wasm_memory_t {
|
) -> *mut wasm_memory_t {
|
||||||
let memory = HostRef::new(Memory::new(&(*store).store, (*mt).memorytype.clone()));
|
let memory = HostRef::new(Memory::new(
|
||||||
|
&(*store).store.borrow(),
|
||||||
|
(*mt).memorytype.clone(),
|
||||||
|
));
|
||||||
let m = Box::new(wasm_memory_t { memory, ext: None });
|
let m = Box::new(wasm_memory_t { memory, ext: None });
|
||||||
Box::into_raw(m)
|
Box::into_raw(m)
|
||||||
}
|
}
|
||||||
@@ -1549,7 +1552,11 @@ pub unsafe extern "C" fn wasm_table_new(
|
|||||||
Val::AnyRef(AnyRef::Null)
|
Val::AnyRef(AnyRef::Null)
|
||||||
};
|
};
|
||||||
let t = Box::new(wasm_table_t {
|
let t = Box::new(wasm_table_t {
|
||||||
table: HostRef::new(Table::new(&(*store).store, (*tt).tabletype.clone(), init)),
|
table: HostRef::new(Table::new(
|
||||||
|
&(*store).store.borrow(),
|
||||||
|
(*tt).tabletype.clone(),
|
||||||
|
init,
|
||||||
|
)),
|
||||||
ext: None,
|
ext: None,
|
||||||
});
|
});
|
||||||
Box::into_raw(t)
|
Box::into_raw(t)
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ fn test_import_calling_export() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let engine = Engine::default();
|
let store = Store::default();
|
||||||
let store = HostRef::new(Store::new(&engine));
|
|
||||||
let wasm = wat::parse_str(WAT).unwrap();
|
let wasm = wat::parse_str(WAT).unwrap();
|
||||||
let module = HostRef::new(Module::new(&store, &wasm).expect("failed to create module"));
|
let module = HostRef::new(Module::new(&store, &wasm).expect("failed to create module"));
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ fn test_trap_return() -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let engine = Engine::default();
|
let store = Store::default();
|
||||||
let store = HostRef::new(Store::new(&engine));
|
|
||||||
let binary = parse_str(
|
let binary = parse_str(
|
||||||
r#"
|
r#"
|
||||||
(module
|
(module
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ pub fn instantiate(wasm: &[u8], strategy: Strategy) {
|
|||||||
.strategy(strategy)
|
.strategy(strategy)
|
||||||
.expect("failed to enable lightbeam");
|
.expect("failed to enable lightbeam");
|
||||||
let engine = Engine::new(&config);
|
let engine = Engine::new(&config);
|
||||||
let store = HostRef::new(Store::new(&engine));
|
let store = Store::new(&engine);
|
||||||
|
|
||||||
let module =
|
let module =
|
||||||
HostRef::new(Module::new(&store, wasm).expect("Failed to compile a valid Wasm module!"));
|
HostRef::new(Module::new(&store, wasm).expect("Failed to compile a valid Wasm module!"));
|
||||||
@@ -91,7 +91,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
|
|||||||
|
|
||||||
let mut config: Option<Config> = None;
|
let mut config: Option<Config> = None;
|
||||||
let mut engine: Option<Engine> = None;
|
let mut engine: Option<Engine> = None;
|
||||||
let mut store: Option<HostRef<Store>> = None;
|
let mut store: Option<Store> = None;
|
||||||
let mut modules: HashMap<usize, HostRef<Module>> = Default::default();
|
let mut modules: HashMap<usize, HostRef<Module>> = Default::default();
|
||||||
let mut instances: HashMap<usize, HostRef<Instance>> = Default::default();
|
let mut instances: HashMap<usize, HostRef<Instance>> = Default::default();
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
|
|||||||
|
|
||||||
ApiCall::StoreNew => {
|
ApiCall::StoreNew => {
|
||||||
assert!(store.is_none());
|
assert!(store.is_none());
|
||||||
store = Some(HostRef::new(Store::new(engine.as_ref().unwrap())));
|
store = Some(Store::new(engine.as_ref().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiCall::ModuleNew { id, wasm } => {
|
ApiCall::ModuleNew { id, wasm } => {
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ use wasmtime::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Create a set of dummy functions/globals/etc for the given imports.
|
/// Create a set of dummy functions/globals/etc for the given imports.
|
||||||
pub fn dummy_imports(
|
pub fn dummy_imports(store: &Store, import_tys: &[ImportType]) -> Result<Vec<Extern>, Trap> {
|
||||||
store: &HostRef<Store>,
|
|
||||||
import_tys: &[ImportType],
|
|
||||||
) -> Result<Vec<Extern>, Trap> {
|
|
||||||
let mut imports = Vec::with_capacity(import_tys.len());
|
let mut imports = Vec::with_capacity(import_tys.len());
|
||||||
for imp in import_tys {
|
for imp in import_tys {
|
||||||
imports.push(match imp.ty() {
|
imports.push(match imp.ty() {
|
||||||
@@ -38,7 +35,7 @@ pub struct DummyFunc(FuncType);
|
|||||||
|
|
||||||
impl DummyFunc {
|
impl DummyFunc {
|
||||||
/// Construct a new dummy `Func`.
|
/// Construct a new dummy `Func`.
|
||||||
pub fn new(store: &HostRef<Store>, ty: FuncType) -> Func {
|
pub fn new(store: &Store, ty: FuncType) -> Func {
|
||||||
let callable = DummyFunc(ty.clone());
|
let callable = DummyFunc(ty.clone());
|
||||||
Func::new(store, ty, Rc::new(callable) as _)
|
Func::new(store, ty, Rc::new(callable) as _)
|
||||||
}
|
}
|
||||||
@@ -80,18 +77,18 @@ pub fn dummy_value(val_ty: &ValType) -> Result<Val, Trap> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy global for the given global type.
|
/// Construct a dummy global for the given global type.
|
||||||
pub fn dummy_global(store: &HostRef<Store>, ty: GlobalType) -> Result<Global, Trap> {
|
pub fn dummy_global(store: &Store, ty: GlobalType) -> Result<Global, Trap> {
|
||||||
let val = dummy_value(ty.content())?;
|
let val = dummy_value(ty.content())?;
|
||||||
Ok(Global::new(store, ty, val))
|
Ok(Global::new(store, ty, val))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy table for the given table type.
|
/// Construct a dummy table for the given table type.
|
||||||
pub fn dummy_table(store: &HostRef<Store>, ty: TableType) -> Result<Table, Trap> {
|
pub fn dummy_table(store: &Store, ty: TableType) -> Result<Table, Trap> {
|
||||||
let init_val = dummy_value(&ty.element())?;
|
let init_val = dummy_value(&ty.element())?;
|
||||||
Ok(Table::new(store, ty, init_val))
|
Ok(Table::new(store, ty, init_val))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy memory for the given memory type.
|
/// Construct a dummy memory for the given memory type.
|
||||||
pub fn dummy_memory(store: &HostRef<Store>, ty: MemoryType) -> Memory {
|
pub fn dummy_memory(store: &Store, ty: MemoryType) -> Memory {
|
||||||
Memory::new(store, ty)
|
Memory::new(store, ty)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ impl wasmtime::Callable for WrappedFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn wrap_into_pyfunction(
|
pub fn wrap_into_pyfunction(
|
||||||
store: &wasmtime::HostRef<wasmtime::Store>,
|
store: &wasmtime::Store,
|
||||||
callable: &PyAny,
|
callable: &PyAny,
|
||||||
) -> PyResult<wasmtime::HostRef<wasmtime::Func>> {
|
) -> PyResult<wasmtime::HostRef<wasmtime::Func>> {
|
||||||
if !callable.hasattr("__annotations__")? {
|
if !callable.hasattr("__annotations__")? {
|
||||||
|
|||||||
@@ -44,11 +44,7 @@ impl InstantiateResultObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_export_in(
|
fn find_export_in(obj: &PyAny, store: &wasmtime::Store, name: &str) -> PyResult<wasmtime::Extern> {
|
||||||
obj: &PyAny,
|
|
||||||
store: &wasmtime::HostRef<wasmtime::Store>,
|
|
||||||
name: &str,
|
|
||||||
) -> PyResult<wasmtime::Extern> {
|
|
||||||
let obj = obj.cast_as::<PyDict>()?;
|
let obj = obj.cast_as::<PyDict>()?;
|
||||||
|
|
||||||
Ok(if let Some(item) = obj.get_item(name) {
|
Ok(if let Some(item) = obj.get_item(name) {
|
||||||
@@ -86,7 +82,7 @@ pub fn instantiate(
|
|||||||
let wasm_data = buffer_source.as_bytes();
|
let wasm_data = buffer_source.as_bytes();
|
||||||
|
|
||||||
let engine = wasmtime::Engine::new(&wasmtime::Config::new().wasm_multi_value(true));
|
let engine = wasmtime::Engine::new(&wasmtime::Config::new().wasm_multi_value(true));
|
||||||
let store = wasmtime::HostRef::new(wasmtime::Store::new(&engine));
|
let store = wasmtime::Store::new(&engine);
|
||||||
|
|
||||||
let module = wasmtime::HostRef::new(wasmtime::Module::new(&store, wasm_data).map_err(err2py)?);
|
let module = wasmtime::HostRef::new(wasmtime::Module::new(&store, wasm_data).map_err(err2py)?);
|
||||||
|
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
|
|||||||
use #root::anyhow::{bail, format_err};
|
use #root::anyhow::{bail, format_err};
|
||||||
|
|
||||||
let engine = Engine::new(Config::new().wasm_multi_value(true));
|
let engine = Engine::new(Config::new().wasm_multi_value(true));
|
||||||
let store = HostRef::new(Store::new(&engine));
|
let store = Store::new(&engine);
|
||||||
let global_exports = store.borrow().global_exports().clone();
|
let global_exports = store.global_exports().clone();
|
||||||
|
|
||||||
let data = #root::wasmtime_interface_types::ModuleData::new(&bytes)?;
|
let data = #root::wasmtime_interface_types::ModuleData::new(&bytes)?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use anyhow::{bail, Context};
|
use anyhow::{bail, Context};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use wasmtime::{Engine, HostRef, Instance, Module, Store};
|
use wasmtime::{HostRef, Instance, Module, Store};
|
||||||
|
|
||||||
pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> {
|
pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> {
|
||||||
let engine = Engine::default();
|
let store = Store::default();
|
||||||
let store = HostRef::new(Store::new(&engine));
|
|
||||||
|
|
||||||
let global_exports = store.borrow().global_exports().clone();
|
let global_exports = store.global_exports().clone();
|
||||||
let get_preopens = |workspace: Option<&Path>| -> anyhow::Result<Vec<_>> {
|
let get_preopens = |workspace: Option<&Path>| -> anyhow::Result<Vec<_>> {
|
||||||
if let Some(workspace) = workspace {
|
if let Some(workspace) = workspace {
|
||||||
let preopen_dir = wasi_common::preopen_dir(workspace)
|
let preopen_dir = wasi_common::preopen_dir(workspace)
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ use wasmtime_runtime::{Imports, InstanceHandle, InstantiationError, VMContext};
|
|||||||
|
|
||||||
/// Creates `wasmtime::Instance` object implementing the "wasi" interface.
|
/// Creates `wasmtime::Instance` object implementing the "wasi" interface.
|
||||||
pub fn create_wasi_instance(
|
pub fn create_wasi_instance(
|
||||||
store: &wasmtime::HostRef<wasmtime::Store>,
|
store: &wasmtime::Store,
|
||||||
preopened_dirs: &[(String, File)],
|
preopened_dirs: &[(String, File)],
|
||||||
argv: &[String],
|
argv: &[String],
|
||||||
environ: &[(String, String)],
|
environ: &[(String, String)],
|
||||||
) -> Result<wasmtime::Instance, InstantiationError> {
|
) -> Result<wasmtime::Instance, InstantiationError> {
|
||||||
let global_exports = store.borrow().global_exports().clone();
|
let global_exports = store.global_exports().clone();
|
||||||
let wasi = instantiate_wasi(global_exports, preopened_dirs, argv, environ)?;
|
let wasi = instantiate_wasi(global_exports, preopened_dirs, argv, environ)?;
|
||||||
let instance = wasmtime::Instance::from_handle(&store, wasi);
|
let instance = wasmtime::Instance::from_handle(&store, wasi);
|
||||||
Ok(instance)
|
Ok(instance)
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ use wasmtime_runtime::{Imports, InstanceHandle, InstantiationError, VMFunctionBo
|
|||||||
|
|
||||||
/// Creates `wasmtime::Instance` object implementing the "wasi" interface.
|
/// Creates `wasmtime::Instance` object implementing the "wasi" interface.
|
||||||
pub fn create_wasi_instance(
|
pub fn create_wasi_instance(
|
||||||
store: &wasmtime::HostRef<wasmtime::Store>,
|
store: &wasmtime::Store,
|
||||||
preopened_dirs: &[(String, File)],
|
preopened_dirs: &[(String, File)],
|
||||||
argv: &[String],
|
argv: &[String],
|
||||||
environ: &[(String, String)],
|
environ: &[(String, String)],
|
||||||
) -> Result<wasmtime::Instance, InstantiationError> {
|
) -> Result<wasmtime::Instance, InstantiationError> {
|
||||||
let global_exports = store.borrow().global_exports().clone();
|
let global_exports = store.global_exports().clone();
|
||||||
let wasi = instantiate_wasi(global_exports, preopened_dirs, argv, environ)?;
|
let wasi = instantiate_wasi(global_exports, preopened_dirs, argv, environ)?;
|
||||||
let instance = wasmtime::Instance::from_handle(&store, wasi);
|
let instance = wasmtime::Instance::from_handle(&store, wasi);
|
||||||
Ok(instance)
|
Ok(instance)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn wrap(
|
fn wrap(
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
ty: FuncType,
|
ty: FuncType,
|
||||||
callable: impl Fn(&[Val], &mut [Val]) -> Result<(), Trap> + 'static,
|
callable: impl Fn(&[Val], &mut [Val]) -> Result<(), Trap> + 'static,
|
||||||
) -> Func {
|
) -> Func {
|
||||||
@@ -26,7 +26,7 @@ fn wrap(
|
|||||||
|
|
||||||
/// Return an instance implementing the "spectest" interface used in the
|
/// Return an instance implementing the "spectest" interface used in the
|
||||||
/// spec testsuite.
|
/// spec testsuite.
|
||||||
pub fn instantiate_spectest(store: &HostRef<Store>) -> HashMap<&'static str, Extern> {
|
pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
|
||||||
let mut ret = HashMap::new();
|
let mut ret = HashMap::new();
|
||||||
|
|
||||||
let ty = FuncType::new(Box::new([]), Box::new([]));
|
let ty = FuncType::new(Box::new([]), Box::new([]));
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ pub struct WastContext {
|
|||||||
current: Option<HostRef<Instance>>,
|
current: Option<HostRef<Instance>>,
|
||||||
|
|
||||||
instances: HashMap<String, HostRef<Instance>>,
|
instances: HashMap<String, HostRef<Instance>>,
|
||||||
store: HostRef<Store>,
|
store: Store,
|
||||||
spectest: Option<HashMap<&'static str, Extern>>,
|
spectest: Option<HashMap<&'static str, Extern>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ enum Outcome<T = Vec<Val>> {
|
|||||||
|
|
||||||
impl WastContext {
|
impl WastContext {
|
||||||
/// Construct a new instance of `WastContext`.
|
/// Construct a new instance of `WastContext`.
|
||||||
pub fn new(store: HostRef<Store>) -> Self {
|
pub fn new(store: Store) -> Self {
|
||||||
Self {
|
Self {
|
||||||
current: None,
|
current: None,
|
||||||
store,
|
store,
|
||||||
|
|||||||
@@ -33,13 +33,12 @@ wasmtime = "<current version>"
|
|||||||
|
|
||||||
where "<current version>" is the current version number of the `wasmtime` crate.
|
where "<current version>" is the current version number of the `wasmtime` crate.
|
||||||
|
|
||||||
It is time to add code to the `src/main.rs`. First, the engine and storage need to be activated:
|
It is time to add code to the `src/main.rs`. First, storage needs to be activated:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use wasmtime::*;
|
use wasmtime::*;
|
||||||
|
|
||||||
let engine = Engine::default();
|
let store = Store::default();
|
||||||
let store = HostRef::new(Store::new(&engine));
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The `HostRef` will be used a lot -- it is a "convenience" object to store and refer an object between the host and
|
The `HostRef` will be used a lot -- it is a "convenience" object to store and refer an object between the host and
|
||||||
@@ -87,8 +86,7 @@ use std::fs::read;
|
|||||||
use wasmtime::*;
|
use wasmtime::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let engine = Engine::default();
|
let store = Store::default();
|
||||||
let store = HostRef::new(Store::new(&engine));
|
|
||||||
|
|
||||||
let wasm = read("hello.wasm").expect("wasm file");
|
let wasm = read("hello.wasm").expect("wasm file");
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ impl RunCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let engine = Engine::new(&config);
|
let engine = Engine::new(&config);
|
||||||
let store = HostRef::new(Store::new(&engine));
|
let store = Store::new(&engine);
|
||||||
let mut module_registry = HashMap::new();
|
let mut module_registry = HashMap::new();
|
||||||
|
|
||||||
// Make wasi available by default.
|
// Make wasi available by default.
|
||||||
@@ -151,7 +151,7 @@ impl RunCommand {
|
|||||||
let wasi_unstable = HostRef::new(if self.enable_wasi_c {
|
let wasi_unstable = HostRef::new(if self.enable_wasi_c {
|
||||||
#[cfg(feature = "wasi-c")]
|
#[cfg(feature = "wasi-c")]
|
||||||
{
|
{
|
||||||
let global_exports = store.borrow().global_exports().clone();
|
let global_exports = store.global_exports().clone();
|
||||||
let handle = instantiate_wasi_c(global_exports, &preopen_dirs, &argv, &self.vars)?;
|
let handle = instantiate_wasi_c(global_exports, &preopen_dirs, &argv, &self.vars)?;
|
||||||
Instance::from_handle(&store, handle)
|
Instance::from_handle(&store, handle)
|
||||||
}
|
}
|
||||||
@@ -231,12 +231,12 @@ impl RunCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate_module(
|
fn instantiate_module(
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
module_registry: &HashMap<String, HostRef<Instance>>,
|
module_registry: &HashMap<String, HostRef<Instance>>,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> Result<(HostRef<Instance>, HostRef<Module>, Vec<u8>)> {
|
) -> Result<(HostRef<Instance>, HostRef<Module>, Vec<u8>)> {
|
||||||
// Read the wasm module binary either as `*.wat` or a raw binary
|
// Read the wasm module binary either as `*.wat` or a raw binary
|
||||||
let data = wat::parse_file(path.to_path_buf())?;
|
let data = wat::parse_file(path)?;
|
||||||
|
|
||||||
let module = HostRef::new(Module::new(store, &data)?);
|
let module = HostRef::new(Module::new(store, &data)?);
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ impl RunCommand {
|
|||||||
|
|
||||||
fn handle_module(
|
fn handle_module(
|
||||||
&self,
|
&self,
|
||||||
store: &HostRef<Store>,
|
store: &Store,
|
||||||
module_registry: &HashMap<String, HostRef<Instance>>,
|
module_registry: &HashMap<String, HostRef<Instance>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let (instance, module, data) =
|
let (instance, module, data) =
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::{init_file_per_thread_logger, pick_compilation_strategy, CommonOption
|
|||||||
use anyhow::{bail, Context as _, Result};
|
use anyhow::{bail, Context as _, Result};
|
||||||
use std::{fmt::Write, path::PathBuf};
|
use std::{fmt::Write, path::PathBuf};
|
||||||
use structopt::{clap::AppSettings, StructOpt};
|
use structopt::{clap::AppSettings, StructOpt};
|
||||||
use wasmtime::{Config, Engine, HostRef, Store};
|
use wasmtime::{Config, Engine, Store};
|
||||||
use wasmtime_environ::cache_init;
|
use wasmtime_environ::cache_init;
|
||||||
use wasmtime_wast::WastContext;
|
use wasmtime_wast::WastContext;
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ impl WastCommand {
|
|||||||
config.cranelift_opt_level(wasmtime::OptLevel::Speed);
|
config.cranelift_opt_level(wasmtime::OptLevel::Speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
let store = HostRef::new(Store::new(&Engine::new(&config)));
|
let store = Store::new(&Engine::new(&config));
|
||||||
let mut wast_context = WastContext::new(store);
|
let mut wast_context = WastContext::new(store);
|
||||||
|
|
||||||
wast_context
|
wast_context
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use wasmtime::{Config, Engine, HostRef, Store, Strategy};
|
use wasmtime::{Config, Engine, Store, Strategy};
|
||||||
use wasmtime_wast::WastContext;
|
use wasmtime_wast::WastContext;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/wast_testsuite_tests.rs"));
|
include!(concat!(env!("OUT_DIR"), "/wast_testsuite_tests.rs"));
|
||||||
@@ -15,7 +15,7 @@ fn run_wast(wast: &str, strategy: Strategy) -> anyhow::Result<()> {
|
|||||||
.wasm_multi_value(wast.iter().any(|s| s == "multi-value"))
|
.wasm_multi_value(wast.iter().any(|s| s == "multi-value"))
|
||||||
.strategy(strategy)?
|
.strategy(strategy)?
|
||||||
.cranelift_debug_verifier(true);
|
.cranelift_debug_verifier(true);
|
||||||
let store = HostRef::new(Store::new(&Engine::new(&cfg)));
|
let store = Store::new(&Engine::new(&cfg));
|
||||||
let mut wast_context = WastContext::new(store);
|
let mut wast_context = WastContext::new(store);
|
||||||
wast_context.register_spectest()?;
|
wast_context.register_spectest()?;
|
||||||
wast_context.run_file(wast)?;
|
wast_context.run_file(wast)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user