Remove need for HostRef<Engine> (#762)

This commit removes the need to use `HostRef<Engine>` in the Rust API.
Usage is retained in the C API in one location, but otherwise `Engine`
can always be used directly.

This is the first step of progress on #708 for the `Engine` type.
Changes here include:

* `Engine` is now `Clone`, and is documented as being cheap. It's not
  intended that cloning an engine creates a deep copy.
* `Engine` is now both `Send` and `Sync`, and asserted to be so.
* Usage of `Engine` in APIs no longer requires or uses `HostRef`.
This commit is contained in:
Alex Crichton
2020-01-06 15:17:03 -06:00
committed by GitHub
parent ad7d48479e
commit b9dc38f4e1
18 changed files with 56 additions and 28 deletions

View File

@@ -38,7 +38,7 @@ fn main() -> Result<()> {
let wasm = wat::parse_str(WAT)?; let wasm = wat::parse_str(WAT)?;
// Instantiate engine and store. // Instantiate engine and store.
let engine = HostRef::new(Engine::default()); let engine = Engine::default();
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
// Load a module. // Load a module.

View File

@@ -18,7 +18,7 @@ fn main() -> Result<()> {
// Configure the initial compilation environment, creating more global // Configure the initial compilation environment, creating more global
// structures such as an `Engine` and a `Store`. // structures such as an `Engine` and a `Store`.
println!("Initializing..."); println!("Initializing...");
let engine = HostRef::new(Engine::default()); let engine = Engine::default();
let store = HostRef::new(Store::new(&engine)); 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

View File

@@ -62,7 +62,7 @@ macro_rules! call {
fn main() -> Result<(), Error> { fn main() -> Result<(), Error> {
// Initialize. // Initialize.
println!("Initializing..."); println!("Initializing...");
let engine = HostRef::new(Engine::default()); let engine = Engine::default();
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
// Load binary. // Load binary.

View File

@@ -50,7 +50,7 @@ fn main() -> Result<()> {
multi_value: true, multi_value: true,
..Default::default() ..Default::default()
}); });
let engine = HostRef::new(Engine::new(&cfg)); let engine = Engine::new(&cfg);
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
// Load binary. // Load binary.

View File

@@ -43,7 +43,7 @@ use wasmtime_runtime::Export;
/// "#)?; /// "#)?;
/// ///
/// // Initialise environment and our module. /// // Initialise environment and our module.
/// let engine = HostRef::new(wasmtime::Engine::default()); /// let engine = wasmtime::Engine::default();
/// let store = HostRef::new(wasmtime::Store::new(&engine)); /// 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)?);
/// ///

View File

@@ -204,7 +204,7 @@ impl Module {
} }
} }
pub fn validate(store: &HostRef<Store>, binary: &[u8]) -> Result<()> { pub fn validate(store: &HostRef<Store>, binary: &[u8]) -> Result<()> {
let features = store.borrow().engine().borrow().config.features.clone(); let features = store.borrow().engine().config.features.clone();
let config = ValidatingParserConfig { let config = ValidatingParserConfig {
operator_config: OperatorValidatorConfig { operator_config: OperatorValidatorConfig {
enable_threads: features.threads, enable_threads: features.threads,

View File

@@ -1,8 +1,8 @@
use crate::context::Context; use crate::context::Context;
use crate::r#ref::HostRef;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
use wasmtime_environ::{ir, settings}; use wasmtime_environ::{ir, settings};
use wasmtime_jit::{CompilationStrategy, Features}; use wasmtime_jit::{CompilationStrategy, Features};
@@ -92,15 +92,38 @@ impl Default for Config {
// Engine // Engine
#[derive(Default)] /// An `Engine` which is a global context for compilation and management of wasm
/// modules.
///
/// An engine can be safely shared across threads and is a cheap cloneable
/// handle to the actual engine. The engine itself will be deallocate once all
/// references to it have gone away.
///
/// Engines store global configuration preferences such as compilation settings,
/// enabled features, etc. You'll likely only need at most one of these for a
/// program.
///
/// ## Engines and `Clone`
///
/// 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.
///
/// ## Engines and `Default`
///
/// You can create an engine with default settings using `Engine::default()`.
/// This engine will not have any unstable wasm features enabled and will use
/// the default compilation backend configured at this crate's compile time.
#[derive(Default, Clone)]
pub struct Engine { pub struct Engine {
pub(crate) config: Config, pub(crate) config: Arc<Config>,
} }
impl Engine { impl Engine {
/// Creates a new [`Engine`] with the specified compilation and
/// configuration settings.
pub fn new(config: &Config) -> Engine { pub fn new(config: &Config) -> Engine {
Engine { Engine {
config: config.clone(), config: Arc::new(config.clone()),
} }
} }
} }
@@ -108,23 +131,23 @@ impl Engine {
// Store // Store
pub struct Store { pub struct Store {
engine: HostRef<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: HashMap<wasmtime_runtime::VMSharedSignatureIndex, ir::Signature>,
} }
impl Store { impl Store {
pub fn new(engine: &HostRef<Engine>) -> Store { pub fn new(engine: &Engine) -> Store {
Store { Store {
engine: engine.clone(), engine: engine.clone(),
context: Context::new(&engine.borrow().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: HashMap::new(),
} }
} }
pub fn engine(&self) -> &HostRef<Engine> { pub fn engine(&self) -> &Engine {
&self.engine &self.engine
} }
@@ -161,3 +184,8 @@ impl Store {
self.signature_cache.get(&type_index) self.signature_cache.get(&type_index)
} }
} }
fn _assert_send_sync() {
fn _assert<T: Send + Sync>() {}
_assert::<Engine>();
}

View File

@@ -778,7 +778,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 { pub unsafe extern "C" fn wasm_store_new(engine: *mut wasm_engine_t) -> *mut wasm_store_t {
let engine = &(*engine).engine; let engine = &(*engine).engine;
let store = Box::new(wasm_store_t { let store = Box::new(wasm_store_t {
store: HostRef::new(Store::new(&engine)), store: HostRef::new(Store::new(&engine.borrow())),
}); });
Box::into_raw(store) Box::into_raw(store)
} }

View File

@@ -32,7 +32,7 @@ fn test_import_calling_export() {
} }
} }
let engine = HostRef::new(Engine::default()); let engine = Engine::default();
let store = HostRef::new(Store::new(&engine)); 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"));

View File

@@ -12,7 +12,7 @@ fn test_trap_return() -> Result<(), String> {
} }
} }
let engine = HostRef::new(Engine::default()); let engine = Engine::default();
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
let binary = parse_str( let binary = parse_str(
r#" r#"

View File

@@ -40,7 +40,7 @@ pub fn instantiate(wasm: &[u8], compilation_strategy: CompilationStrategy) {
let mut config = Config::new(); let mut config = Config::new();
config.strategy(compilation_strategy); config.strategy(compilation_strategy);
let engine = HostRef::new(Engine::new(&config)); let engine = Engine::new(&config);
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
let module = let module =
@@ -89,7 +89,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
use crate::generators::api::ApiCall; use crate::generators::api::ApiCall;
let mut config: Option<Config> = None; let mut config: Option<Config> = None;
let mut engine: Option<HostRef<Engine>> = None; let mut engine: Option<Engine> = None;
let mut store: Option<HostRef<Store>> = None; let mut store: Option<HostRef<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();
@@ -107,7 +107,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
ApiCall::EngineNew => { ApiCall::EngineNew => {
assert!(engine.is_none()); assert!(engine.is_none());
engine = Some(HostRef::new(Engine::new(config.as_ref().unwrap()))); engine = Some(Engine::new(config.as_ref().unwrap()));
} }
ApiCall::StoreNew => { ApiCall::StoreNew => {

View File

@@ -92,7 +92,7 @@ pub fn instantiate(
..Default::default() ..Default::default()
}); });
let engine = wasmtime::HostRef::new(wasmtime::Engine::new(&config)); let engine = wasmtime::Engine::new(&config);
let store = wasmtime::HostRef::new(wasmtime::Store::new(&engine)); let store = wasmtime::HostRef::new(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)?);

View File

@@ -56,7 +56,7 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
multi_value: true, multi_value: true,
..Default::default() ..Default::default()
}); });
let engine = HostRef::new(Engine::new(&config)); let engine = Engine::new(&config);
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
let global_exports = store.borrow().global_exports().clone(); let global_exports = store.borrow().global_exports().clone();

View File

@@ -15,7 +15,7 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
let mut config = Config::new(); let mut config = Config::new();
config.flags(settings::Flags::new(flag_builder)); config.flags(settings::Flags::new(flag_builder));
let engine = HostRef::new(Engine::new(&config)); let engine = Engine::new(&config);
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
let global_exports = store.borrow().global_exports().clone(); let global_exports = store.borrow().global_exports().clone();

View File

@@ -38,7 +38,7 @@ It is time to add code to the `src/main.rs`. First, the engine and storage need
```rust ```rust
use wasmtime::*; use wasmtime::*;
let engine = HostRef::new(Engine::default()); let engine = Engine::default();
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
``` ```
@@ -87,7 +87,7 @@ use std::fs::read;
use wasmtime::*; use wasmtime::*;
fn main() { fn main() {
let engine = HostRef::new(Engine::default()); let engine = Engine::default();
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
let wasm = read("hello.wasm").expect("wasm file"); let wasm = read("hello.wasm").expect("wasm file");

View File

@@ -266,7 +266,7 @@ fn main() -> Result<()> {
.flags(settings::Flags::new(flag_builder)) .flags(settings::Flags::new(flag_builder))
.debug_info(debug_info) .debug_info(debug_info)
.strategy(strategy); .strategy(strategy);
let engine = HostRef::new(Engine::new(&config)); let engine = Engine::new(&config);
let store = HostRef::new(Store::new(&engine)); let store = HostRef::new(Store::new(&engine));
let mut module_registry = HashMap::new(); let mut module_registry = HashMap::new();

View File

@@ -154,7 +154,7 @@ fn main() {
cfg.strategy(strategy) cfg.strategy(strategy)
.flags(settings::Flags::new(flag_builder)) .flags(settings::Flags::new(flag_builder))
.features(features); .features(features);
let store = HostRef::new(Store::new(&HostRef::new(Engine::new(&cfg)))); let store = HostRef::new(Store::new(&Engine::new(&cfg)));
let mut wast_context = WastContext::new(store); let mut wast_context = WastContext::new(store);
wast_context wast_context

View File

@@ -27,7 +27,7 @@ fn run_wast(wast: &str, strategy: CompilationStrategy) -> anyhow::Result<()> {
cfg.strategy(strategy) cfg.strategy(strategy)
.flags(settings::Flags::new(flag_builder)) .flags(settings::Flags::new(flag_builder))
.features(features); .features(features);
let store = HostRef::new(Store::new(&HostRef::new(Engine::new(&cfg)))); let store = HostRef::new(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)?;