Skip to content

Commit

Permalink
Merge #3378
Browse files Browse the repository at this point in the history
3378: Introduced EngineRef and AsEngineRef trait r=ptitSeb a=ptitSeb

# Description
Introduced `EngineRef` structure that is used to build a Module (instead of `StoreRef`) and the `AsEngineRef` trait.
`Store` implement this trait, so there will be no change in writen code even if it's an API change.

This allow to create a Module independantly of a Store, as it can be usefull for multi-thread scenario.

For #3372 

Co-authored-by: ptitSeb <sebastien.chev@gmail.com>
  • Loading branch information
bors[bot] and ptitSeb authored Nov 30, 2022
2 parents b771604 + 241f92d commit 46328d5
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 191 deletions.
2 changes: 1 addition & 1 deletion lib/api/src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ pub use wasmer_compiler_cranelift::{Cranelift, CraneliftOptLevel};
#[cfg(feature = "llvm")]
pub use wasmer_compiler_llvm::{LLVMOptLevel, LLVM};

pub use wasmer_compiler::Engine;
#[cfg(feature = "compiler")]
pub use wasmer_compiler::{Artifact, EngineBuilder};
pub use wasmer_compiler::{AsEngineRef, Engine, EngineRef};

/// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
Expand Down
40 changes: 24 additions & 16 deletions lib/api/src/sys/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::sync::Arc;
use thiserror::Error;
use wasmer_compiler::Artifact;
use wasmer_compiler::ArtifactCreate;
use wasmer_compiler::AsEngineRef;
#[cfg(feature = "wat")]
use wasmer_types::WasmError;
use wasmer_types::{
Expand Down Expand Up @@ -158,28 +159,38 @@ impl Module {
/// # Ok(())
/// # }
/// ```
/// # Example of loading a module using just an `Engine` and no `Store`
///
/// ```
/// # use wasmer::*;
/// #
/// # let compiler = Cranelift::default();
/// # let engine = EngineBuilder::new(compiler).engine();
///
/// let module = Module::from_file(&engine, "path/to/foo.wasm");
/// ```
#[allow(unreachable_code)]
pub fn new(store: &impl AsStoreRef, bytes: impl AsRef<[u8]>) -> Result<Self, CompileError> {
pub fn new(engine: &impl AsEngineRef, bytes: impl AsRef<[u8]>) -> Result<Self, CompileError> {
#[cfg(feature = "wat")]
let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| {
CompileError::Wasm(WasmError::Generic(format!(
"Error when converting wat: {}",
e
)))
})?;
Self::from_binary(store, bytes.as_ref())
Self::from_binary(engine, bytes.as_ref())
}

#[cfg(feature = "compiler")]
/// Creates a new WebAssembly module from a file path.
pub fn from_file(
store: &impl AsStoreRef,
engine: &impl AsEngineRef,
file: impl AsRef<Path>,
) -> Result<Self, IoCompileError> {
let file_ref = file.as_ref();
let canonical = file_ref.canonicalize()?;
let wasm_bytes = std::fs::read(file_ref)?;
let mut module = Self::new(store, &wasm_bytes)?;
let mut module = Self::new(engine, &wasm_bytes)?;
// Set the module name to the absolute path of the filename.
// This is useful for debugging the stack traces.
let filename = canonical.as_path().to_str().unwrap();
Expand All @@ -193,9 +204,9 @@ impl Module {
/// Opposed to [`Module::new`], this function is not compatible with
/// the WebAssembly text format (if the "wat" feature is enabled for
/// this crate).
pub fn from_binary(store: &impl AsStoreRef, binary: &[u8]) -> Result<Self, CompileError> {
Self::validate(store, binary)?;
unsafe { Self::from_binary_unchecked(store, binary) }
pub fn from_binary(engine: &impl AsEngineRef, binary: &[u8]) -> Result<Self, CompileError> {
Self::validate(engine, binary)?;
unsafe { Self::from_binary_unchecked(engine, binary) }
}

#[cfg(feature = "compiler")]
Expand All @@ -207,10 +218,10 @@ impl Module {
/// in environments where the WebAssembly modules are trusted and validated
/// beforehand.
pub unsafe fn from_binary_unchecked(
store: &impl AsStoreRef,
engine: &impl AsEngineRef,
binary: &[u8],
) -> Result<Self, CompileError> {
let module = Self::compile(store, binary)?;
let module = Self::compile(engine, binary)?;
Ok(module)
}

Expand All @@ -221,16 +232,13 @@ impl Module {
/// This validation is normally pretty fast and checks the enabled
/// WebAssembly features in the Store Engine to assure deterministic
/// validation of the Module.
pub fn validate(store: &impl AsStoreRef, binary: &[u8]) -> Result<(), CompileError> {
store.as_store_ref().engine().validate(binary)
pub fn validate(engine: &impl AsEngineRef, binary: &[u8]) -> Result<(), CompileError> {
engine.as_engine_ref().engine().validate(binary)
}

#[cfg(feature = "compiler")]
fn compile(store: &impl AsStoreRef, binary: &[u8]) -> Result<Self, CompileError> {
let artifact = store
.as_store_ref()
.engine()
.compile(binary, store.as_store_ref().tunables())?;
fn compile(engine: &impl AsEngineRef, binary: &[u8]) -> Result<Self, CompileError> {
let artifact = engine.as_engine_ref().engine().compile(binary)?;
Ok(Self::from_artifact(artifact))
}

Expand Down
75 changes: 47 additions & 28 deletions lib/api/src/sys/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::sys::tunables::BaseTunables;
use std::fmt;
use std::sync::{Arc, RwLock};
#[cfg(feature = "compiler")]
use wasmer_compiler::{Engine, EngineBuilder, Tunables};
use wasmer_compiler::{AsEngineRef, Engine, EngineBuilder, EngineRef, Tunables};
use wasmer_vm::{init_traps, TrapHandler, TrapHandlerFn};

use wasmer_vm::StoreObjects;
Expand All @@ -14,8 +14,6 @@ pub(crate) struct StoreInner {
pub(crate) objects: StoreObjects,
#[cfg(feature = "compiler")]
pub(crate) engine: Engine,
#[cfg(feature = "compiler")]
pub(crate) tunables: Box<dyn Tunables + Send + Sync>,
pub(crate) trap_handler: Option<Box<TrapHandlerFn<'static>>>,
}

Expand All @@ -25,10 +23,7 @@ pub(crate) struct StoreInner {
/// have been allocated during the lifetime of the abstract machine.
///
/// The `Store` holds the engine (that is —amongst many things— used to compile
/// the Wasm bytes into a valid module artifact), in addition to the
#[cfg_attr(feature = "compiler", doc = "[`Tunables`]")]
#[cfg_attr(not(feature = "compiler"), doc = "`Tunables`")]
/// (that are used to create the memories, tables and globals).
/// the Wasm bytes into a valid module artifact).
///
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#store>
pub struct Store {
Expand All @@ -43,8 +38,20 @@ impl Store {
/// Creates a new `Store` with a specific [`Engine`].
pub fn new(engine: impl Into<Engine>) -> Self {
let engine = engine.into();
let target = engine.target().clone();
Self::new_with_tunables(engine, BaseTunables::for_target(&target))

// Make sure the signal handlers are installed.
// This is required for handling traps.
init_traps();

Self {
inner: Box::new(StoreInner {
objects: Default::default(),
engine: engine.cloned(),
trap_handler: None,
}),
engine: engine.cloned(),
trap_handler: Arc::new(RwLock::new(None)),
}
}

#[cfg(feature = "compiler")]
Expand All @@ -68,28 +75,16 @@ impl Store {
engine: impl Into<Engine>,
tunables: impl Tunables + Send + Sync + 'static,
) -> Self {
let engine = engine.into();
let mut engine = engine.into();
engine.set_tunables(tunables);

// Make sure the signal handlers are installed.
// This is required for handling traps.
init_traps();

Self {
inner: Box::new(StoreInner {
objects: Default::default(),
engine: engine.cloned(),
tunables: Box::new(tunables),
trap_handler: None,
}),
engine: engine.cloned(),
trap_handler: Arc::new(RwLock::new(None)),
}
Self::new(engine)
}

#[cfg(feature = "compiler")]
/// Returns the [`Tunables`].
pub fn tunables(&self) -> &dyn Tunables {
self.inner.tunables.as_ref()
self.engine.tunables()
}

#[cfg(feature = "compiler")]
Expand Down Expand Up @@ -202,6 +197,30 @@ impl AsStoreMut for Store {
}
}

impl AsEngineRef for Store {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef::new(&self.engine)
}
}

impl AsEngineRef for &Store {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef::new(&self.engine)
}
}

impl AsEngineRef for StoreRef<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef::new(&self.inner.engine)
}
}

impl AsEngineRef for StoreMut<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef::new(&self.inner.engine)
}
}

impl fmt::Debug for Store {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Store").finish()
Expand All @@ -221,7 +240,7 @@ impl<'a> StoreRef<'a> {
#[cfg(feature = "compiler")]
/// Returns the [`Tunables`].
pub fn tunables(&self) -> &dyn Tunables {
self.inner.tunables.as_ref()
self.inner.engine.tunables()
}

#[cfg(feature = "compiler")]
Expand Down Expand Up @@ -257,7 +276,7 @@ impl<'a> StoreMut<'a> {
/// Returns the [`Tunables`].
#[cfg(feature = "compiler")]
pub fn tunables(&self) -> &dyn Tunables {
self.inner.tunables.as_ref()
self.inner.engine.tunables()
}

/// Returns the [`Engine`].
Expand All @@ -276,7 +295,7 @@ impl<'a> StoreMut<'a> {

#[cfg(feature = "compiler")]
pub(crate) fn tunables_and_objects_mut(&mut self) -> (&dyn Tunables, &mut StoreObjects) {
(self.inner.tunables.as_ref(), &mut self.inner.objects)
(self.inner.engine.tunables(), &mut self.inner.objects)
}

pub(crate) fn as_raw(&self) -> *mut StoreInner {
Expand Down
Loading

0 comments on commit 46328d5

Please sign in to comment.