Introduced EngineRef and AsEngineRef trait

This commit is contained in:
ptitSeb
2022-11-25 16:59:54 +01:00
parent e0707e97d6
commit a466c4b27b
8 changed files with 245 additions and 15 deletions

View File

@@ -0,0 +1,47 @@
use crate::Tunables;
use wasmer_compiler::Engine;
/// A temporary handle to an [`Engine`] and [`Tunables`].
/// EngineRef can be used to build a [`Module`]
/// It can be created directly with an [`Engine`] and [`Tunables`]
/// Or from anything implementing [`AsEngineRef`]
/// like from [`Store`] typicaly
pub struct EngineRef<'a> {
/// The inner engine
pub(crate) inner: &'a Engine,
/// optionnal tunnables
pub(crate) tunables: &'a dyn Tunables,
}
impl<'a> EngineRef<'a> {
/// Get inner [`Engine`]
pub fn engine(&self) -> &Engine {
self.inner
}
/// Get the [`Tunables`]
pub fn tunables(&self) -> &dyn Tunables {
self.tunables
}
/// Create an EngineRef from an Engine and Tunables
pub fn new(engine: &'a Engine, tunables: &'a dyn Tunables) -> Self {
EngineRef {
inner: engine,
tunables,
}
}
}
/// Helper trait for a value that is convertible to a [`EngineRef`].
pub trait AsEngineRef {
/// Returns a `EngineRef` pointing to the underlying context.
fn as_engine_ref(&self) -> EngineRef<'_>;
}
impl AsEngineRef for EngineRef<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: self.inner,
tunables: self.tunables,
}
}
}

View File

@@ -23,6 +23,7 @@ mod lib {
} }
} }
mod engineref;
pub(crate) mod error; pub(crate) mod error;
mod export; mod export;
mod exports; mod exports;
@@ -43,6 +44,7 @@ mod types;
mod value; mod value;
mod wasm_bindgen_polyfill; mod wasm_bindgen_polyfill;
pub use crate::js::engineref::{AsEngineRef, EngineRef};
pub use crate::js::error::{DeserializeError, InstantiationError, SerializeError}; pub use crate::js::error::{DeserializeError, InstantiationError, SerializeError};
pub use crate::js::export::Export; pub use crate::js::export::Export;
pub use crate::js::exports::{ExportError, Exportable, Exports, ExportsIterator}; pub use crate::js::exports::{ExportError, Exportable, Exports, ExportsIterator};

View File

@@ -180,6 +180,42 @@ impl<T: AsStoreMut> AsStoreMut for &'_ mut T {
} }
} }
impl AsEngineRef for Store {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: &self.engine,
tunables: self.inner.tunables.as_ref(),
}
}
}
impl AsEngineRef for &Store {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: &self.engine,
tunables: self.inner.tunables.as_ref(),
}
}
}
impl AsEngineRef for StoreRef<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: &self.inner.engine,
tunables: self.inner.tunables.as_ref(),
}
}
}
impl AsEngineRef for StoreMut<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: &self.inner.engine,
tunables: self.inner.tunables.as_ref(),
}
}
}
pub use objects::*; pub use objects::*;
mod objects { mod objects {

View File

@@ -0,0 +1,47 @@
use crate::Tunables;
use wasmer_compiler::Engine;
/// A temporary handle to an [`Engine`] and [`Tunables`].
/// EngineRef can be used to build a [`Module`]
/// It can be created directly with an [`Engine`] and [`Tunables`]
/// Or from anything implementing [`AsEngineRef`]
/// like from [`Store`] typicaly
pub struct EngineRef<'a> {
/// The inner engine
pub(crate) inner: &'a Engine,
/// optionnal tunnables
pub(crate) tunables: &'a dyn Tunables,
}
impl<'a> EngineRef<'a> {
/// Get inner [`Engine`]
pub fn engine(&self) -> &Engine {
self.inner
}
/// Get the [`Tunables`]
pub fn tunables(&self) -> &dyn Tunables {
self.tunables
}
/// Create an EngineRef from an Engine and Tunables
pub fn new(engine: &'a Engine, tunables: &'a dyn Tunables) -> Self {
EngineRef {
inner: engine,
tunables,
}
}
}
/// Helper trait for a value that is convertible to a [`EngineRef`].
pub trait AsEngineRef {
/// Returns a `EngineRef` pointing to the underlying context.
fn as_engine_ref(&self) -> EngineRef<'_>;
}
impl AsEngineRef for EngineRef<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: self.inner,
tunables: self.tunables,
}
}
}

View File

@@ -1,3 +1,4 @@
mod engineref;
mod exports; mod exports;
mod extern_ref; mod extern_ref;
mod externals; mod externals;
@@ -13,6 +14,7 @@ mod store;
mod tunables; mod tunables;
mod value; mod value;
pub use crate::sys::engineref::{AsEngineRef, EngineRef};
pub use crate::sys::exports::{ExportError, Exportable, Exports, ExportsIterator}; pub use crate::sys::exports::{ExportError, Exportable, Exports, ExportsIterator};
pub use crate::sys::extern_ref::ExternRef; pub use crate::sys::extern_ref::ExternRef;
pub use crate::sys::externals::{ pub use crate::sys::externals::{

View File

@@ -1,4 +1,5 @@
use crate::sys::InstantiationError; use crate::sys::InstantiationError;
use crate::AsEngineRef;
use crate::AsStoreMut; use crate::AsStoreMut;
use crate::AsStoreRef; use crate::AsStoreRef;
use bytes::Bytes; use bytes::Bytes;
@@ -159,7 +160,7 @@ impl Module {
/// # } /// # }
/// ``` /// ```
#[allow(unreachable_code)] #[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")] #[cfg(feature = "wat")]
let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| { let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| {
CompileError::Wasm(WasmError::Generic(format!( CompileError::Wasm(WasmError::Generic(format!(
@@ -167,19 +168,19 @@ impl Module {
e e
))) )))
})?; })?;
Self::from_binary(store, bytes.as_ref()) Self::from_binary(engine, bytes.as_ref())
} }
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
/// Creates a new WebAssembly module from a file path. /// Creates a new WebAssembly module from a file path.
pub fn from_file( pub fn from_file(
store: &impl AsStoreRef, engine: &impl AsEngineRef,
file: impl AsRef<Path>, file: impl AsRef<Path>,
) -> Result<Self, IoCompileError> { ) -> Result<Self, IoCompileError> {
let file_ref = file.as_ref(); let file_ref = file.as_ref();
let canonical = file_ref.canonicalize()?; let canonical = file_ref.canonicalize()?;
let wasm_bytes = std::fs::read(file_ref)?; 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. // Set the module name to the absolute path of the filename.
// This is useful for debugging the stack traces. // This is useful for debugging the stack traces.
let filename = canonical.as_path().to_str().unwrap(); let filename = canonical.as_path().to_str().unwrap();
@@ -193,9 +194,9 @@ impl Module {
/// Opposed to [`Module::new`], this function is not compatible with /// Opposed to [`Module::new`], this function is not compatible with
/// the WebAssembly text format (if the "wat" feature is enabled for /// the WebAssembly text format (if the "wat" feature is enabled for
/// this crate). /// this crate).
pub fn from_binary(store: &impl AsStoreRef, binary: &[u8]) -> Result<Self, CompileError> { pub fn from_binary(engine: &impl AsEngineRef, binary: &[u8]) -> Result<Self, CompileError> {
Self::validate(store, binary)?; Self::validate(engine, binary)?;
unsafe { Self::from_binary_unchecked(store, binary) } unsafe { Self::from_binary_unchecked(engine, binary) }
} }
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
@@ -207,10 +208,10 @@ impl Module {
/// in environments where the WebAssembly modules are trusted and validated /// in environments where the WebAssembly modules are trusted and validated
/// beforehand. /// beforehand.
pub unsafe fn from_binary_unchecked( pub unsafe fn from_binary_unchecked(
store: &impl AsStoreRef, engine: &impl AsEngineRef,
binary: &[u8], binary: &[u8],
) -> Result<Self, CompileError> { ) -> Result<Self, CompileError> {
let module = Self::compile(store, binary)?; let module = Self::compile(engine, binary)?;
Ok(module) Ok(module)
} }
@@ -221,16 +222,16 @@ impl Module {
/// This validation is normally pretty fast and checks the enabled /// This validation is normally pretty fast and checks the enabled
/// WebAssembly features in the Store Engine to assure deterministic /// WebAssembly features in the Store Engine to assure deterministic
/// validation of the Module. /// validation of the Module.
pub fn validate(store: &impl AsStoreRef, binary: &[u8]) -> Result<(), CompileError> { pub fn validate(engine: &impl AsEngineRef, binary: &[u8]) -> Result<(), CompileError> {
store.as_store_ref().engine().validate(binary) engine.as_engine_ref().engine().validate(binary)
} }
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
fn compile(store: &impl AsStoreRef, binary: &[u8]) -> Result<Self, CompileError> { fn compile(engine: &impl AsEngineRef, binary: &[u8]) -> Result<Self, CompileError> {
let artifact = store let artifact = engine
.as_store_ref() .as_engine_ref()
.engine() .engine()
.compile(binary, store.as_store_ref().tunables())?; .compile(binary, engine.as_engine_ref().tunables())?;
Ok(Self::from_artifact(artifact)) Ok(Self::from_artifact(artifact))
} }

View File

@@ -1,3 +1,4 @@
use crate::sys::engineref::{AsEngineRef, EngineRef};
use crate::sys::tunables::BaseTunables; use crate::sys::tunables::BaseTunables;
use std::fmt; use std::fmt;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@@ -202,6 +203,42 @@ impl AsStoreMut for Store {
} }
} }
impl AsEngineRef for Store {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: &self.engine,
tunables: self.inner.tunables.as_ref(),
}
}
}
impl AsEngineRef for &Store {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: &self.engine,
tunables: self.inner.tunables.as_ref(),
}
}
}
impl AsEngineRef for StoreRef<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: &self.inner.engine,
tunables: self.inner.tunables.as_ref(),
}
}
}
impl AsEngineRef for StoreMut<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef {
inner: &self.inner.engine,
tunables: self.inner.tunables.as_ref(),
}
}
}
impl fmt::Debug for Store { impl fmt::Debug for Store {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Store").finish() f.debug_struct("Store").finish()

View File

@@ -0,0 +1,58 @@
use crate::units::Pages;
use crate::compilation::target::{PointerWidth, Target};
/// Tunable parameters for WebAssembly compilation.
/// This is the reference implementation of the `Tunables` trait,
/// used by default.
///
/// You can use this as a template for creating a custom Tunables
/// implementation or use composition to wrap your Tunables around
/// this one. The later approach is demonstrated in the
/// tunables-limit-memory example.
#[derive(Clone)]
pub struct BaseTunables {
/// For static heaps, the size in wasm pages of the heap protected by bounds checking.
pub static_memory_bound: Pages,
/// The size in bytes of the offset guard for static heaps.
pub static_memory_offset_guard_size: u64,
/// The size in bytes of the offset guard for dynamic heaps.
pub dynamic_memory_offset_guard_size: u64,
}
impl BaseTunables {
/// Get the `BaseTunables` for a specific Target
pub fn for_target(target: &Target) -> Self {
let triple = target.triple();
let pointer_width: PointerWidth = triple.pointer_width().unwrap();
let (static_memory_bound, static_memory_offset_guard_size): (Pages, u64) =
match pointer_width {
PointerWidth::U16 => (0x400.into(), 0x1000),
PointerWidth::U32 => (0x4000.into(), 0x1_0000),
// Static Memory Bound:
// Allocating 4 GiB of address space let us avoid the
// need for explicit bounds checks.
// Static Memory Guard size:
// Allocating 2 GiB of address space lets us translate wasm
// offsets into x86 offsets as aggressively as we can.
PointerWidth::U64 => (0x1_0000.into(), 0x8000_0000),
};
// Allocate a small guard to optimize common cases but without
// wasting too much memory.
// The Windows memory manager seems more laxed than the other ones
// And a guard of just 1 page may not be enough is some borderline cases
// So using 2 pages for guard on this platform
#[cfg(target_os = "windows")]
let dynamic_memory_offset_guard_size: u64 = 0x2_0000;
#[cfg(not(target_os = "windows"))]
let dynamic_memory_offset_guard_size: u64 = 0x1_0000;
Self {
static_memory_bound,
static_memory_offset_guard_size,
dynamic_memory_offset_guard_size,
}
}
}