Skip to content

Commit

Permalink
Remove the need for HostRef<Store> (#771)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
alexcrichton committed Jan 7, 2020
1 parent 296ebc4 commit 045d6a7
Show file tree
Hide file tree
Showing 31 changed files with 163 additions and 155 deletions.
17 changes: 5 additions & 12 deletions crates/api/examples/gcd.rs
@@ -1,7 +1,6 @@
//! Example of instantiating of the WebAssembly module and
//! invoking its exported function.

use anyhow::{format_err, Result};
use wasmtime::*;

const WAT: &str = r#"
Expand Down Expand Up @@ -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)?;

// Instantiate engine and store.
let engine = Engine::default();
let store = HostRef::new(Store::new(&engine));

// Load a module.
let store = Store::default();
let module = HostRef::new(Module::new(&store, &wasm)?);

// Find index of the `gcd` export.
Expand All @@ -59,10 +55,7 @@ fn main() -> Result<()> {

// Invoke `gcd` export
let gcd = instance.exports()[gcd_index].func().expect("gcd");
let result = gcd
.borrow()
.call(&[Val::from(6i32), Val::from(27i32)])
.map_err(|e| format_err!("call error: {:?}", e))?;
let result = gcd.borrow().call(&[Val::from(6i32), Val::from(27i32)])?;

println!("{:?}", result);
Ok(())
Expand Down
15 changes: 6 additions & 9 deletions crates/api/examples/hello.rs
@@ -1,6 +1,6 @@
//! Translation of hello example

use anyhow::{ensure, format_err, Context as _, Result};
use anyhow::{ensure, Context as _, Result};
use std::rc::Rc;
use wasmtime::*;

Expand All @@ -15,11 +15,11 @@ impl Callable for HelloCallback {
}

fn main() -> Result<()> {
// Configure the initial compilation environment, creating more global
// structures such as an `Engine` and a `Store`.
// Configure the initial compilation environment, creating the global
// `Store` structure. Note that you can also tweak configuration settings
// with a `Config` and an `Engine` if desired.
println!("Initializing...");
let engine = Engine::default();
let store = HostRef::new(Store::new(&engine));
let store = Store::default();

// Next upload the `*.wasm` binary file, which in this case we're going to
// be parsing an inline text format into a binary.
Expand Down Expand Up @@ -59,10 +59,7 @@ fn main() -> Result<()> {

// And last but not least we can call it!
println!("Calling export...");
run_func
.borrow()
.call(&[])
.map_err(|e| format_err!("> Error calling function: {:?}", e))?;
run_func.borrow().call(&[])?;

println!("Done.");
Ok(())
Expand Down
3 changes: 1 addition & 2 deletions crates/api/examples/memory.rs
Expand Up @@ -62,8 +62,7 @@ macro_rules! call {
fn main() -> Result<(), Error> {
// Initialize.
println!("Initializing...");
let engine = Engine::default();
let store = HostRef::new(Store::new(&engine));
let store = Store::default();

// Load binary.
println!("Loading binary...");
Expand Down
2 changes: 1 addition & 1 deletion crates/api/examples/multi.rs
Expand Up @@ -46,7 +46,7 @@ fn main() -> Result<()> {
// Initialize.
println!("Initializing...");
let engine = Engine::new(Config::new().wasm_multi_value(true));
let store = HostRef::new(Store::new(&engine));
let store = Store::new(&engine);

// Load binary.
println!("Loading binary...");
Expand Down
14 changes: 4 additions & 10 deletions crates/api/src/callable.rs
Expand Up @@ -43,8 +43,7 @@ use wasmtime_runtime::Export;
/// "#)?;
///
/// // Initialise environment and our module.
/// let engine = wasmtime::Engine::default();
/// let store = HostRef::new(wasmtime::Store::new(&engine));
/// let store = wasmtime::Store::default();
/// let module = HostRef::new(wasmtime::Module::new(&store, &binary)?);
///
/// // Define the type of the function we're going to call.
Expand Down Expand Up @@ -103,13 +102,13 @@ pub(crate) trait WrappedCallable {
}

pub(crate) struct WasmtimeFn {
store: HostRef<Store>,
store: Store,
instance: InstanceHandle,
export: Export,
}

impl WasmtimeFn {
pub fn new(store: &HostRef<Store>, instance: InstanceHandle, export: Export) -> WasmtimeFn {
pub fn new(store: &Store, instance: InstanceHandle, export: Export) -> WasmtimeFn {
WasmtimeFn {
store: store.clone(),
instance,
Expand Down Expand Up @@ -146,7 +145,6 @@ impl WrappedCallable for WasmtimeFn {
// Get the trampoline to call for this function.
let exec_code_buf = self
.store
.borrow_mut()
.context()
.compiler()
.get_published_trampoline(body, &signature, value_size)
Expand Down Expand Up @@ -191,11 +189,7 @@ pub struct NativeCallable {
}

impl NativeCallable {
pub(crate) fn new(
callable: Rc<dyn Callable + 'static>,
ft: &FuncType,
store: &HostRef<Store>,
) -> Self {
pub(crate) fn new(callable: Rc<dyn Callable + 'static>, ft: &FuncType, store: &Store) -> Self {
let (instance, export) =
generate_func_export(ft, &callable, store).expect("generated func");
NativeCallable {
Expand Down
2 changes: 1 addition & 1 deletion crates/api/src/context.rs
Expand Up @@ -30,7 +30,7 @@ impl Context {
self.debug_info
}

pub(crate) fn compiler(&mut self) -> RefMut<Compiler> {
pub(crate) fn compiler(&self) -> RefMut<Compiler> {
self.compiler.borrow_mut()
}
}
Expand Down
35 changes: 16 additions & 19 deletions crates/api/src/externals.rs
Expand Up @@ -66,7 +66,7 @@ impl Extern {
}

pub(crate) fn from_wasmtime_export(
store: &HostRef<Store>,
store: &Store,
instance_handle: InstanceHandle,
export: wasmtime_runtime::Export,
) -> Extern {
Expand Down Expand Up @@ -112,19 +112,19 @@ impl From<HostRef<Table>> for Extern {
}

pub struct Func {
_store: HostRef<Store>,
_store: Store,
callable: Rc<dyn WrappedCallable + 'static>,
r#type: FuncType,
}

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));
Func::from_wrapped(store, ty, callable)
}

fn from_wrapped(
store: &HostRef<Store>,
store: &Store,
r#type: FuncType,
callable: Rc<dyn WrappedCallable + 'static>,
) -> Func {
Expand Down Expand Up @@ -159,7 +159,7 @@ impl Func {

pub(crate) fn from_wasmtime_function(
export: wasmtime_runtime::Export,
store: &HostRef<Store>,
store: &Store,
instance_handle: InstanceHandle,
) -> Self {
let ty = if let wasmtime_runtime::Export::Function { signature, .. } = &export {
Expand All @@ -179,15 +179,15 @@ impl fmt::Debug for Func {
}

pub struct Global {
_store: HostRef<Store>,
_store: Store,
r#type: GlobalType,
wasmtime_export: wasmtime_runtime::Export,
#[allow(dead_code)]
wasmtime_state: Option<crate::trampoline::GlobalState>,
}

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) =
generate_global_export(&r#type, val).expect("generated global");
Global {
Expand Down Expand Up @@ -246,10 +246,7 @@ impl Global {
&self.wasmtime_export
}

pub(crate) fn from_wasmtime_global(
export: wasmtime_runtime::Export,
store: &HostRef<Store>,
) -> Global {
pub(crate) fn from_wasmtime_global(export: wasmtime_runtime::Export, store: &Store) -> Global {
let global = if let wasmtime_runtime::Export::Global { ref global, .. } = export {
global
} else {
Expand All @@ -266,15 +263,15 @@ impl Global {
}

pub struct Table {
store: HostRef<Store>,
store: Store,
r#type: TableType,
wasmtime_handle: InstanceHandle,
wasmtime_export: wasmtime_runtime::Export,
}

fn get_table_item(
handle: &InstanceHandle,
store: &HostRef<Store>,
store: &Store,
table_index: wasm::DefinedTableIndex,
item_index: u32,
) -> Val {
Expand All @@ -287,7 +284,7 @@ fn get_table_item(

fn set_table_item(
handle: &mut InstanceHandle,
store: &HostRef<Store>,
store: &Store,
table_index: wasm::DefinedTableIndex,
item_index: u32,
val: Val,
Expand All @@ -302,7 +299,7 @@ fn set_table_item(
}

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() {
ValType::FuncRef => (),
_ => panic!("table is not for funcref"),
Expand Down Expand Up @@ -387,7 +384,7 @@ impl Table {

pub(crate) fn from_wasmtime_table(
export: wasmtime_runtime::Export,
store: &HostRef<Store>,
store: &Store,
instance_handle: wasmtime_runtime::InstanceHandle,
) -> Table {
let table = if let wasmtime_runtime::Export::Table { ref table, .. } = export {
Expand All @@ -406,14 +403,14 @@ impl Table {
}

pub struct Memory {
_store: HostRef<Store>,
_store: Store,
r#type: MemoryType,
wasmtime_handle: InstanceHandle,
wasmtime_export: wasmtime_runtime::Export,
}

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) =
generate_memory_export(&r#type).expect("generated memory");
Memory {
Expand Down Expand Up @@ -473,7 +470,7 @@ impl Memory {

pub(crate) fn from_wasmtime_memory(
export: wasmtime_runtime::Export,
store: &HostRef<Store>,
store: &Store,
instance_handle: wasmtime_runtime::InstanceHandle,
) -> Memory {
let memory = if let wasmtime_runtime::Export::Memory { ref memory, .. } = export {
Expand Down
12 changes: 6 additions & 6 deletions crates/api/src/instance.rs
Expand Up @@ -30,7 +30,7 @@ impl Resolver for SimpleResolver {
pub fn instantiate_in_context(
data: &[u8],
imports: Vec<(String, String, Extern)>,
mut context: Context,
context: Context,
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
let mut contexts = HashSet::new();
Expand Down Expand Up @@ -70,12 +70,12 @@ pub struct Instance {

impl Instance {
pub fn new(
store: &HostRef<Store>,
store: &Store,
module: &HostRef<Module>,
externs: &[Extern],
) -> Result<Instance, Error> {
let context = store.borrow_mut().context().clone();
let exports = store.borrow_mut().global_exports().clone();
let context = store.context().clone();
let exports = store.global_exports().clone();
let imports = module
.borrow()
.imports()
Expand Down Expand Up @@ -131,7 +131,7 @@ impl Instance {
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 mut exports = Vec::new();
Expand All @@ -143,7 +143,7 @@ impl Instance {
// HACK ensure all handles, instantiated outside Store, present in
// the store's SignatureRegistry, e.g. WASI instances that are
// 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);
exports_types.push(ExportType::new(name, extern_type));
Expand Down
13 changes: 6 additions & 7 deletions crates/api/src/module.rs
@@ -1,4 +1,3 @@
use crate::r#ref::HostRef;
use crate::runtime::Store;
use crate::types::{
ExportType, ExternType, FuncType, GlobalType, ImportType, Limits, MemoryType, Mutability,
Expand Down Expand Up @@ -173,7 +172,7 @@ pub(crate) enum ModuleCodeSource {

#[derive(Clone)]
pub struct Module {
store: HostRef<Store>,
store: Store,
source: ModuleCodeSource,
imports: Box<[ImportType]>,
exports: Box<[ExportType]>,
Expand All @@ -182,13 +181,13 @@ pub struct Module {
impl Module {
/// Validate and decode the raw wasm data in `binary` and create a new
/// `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::new_unchecked(store, binary)
}
/// Similar to `new`, but does not perform any validation. Only use this
/// 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)?;
Ok(Module {
store: store.clone(),
Expand All @@ -203,8 +202,8 @@ impl Module {
_ => None,
}
}
pub fn validate(store: &HostRef<Store>, binary: &[u8]) -> Result<()> {
let features = store.borrow().engine().config.features.clone();
pub fn validate(store: &Store, binary: &[u8]) -> Result<()> {
let features = store.engine().config.features.clone();
let config = ValidatingParserConfig {
operator_config: OperatorValidatorConfig {
enable_threads: features.threads,
Expand All @@ -222,7 +221,7 @@ impl Module {
pub fn exports(&self) -> &[ExportType] {
&self.exports
}
pub fn from_exports(store: &HostRef<Store>, exports: Box<[ExportType]>) -> Self {
pub fn from_exports(store: &Store, exports: Box<[ExportType]>) -> Self {
Module {
store: store.clone(),
source: ModuleCodeSource::Unknown,
Expand Down

0 comments on commit 045d6a7

Please sign in to comment.