Remove Engine trait

This commit is contained in:
Manos Pitsidianakis
2022-07-04 09:00:53 +03:00
parent 187d2e6364
commit 987a90c0dc
15 changed files with 171 additions and 225 deletions

View File

@ -9,22 +9,22 @@ SHELL=/usr/bin/env bash
# The matrix is the product of the following columns: # The matrix is the product of the following columns:
# #
# |------------|-----------|----------|--------------|-------| # |------------|----------|--------------|-------|
# | Compiler Engine Platform Architecture libc | # | Compiler Platform Architecture libc |
# |------------|-----------|----------|--------------|-------| # |------------|----------|--------------|-------|
# | Cranelift | Universal | Linux | amd64 | glibc | # | Cranelift | Linux | amd64 | glibc |
# | LLVM | | Darwin | aarch64 | musl | # | LLVM | Darwin | aarch64 | musl |
# | Singlepass | | Windows | | | # | Singlepass | Windows | | |
# |------------|-----------|----------|--------------|-------| # |------------|----------|--------------|-------|
# #
# Here is what works and what doesn't: # Here is what works and what doesn't:
# #
# * Cranelift with the Universal engine works everywhere, # * Cranelift works everywhere,
# #
# * LLVM with the Universal engine works on Linux+Darwin/`amd64`, # * LLVM works on Linux+Darwin/`amd64`,
# but it doesn't work on */`aarch64` or Windows/*. # but it doesn't work on */`aarch64` or Windows/*.
# #
# * Singlepass with the Universal engine works on Linux+Darwin/`amd64`, but # * Singlepass works on Linux+Darwin/`amd64`, but
# it doesn't work on */`aarch64` or Windows/*. # it doesn't work on */`aarch64` or Windows/*.
# #
# * Windows isn't tested on `aarch64`, that's why we consider it's not # * Windows isn't tested on `aarch64`, that's why we consider it's not

View File

@ -2,7 +2,7 @@
use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary, fuzz_target}; use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary, fuzz_target};
use wasm_smith::{Config, ConfiguredModule}; use wasm_smith::{Config, ConfiguredModule};
use wasmer::{CompilerConfig, Engine, Module, Store}; use wasmer::{CompilerConfig, Module, Store, UniversalEngine};
use wasmer_compiler::Universal; use wasmer_compiler::Universal;
use wasmer_compiler_cranelift::Cranelift; use wasmer_compiler_cranelift::Cranelift;
use wasmer_compiler_llvm::LLVM; use wasmer_compiler_llvm::LLVM;
@ -23,8 +23,8 @@ impl Config for NoImportsConfig {
} }
} }
fn compile_and_compare(name: &str, engine: impl Engine, wasm: &[u8]) { fn compile_and_compare(name: &str, engine: UniversalEngine, wasm: &[u8]) {
let mut store = Store::new_with_engine(&engine); let store = Store::new_with_engine(&engine);
// compile for first time // compile for first time
let module = Module::new(&store, wasm).unwrap(); let module = Module::new(&store, wasm).unwrap();

View File

@ -36,7 +36,7 @@ pub use target_lexicon::{Architecture, CallingConvention, OperatingSystem, Tripl
pub use wasmer_compiler::{ pub use wasmer_compiler::{
wasmparser, CompilerConfig, FunctionMiddleware, MiddlewareReaderState, ModuleMiddleware, wasmparser, CompilerConfig, FunctionMiddleware, MiddlewareReaderState, ModuleMiddleware,
}; };
pub use wasmer_compiler::{Engine, Features, FrameInfo, LinkError, RuntimeError, Tunables}; pub use wasmer_compiler::{Features, FrameInfo, LinkError, RuntimeError, Tunables};
pub use wasmer_derive::ValueType; pub use wasmer_derive::ValueType;
pub use wasmer_types::is_wasm; pub use wasmer_types::is_wasm;
pub use wasmer_types::{ pub use wasmer_types::{

View File

@ -1,12 +1,11 @@
use crate::sys::tunables::BaseTunables; use crate::sys::tunables::BaseTunables;
use std::fmt; use std::fmt;
use std::sync::Arc; use std::sync::{Arc, RwLock};
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
use wasmer_compiler::CompilerConfig; use wasmer_compiler::CompilerConfig;
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
use wasmer_compiler::Universal; use wasmer_compiler::{Tunables, Universal, UniversalEngine};
use wasmer_compiler::{Engine, Tunables}; use wasmer_vm::{init_traps, TrapHandler, TrapHandlerFn};
use wasmer_vm::{init_traps, TrapHandlerFn};
use wasmer_vm::StoreObjects; use wasmer_vm::StoreObjects;
@ -15,7 +14,7 @@ use wasmer_vm::StoreObjects;
/// wrap the actual context in a box. /// wrap the actual context in a box.
pub(crate) struct StoreInner { pub(crate) struct StoreInner {
pub(crate) objects: StoreObjects, pub(crate) objects: StoreObjects,
pub(crate) engine: Arc<dyn Engine + Send + Sync>, pub(crate) engine: Arc<UniversalEngine>,
pub(crate) tunables: Box<dyn Tunables + Send + Sync>, pub(crate) tunables: Box<dyn Tunables + Send + Sync>,
pub(crate) trap_handler: Option<Box<TrapHandlerFn<'static>>>, pub(crate) trap_handler: Option<Box<TrapHandlerFn<'static>>>,
} }
@ -32,6 +31,8 @@ pub(crate) struct StoreInner {
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#store> /// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#store>
pub struct Store { pub struct Store {
pub(crate) inner: Box<StoreInner>, pub(crate) inner: Box<StoreInner>,
engine: Arc<UniversalEngine>,
trap_handler: Arc<RwLock<Option<Box<TrapHandlerFn<'static>>>>>,
} }
impl Store { impl Store {
@ -43,10 +44,7 @@ impl Store {
} }
/// Creates a new `Store` with a specific [`Engine`]. /// Creates a new `Store` with a specific [`Engine`].
pub fn new_with_engine<E>(engine: &E) -> Self pub fn new_with_engine(engine: &UniversalEngine) -> Self {
where
E: Engine + ?Sized,
{
Self::new_with_tunables(engine, BaseTunables::for_target(engine.target())) Self::new_with_tunables(engine, BaseTunables::for_target(engine.target()))
} }
@ -56,10 +54,10 @@ impl Store {
} }
/// Creates a new `Store` with a specific [`Engine`] and [`Tunables`]. /// Creates a new `Store` with a specific [`Engine`] and [`Tunables`].
pub fn new_with_tunables<E>(engine: &E, tunables: impl Tunables + Send + Sync + 'static) -> Self pub fn new_with_tunables(
where engine: &UniversalEngine,
E: Engine + ?Sized, tunables: impl Tunables + Send + Sync + 'static,
{ ) -> Self {
// Make sure the signal handlers are installed. // Make sure the signal handlers are installed.
// This is required for handling traps. // This is required for handling traps.
init_traps(); init_traps();
@ -71,6 +69,41 @@ impl Store {
tunables: Box::new(tunables), tunables: Box::new(tunables),
trap_handler: None, trap_handler: None,
}), }),
engine: engine.cloned(),
trap_handler: Arc::new(RwLock::new(None)),
}
}
/// Returns the [`Tunables`].
pub fn tunables(&self) -> &dyn Tunables {
self.inner.tunables.as_ref()
}
/// Returns the [`Engine`].
pub fn engine(&self) -> &Arc<UniversalEngine> {
&self.engine
}
/// Checks whether two stores are identical. A store is considered
/// equal to another store if both have the same engine. The
/// tunables are excluded from the logic.
pub fn same(a: &Self, b: &Self) -> bool {
a.engine.id() == b.engine.id()
}
}
impl PartialEq for Store {
fn eq(&self, other: &Self) -> bool {
Self::same(self, other)
}
}
unsafe impl TrapHandler for Store {
fn custom_trap_handler(&self, call: &dyn Fn(&TrapHandlerFn) -> bool) -> bool {
if let Some(handler) = self.trap_handler.read().unwrap().as_ref() {
call(handler)
} else {
false
} }
} }
} }
@ -109,7 +142,7 @@ impl Default for Store {
} }
#[allow(unreachable_code, unused_mut)] #[allow(unreachable_code, unused_mut)]
fn get_engine(mut config: impl CompilerConfig + 'static) -> impl Engine + Send + Sync { fn get_engine(mut config: impl CompilerConfig + 'static) -> UniversalEngine {
cfg_if::cfg_if! { cfg_if::cfg_if! {
if #[cfg(feature = "default-universal")] { if #[cfg(feature = "default-universal")] {
wasmer_compiler::Universal::new(config) wasmer_compiler::Universal::new(config)
@ -165,7 +198,7 @@ impl<'a> StoreRef<'a> {
} }
/// Returns the [`Engine`]. /// Returns the [`Engine`].
pub fn engine(&self) -> &Arc<dyn Engine + Send + Sync> { pub fn engine(&self) -> &Arc<UniversalEngine> {
&self.inner.engine &self.inner.engine
} }
@ -198,7 +231,7 @@ impl<'a> StoreMut<'a> {
} }
/// Returns the [`Engine`]. /// Returns the [`Engine`].
pub fn engine(&self) -> &Arc<dyn Engine + Send + Sync> { pub fn engine(&self) -> &Arc<UniversalEngine> {
&self.inner.engine &self.inner.engine
} }

View File

@ -12,9 +12,8 @@ use super::unstable::target_lexicon::wasmer_target_t;
use crate::error::update_last_error; use crate::error::update_last_error;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use std::sync::Arc; use std::sync::Arc;
use wasmer_api::Engine;
#[cfg(feature = "universal")] #[cfg(feature = "universal")]
use wasmer_compiler::Universal; use wasmer_compiler::{Universal, UniversalEngine};
/// Kind of compilers that can be used by the engines. /// Kind of compilers that can be used by the engines.
/// ///
@ -263,7 +262,7 @@ pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: was
/// cbindgen:ignore /// cbindgen:ignore
#[repr(C)] #[repr(C)]
pub struct wasm_engine_t { pub struct wasm_engine_t {
pub(crate) inner: Arc<dyn Engine + Send + Sync>, pub(crate) inner: Arc<UniversalEngine>,
} }
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
@ -296,7 +295,7 @@ cfg_if! {
#[no_mangle] #[no_mangle]
pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> { pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> {
let compiler_config: Box<dyn CompilerConfig> = get_default_compiler_config(); let compiler_config: Box<dyn CompilerConfig> = get_default_compiler_config();
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Universal::new(compiler_config).engine()); let engine: Arc<UniversalEngine> = Arc::new(Universal::new(compiler_config).engine());
Box::new(wasm_engine_t { inner: engine }) Box::new(wasm_engine_t { inner: engine })
} }
} else if #[cfg(feature = "universal")] { } else if #[cfg(feature = "universal")] {
@ -309,7 +308,7 @@ cfg_if! {
/// cbindgen:ignore /// cbindgen:ignore
#[no_mangle] #[no_mangle]
pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> { pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> {
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Universal::headless().engine()); let engine: Arc<UniversalEngine> = Arc::new(Universal::headless().engine());
Box::new(wasm_engine_t { inner: engine }) Box::new(wasm_engine_t { inner: engine })
} }
} else { } else {
@ -419,10 +418,11 @@ pub extern "C" fn wasm_engine_new_with_config(
compiler_config.canonicalize_nans(true); compiler_config.canonicalize_nans(true);
} }
let inner: Arc<dyn Engine + Send + Sync> = match config.engine { #[cfg(not(feature = "universal"))]
wasmer_engine_t::UNIVERSAL => { return return_with_error("Wasmer has not been compiled with the `universal` feature.");
cfg_if! { #[cfg(feature = "universal")]
if #[cfg(feature = "universal")] { let inner: Arc<UniversalEngine> =
{
let mut builder = Universal::new(compiler_config); let mut builder = Universal::new(compiler_config);
if let Some(target) = config.target { if let Some(target) = config.target {
@ -434,16 +434,10 @@ pub extern "C" fn wasm_engine_new_with_config(
} }
Arc::new(builder.engine()) Arc::new(builder.engine())
} else { };
return return_with_error("Wasmer has not been compiled with the `universal` feature.");
}
}
},
};
Some(Box::new(wasm_engine_t { inner })) Some(Box::new(wasm_engine_t { inner }))
} else { } else {
let inner: Arc<dyn Engine + Send + Sync> = match config.engine { let inner: Arc<UniversalEngine> =
wasmer_engine_t::UNIVERSAL => {
cfg_if! { cfg_if! {
if #[cfg(feature = "universal")] { if #[cfg(feature = "universal")] {
let mut builder = Universal::headless(); let mut builder = Universal::headless();
@ -460,9 +454,7 @@ pub extern "C" fn wasm_engine_new_with_config(
} else { } else {
return return_with_error("Wasmer has not been compiled with the `universal` feature."); return return_with_error("Wasmer has not been compiled with the `universal` feature.");
} }
} };
},
};
Some(Box::new(wasm_engine_t { inner })) Some(Box::new(wasm_engine_t { inner }))
} }
} }

View File

@ -1,4 +1,4 @@
use crate::store::{EngineType, StoreOptions}; use crate::store::StoreOptions;
use crate::warning; use crate::warning;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -39,15 +39,8 @@ impl Compile {
.context(format!("failed to compile `{}`", self.path.display())) .context(format!("failed to compile `{}`", self.path.display()))
} }
pub(crate) fn get_recommend_extension( pub(crate) fn get_recommend_extension(target_triple: &Triple) -> Result<&'static str> {
engine_type: &EngineType, Ok(wasmer_compiler::UniversalArtifactBuild::get_default_extension(target_triple))
target_triple: &Triple,
) -> Result<&'static str> {
Ok(match engine_type {
EngineType::Universal => {
wasmer_compiler::UniversalArtifactBuild::get_default_extension(target_triple)
}
})
} }
fn inner_execute(&self) -> Result<()> { fn inner_execute(&self) -> Result<()> {
@ -66,14 +59,13 @@ impl Compile {
Target::new(target_triple.clone(), features) Target::new(target_triple.clone(), features)
}) })
.unwrap_or_default(); .unwrap_or_default();
let (mut engine, engine_type, compiler_type) = let (mut engine, compiler_type) = self.store.get_engine_for_target(target.clone())?;
self.store.get_engine_for_target(target.clone())?;
let output_filename = self let output_filename = self
.output .output
.file_stem() .file_stem()
.map(|osstr| osstr.to_string_lossy().to_string()) .map(|osstr| osstr.to_string_lossy().to_string())
.unwrap_or_default(); .unwrap_or_default();
let recommended_extension = Self::get_recommend_extension(&engine_type, target.triple())?; let recommended_extension = Self::get_recommend_extension(target.triple())?;
match self.output.extension() { match self.output.extension() {
Some(ext) => { Some(ext) => {
if ext != recommended_extension { if ext != recommended_extension {
@ -86,7 +78,6 @@ impl Compile {
} }
let tunables = self.store.get_tunables_for_target(&target)?; let tunables = self.store.get_tunables_for_target(&target)?;
println!("Engine: {}", engine_type.to_string());
println!("Compiler: {}", compiler_type.to_string()); println!("Compiler: {}", compiler_type.to_string());
println!("Target: {}", target.triple()); println!("Target: {}", target.triple());

View File

@ -27,7 +27,7 @@ impl Validate {
Triple::from_str("x86_64-linux-gnu").unwrap(), Triple::from_str("x86_64-linux-gnu").unwrap(),
CpuFeature::SSE2 | CpuFeature::AVX, CpuFeature::SSE2 | CpuFeature::AVX,
); );
let (engine, _engine_type, _compiler_type) = self.store.get_engine_for_target(target)?; let (engine, _compiler_type) = self.store.get_engine_for_target(target)?;
let module_contents = std::fs::read(&self.path)?; let module_contents = std::fs::read(&self.path)?;
if !is_wasm(&module_contents) { if !is_wasm(&module_contents) {
bail!("`wasmer validate` only validates WebAssembly files"); bail!("`wasmer validate` only validates WebAssembly files");

View File

@ -172,14 +172,10 @@ impl CompilerOptions {
&self, &self,
target: Target, target: Target,
compiler_config: Box<dyn CompilerConfig>, compiler_config: Box<dyn CompilerConfig>,
engine_type: EngineType,
) -> Result<UniversalEngineBuilder> { ) -> Result<UniversalEngineBuilder> {
let features = self.get_features(compiler_config.default_features_for_target(&target))?; let features = self.get_features(compiler_config.default_features_for_target(&target))?;
let engine: UniversalEngineBuilder = match engine_type { let engine: UniversalEngineBuilder =
EngineType::Universal => { UniversalEngineBuilder::new(Some(compiler_config.compiler()), features);
UniversalEngineBuilder::new(Some(compiler_config.compiler()), features)
}
};
Ok(engine) Ok(engine)
} }
@ -361,48 +357,23 @@ impl ToString for CompilerType {
} }
} }
/// The engine used for the store
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum EngineType {
/// Universal Engine
Universal,
}
impl ToString for EngineType {
fn to_string(&self) -> String {
match self {
Self::Universal => "universal".to_string(),
}
}
}
impl StoreOptions { impl StoreOptions {
/// Get a UniversalEngineBulder for the Target /// Get a UniversalEngineBulder for the Target
pub fn get_engine_for_target( pub fn get_engine_for_target(
&self, &self,
target: Target, target: Target,
) -> Result<(UniversalEngineBuilder, EngineType, CompilerType)> { ) -> Result<(UniversalEngineBuilder, CompilerType)> {
let (compiler_config, compiler_type) = self.compiler.get_compiler_config()?; let (compiler_config, compiler_type) = self.compiler.get_compiler_config()?;
let (engine, engine_type) = self.get_engine_with_compiler(target, compiler_config)?; let engine = self.get_engine_with_compiler(target, compiler_config)?;
Ok((engine, engine_type, compiler_type)) Ok((engine, compiler_type))
}
/// Get default EngineType
pub fn get_engine(&self) -> Result<EngineType> {
Ok(EngineType::Universal)
} }
fn get_engine_with_compiler( fn get_engine_with_compiler(
&self, &self,
target: Target, target: Target,
compiler_config: Box<dyn CompilerConfig>, compiler_config: Box<dyn CompilerConfig>,
) -> Result<(UniversalEngineBuilder, EngineType)> { ) -> Result<UniversalEngineBuilder> {
let engine_type = self.get_engine()?; self.compiler.get_engine_by_type(target, compiler_config)
let engine = self
.compiler
.get_engine_by_type(target, compiler_config, engine_type)?;
Ok((engine, engine_type))
} }
/// Get (Subset)Tunables for the Target /// Get (Subset)Tunables for the Target

View File

@ -112,9 +112,9 @@ impl CompilerOptions {
&self, &self,
target: Target, target: Target,
compiler_config: Box<dyn CompilerConfig>, compiler_config: Box<dyn CompilerConfig>,
) -> Result<Box<dyn Engine + Send + Sync>> { ) -> Result<Box<UniversalEngine>> {
let features = self.get_features(compiler_config.default_features_for_target(&target))?; let features = self.get_features(compiler_config.default_features_for_target(&target))?;
let engine: Box<dyn Engine + Send + Sync> = Box::new( let engine: Box<UniversalEngine> = Box::new(
wasmer_compiler::Universal::new(compiler_config) wasmer_compiler::Universal::new(compiler_config)
.features(features) .features(features)
.target(target) .target(target)
@ -321,7 +321,7 @@ impl StoreOptions {
&self, &self,
target: Target, target: Target,
compiler_config: Box<dyn CompilerConfig>, compiler_config: Box<dyn CompilerConfig>,
) -> Result<Box<dyn Engine + Send + Sync>> { ) -> Result<Box<UniversalEngine>> {
let engine = self.compiler.get_engine(target, compiler_config)?; let engine = self.compiler.get_engine(target, compiler_config)?;
Ok(engine) Ok(engine)
@ -331,8 +331,8 @@ impl StoreOptions {
// If we don't have a compiler, but we have an engine // If we don't have a compiler, but we have an engine
#[cfg(not(feature = "compiler"))] #[cfg(not(feature = "compiler"))]
impl StoreOptions { impl StoreOptions {
fn get_engine_headless(&self) -> Result<Arc<dyn Engine + Send + Sync>> { fn get_engine_headless(&self) -> Result<Arc<UniversalEngine>> {
let engine: Arc<dyn Engine + Send + Sync> = let engine: Arc<UniversalEngine> =
Arc::new(wasmer_compiler::Universal::headless().engine()); Arc::new(wasmer_compiler::Universal::headless().engine());
Ok(engine) Ok(engine)
} }

View File

@ -1,97 +0,0 @@
//! Engine trait and associated types.
use crate::engine::tunables::Tunables;
use crate::UniversalArtifact;
use memmap2::Mmap;
use std::path::Path;
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use std::sync::Arc;
use wasmer_types::{CompileError, DeserializeError, FunctionType, Target};
use wasmer_vm::VMSharedSignatureIndex;
/// A unimplemented Wasmer `Engine`.
///
/// This trait is used by implementors to implement custom engines
/// such as: Universal or Native.
///
/// The product that an `Engine` produces and consumes is the [`Artifact`].
pub trait Engine {
/// Gets the target
fn target(&self) -> &Target;
/// Register a signature
fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex;
/// Lookup a signature
fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FunctionType>;
/// Validates a WebAssembly module
fn validate(&self, binary: &[u8]) -> Result<(), CompileError>;
/// Compile a WebAssembly binary
fn compile(
&self,
binary: &[u8],
tunables: &dyn Tunables,
) -> Result<Arc<UniversalArtifact>, CompileError>;
/// Deserializes a WebAssembly module
///
/// # Safety
///
/// The serialized content must represent a serialized WebAssembly module.
unsafe fn deserialize(&self, bytes: &[u8]) -> Result<Arc<UniversalArtifact>, DeserializeError>;
/// Deserializes a WebAssembly module from a path
///
/// # Safety
///
/// The file's content must represent a serialized WebAssembly module.
unsafe fn deserialize_from_file(
&self,
file_ref: &Path,
) -> Result<Arc<UniversalArtifact>, DeserializeError> {
let file = std::fs::File::open(file_ref)?;
let mmap = Mmap::map(&file)?;
self.deserialize(&mmap)
}
/// A unique identifier for this object.
///
/// This exists to allow us to compare two Engines for equality. Otherwise,
/// comparing two trait objects unsafely relies on implementation details
/// of trait representation.
fn id(&self) -> &EngineId;
/// Clone the engine
fn cloned(&self) -> Arc<dyn Engine + Send + Sync>;
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
/// A unique identifier for an Engine.
pub struct EngineId {
id: usize,
}
impl EngineId {
/// Format this identifier as a string.
pub fn id(&self) -> String {
format!("{}", &self.id)
}
}
impl Clone for EngineId {
fn clone(&self) -> Self {
Self::default()
}
}
impl Default for EngineId {
fn default() -> Self {
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
Self {
id: NEXT_ID.fetch_add(1, SeqCst),
}
}
}

View File

@ -1,7 +1,6 @@
//! Generic Engine abstraction for Wasmer Engines. //! The Wasmer Engine.
mod error; mod error;
mod inner;
mod resolver; mod resolver;
mod trap; mod trap;
mod tunables; mod tunables;
@ -10,7 +9,6 @@ mod tunables;
mod universal; mod universal;
pub use self::error::{InstantiationError, LinkError}; pub use self::error::{InstantiationError, LinkError};
pub use self::inner::{Engine, EngineId};
pub use self::resolver::resolve_imports; pub use self::resolver::resolve_imports;
pub use self::trap::*; pub use self::trap::*;
pub use self::tunables::Tunables; pub use self::tunables::Tunables;

View File

@ -5,13 +5,13 @@ use super::engine::{UniversalEngine, UniversalEngineInner};
use crate::engine::universal::link::link_module; use crate::engine::universal::link::link_module;
use crate::ArtifactCreate; use crate::ArtifactCreate;
use crate::Features; use crate::Features;
#[cfg(feature = "universal_engine")]
use crate::ModuleEnvironment;
use crate::UniversalArtifactBuild; use crate::UniversalArtifactBuild;
use crate::{ use crate::{
register_frame_info, resolve_imports, FunctionExtent, GlobalFrameInfoRegistration, register_frame_info, resolve_imports, FunctionExtent, GlobalFrameInfoRegistration,
InstantiationError, MetadataHeader, RuntimeError, Tunables, InstantiationError, MetadataHeader, RuntimeError, Tunables,
}; };
#[cfg(feature = "universal_engine")]
use crate::{Engine, ModuleEnvironment};
use enumset::EnumSet; use enumset::EnumSet;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;

View File

@ -4,7 +4,10 @@
use crate::Compiler; use crate::Compiler;
use crate::UniversalEngineBuilder; use crate::UniversalEngineBuilder;
use crate::{CodeMemory, UniversalArtifact}; use crate::{CodeMemory, UniversalArtifact};
use crate::{Engine, EngineId, FunctionExtent, Tunables}; use crate::{FunctionExtent, Tunables};
use memmap2::Mmap;
use std::path::Path;
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use wasmer_types::entity::PrimaryMap; use wasmer_types::entity::PrimaryMap;
use wasmer_types::FunctionBody; use wasmer_types::FunctionBody;
@ -74,34 +77,32 @@ impl UniversalEngine {
pub(crate) fn inner_mut(&self) -> std::sync::MutexGuard<'_, UniversalEngineInner> { pub(crate) fn inner_mut(&self) -> std::sync::MutexGuard<'_, UniversalEngineInner> {
self.inner.lock().unwrap() self.inner.lock().unwrap()
} }
}
impl Engine for UniversalEngine { /// Gets the target
/// The target pub fn target(&self) -> &Target {
fn target(&self) -> &Target {
&self.target &self.target
} }
/// Register a signature /// Register a signature
fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex { pub fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex {
let compiler = self.inner(); let compiler = self.inner();
compiler.signatures().register(func_type) compiler.signatures().register(func_type)
} }
/// Lookup a signature /// Lookup a signature
fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FunctionType> { pub fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FunctionType> {
let compiler = self.inner(); let compiler = self.inner();
compiler.signatures().lookup(sig) compiler.signatures().lookup(sig)
} }
/// Validates a WebAssembly module /// Validates a WebAssembly module
fn validate(&self, binary: &[u8]) -> Result<(), CompileError> { pub fn validate(&self, binary: &[u8]) -> Result<(), CompileError> {
self.inner().validate(binary) self.inner().validate(binary)
} }
/// Compile a WebAssembly binary /// Compile a WebAssembly binary
#[cfg(feature = "universal_engine")] #[cfg(feature = "universal_engine")]
fn compile( pub fn compile(
&self, &self,
binary: &[u8], binary: &[u8],
tunables: &dyn Tunables, tunables: &dyn Tunables,
@ -111,7 +112,7 @@ impl Engine for UniversalEngine {
/// Compile a WebAssembly binary /// Compile a WebAssembly binary
#[cfg(not(feature = "universal_engine"))] #[cfg(not(feature = "universal_engine"))]
fn compile( pub fn compile(
&self, &self,
_binary: &[u8], _binary: &[u8],
_tunables: &dyn Tunables, _tunables: &dyn Tunables,
@ -123,15 +124,42 @@ impl Engine for UniversalEngine {
} }
/// Deserializes a WebAssembly module /// Deserializes a WebAssembly module
unsafe fn deserialize(&self, bytes: &[u8]) -> Result<Arc<UniversalArtifact>, DeserializeError> { ///
/// # Safety
///
/// The serialized content must represent a serialized WebAssembly module.
pub unsafe fn deserialize(
&self,
bytes: &[u8],
) -> Result<Arc<UniversalArtifact>, DeserializeError> {
Ok(Arc::new(UniversalArtifact::deserialize(self, bytes)?)) Ok(Arc::new(UniversalArtifact::deserialize(self, bytes)?))
} }
fn id(&self) -> &EngineId { /// Deserializes a WebAssembly module from a path
///
/// # Safety
///
/// The file's content must represent a serialized WebAssembly module.
pub unsafe fn deserialize_from_file(
&self,
file_ref: &Path,
) -> Result<Arc<UniversalArtifact>, DeserializeError> {
let file = std::fs::File::open(file_ref)?;
let mmap = Mmap::map(&file)?;
self.deserialize(&mmap)
}
/// A unique identifier for this object.
///
/// This exists to allow us to compare two Engines for equality. Otherwise,
/// comparing two trait objects unsafely relies on implementation details
/// of trait representation.
pub fn id(&self) -> &EngineId {
&self.engine_id &self.engine_id
} }
fn cloned(&self) -> Arc<dyn Engine + Send + Sync> { /// Clone the engine
pub fn cloned(&self) -> Arc<Self> {
Arc::new(self.clone()) Arc::new(self.clone())
} }
} }
@ -285,3 +313,32 @@ impl UniversalEngineInner {
&self.signatures &self.signatures
} }
} }
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
/// A unique identifier for an Engine.
pub struct EngineId {
id: usize,
}
impl EngineId {
/// Format this identifier as a string.
pub fn id(&self) -> String {
format!("{}", &self.id)
}
}
impl Clone for EngineId {
fn clone(&self) -> Self {
Self::default()
}
}
impl Default for EngineId {
fn default() -> Self {
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
Self {
id: NEXT_ID.fetch_add(1, SeqCst),
}
}
}

View File

@ -1,5 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use wasmer::{CompilerConfig, Engine, Features, ModuleMiddleware, Store}; use wasmer::{CompilerConfig, Features, ModuleMiddleware, Store};
use wasmer_compiler::UniversalEngine;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum Compiler { pub enum Compiler {
@ -49,7 +50,7 @@ impl Config {
Store::new_with_engine(&*engine) Store::new_with_engine(&*engine)
} }
pub fn engine(&self, compiler_config: Box<dyn CompilerConfig>) -> Box<dyn Engine> { pub fn engine(&self, compiler_config: Box<dyn CompilerConfig>) -> Box<UniversalEngine> {
let mut engine = wasmer_compiler::Universal::new(compiler_config); let mut engine = wasmer_compiler::Universal::new(compiler_config);
if let Some(ref features) = self.features { if let Some(ref features) = self.features {
engine = engine.features(features.clone()) engine = engine.features(features.clone())
@ -57,7 +58,7 @@ impl Config {
Box::new(engine.engine()) Box::new(engine.engine())
} }
pub fn engine_headless(&self) -> Box<dyn Engine> { pub fn engine_headless(&self) -> Box<UniversalEngine> {
Box::new(wasmer_compiler::Universal::headless().engine()) Box::new(wasmer_compiler::Universal::headless().engine())
} }

View File

@ -115,7 +115,7 @@ impl Ignores {
arch = Some(alias.to_string()); arch = Some(alias.to_string());
} }
// Engines // Engines
"universal" => { "universal" | "engine" => {
engine = Some(alias.to_string()); engine = Some(alias.to_string());
} }
// Compilers // Compilers