From d25f47d54d867fcdfefe4a8d70ca21d09cf6c61e Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 2 May 2020 18:41:05 -0700 Subject: [PATCH] Got half-baked engine --- Cargo.lock | 30 ++++++ Cargo.toml | 1 + lib/api/Cargo.toml | 1 + lib/api/src/import_object.rs | 2 +- lib/api/src/instance.rs | 2 +- lib/api/src/lib.rs | 2 +- lib/api/src/module.rs | 9 +- lib/api/src/tunables.rs | 3 +- lib/engine/Cargo.toml | 34 +++++++ lib/engine/README.md | 12 +++ lib/engine/src/engine.rs | 49 +++++++++ lib/{jit => engine}/src/error.rs | 1 - lib/engine/src/lib.rs | 45 +++++++++ lib/engine/src/module.rs | 19 ++++ lib/{jit => engine}/src/resolver.rs | 0 lib/engine/src/serialize.rs | 107 ++++++++++++++++++++ lib/{jit => engine}/src/trap/error.rs | 0 lib/{jit => engine}/src/trap/frame_info.rs | 0 lib/engine/src/trap/mod.rs | 4 + lib/{jit => engine}/src/tunables.rs | 0 lib/jit/Cargo.toml | 1 + lib/jit/src/engine.rs | 38 +++---- lib/jit/src/lib.rs | 12 --- lib/jit/src/link.rs | 11 +-- lib/jit/src/module.rs | 57 +++++------ lib/jit/src/serialize.rs | 109 +-------------------- lib/jit/src/trap/mod.rs | 4 - 27 files changed, 363 insertions(+), 190 deletions(-) create mode 100644 lib/engine/Cargo.toml create mode 100644 lib/engine/README.md create mode 100644 lib/engine/src/engine.rs rename lib/{jit => engine}/src/error.rs (98%) create mode 100644 lib/engine/src/lib.rs create mode 100644 lib/engine/src/module.rs rename lib/{jit => engine}/src/resolver.rs (100%) create mode 100644 lib/engine/src/serialize.rs rename lib/{jit => engine}/src/trap/error.rs (100%) rename lib/{jit => engine}/src/trap/frame_info.rs (100%) create mode 100644 lib/engine/src/trap/mod.rs rename lib/{jit => engine}/src/tunables.rs (100%) delete mode 100644 lib/jit/src/trap/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 6c96d75a4..38d7a7fea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -353,6 +353,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "downcast-rs" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6" + [[package]] name = "either" version = "1.5.3" @@ -1465,6 +1471,7 @@ dependencies = [ "wasmer-compiler-cranelift", "wasmer-compiler-llvm", "wasmer-compiler-singlepass", + "wasmer-engine", "wasmer-jit", "wasmer-runtime", "wat", @@ -1488,6 +1495,7 @@ dependencies = [ "wasmer-compiler-cranelift", "wasmer-compiler-llvm", "wasmer-compiler-singlepass", + "wasmer-engine", "wasmer-jit", "wasmer-wasi", "wasmer-wasi-experimental-io-devices", @@ -1574,6 +1582,27 @@ dependencies = [ "wasmer-runtime", ] +[[package]] +name = "wasmer-engine" +version = "0.16.2" +dependencies = [ + "backtrace", + "bincode", + "downcast-rs", + "lazy_static", + "more-asserts", + "region", + "rustc-demangle", + "serde", + "serde_bytes", + "target-lexicon", + "thiserror", + "wasm-common", + "wasmer-compiler", + "wasmer-runtime", + "winapi", +] + [[package]] name = "wasmer-jit" version = "0.16.2" @@ -1590,6 +1619,7 @@ dependencies = [ "thiserror", "wasm-common", "wasmer-compiler", + "wasmer-engine", "wasmer-runtime", "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 3646e5221..34d475d0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ wasmer-compiler = { path = "lib/compiler" } wasmer-compiler-cranelift = { path = "lib/compiler-cranelift", optional = true } wasmer-compiler-singlepass = { path = "lib/compiler-singlepass", optional = true } wasmer-compiler-llvm = { path = "lib/compiler-llvm", optional = true } +wasmer-engine = { path = "lib/engine" } wasmer-jit = { path = "lib/jit" } wasmer-wasi = { path = "lib/wasi", optional = true } wasmer-wasi-experimental-io-devices = { path = "lib/wasi-experimental-io-devices", optional = true } diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index cb5435081..74abb180c 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -14,6 +14,7 @@ wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "0.16. wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "0.16.2", optional = true } wasmer-compiler-llvm = { path = "../compiler-llvm", version = "0.16.2", optional = true } wasmer-compiler = { path = "../compiler", version = "0.16.2" } +wasmer-engine = { path = "../engine", version = "0.16.2" } wasmer-jit = { path = "../jit", version = "0.16.2" } wasm-common = { path = "../wasm-common", version = "0.16.2" } indexmap = { version = "1.3.2", features = ["serde-1"] } diff --git a/lib/api/src/import_object.rs b/lib/api/src/import_object.rs index 1c86af791..b5000c513 100644 --- a/lib/api/src/import_object.rs +++ b/lib/api/src/import_object.rs @@ -8,7 +8,7 @@ use std::{ ffi::c_void, sync::{Arc, Mutex}, }; -use wasmer_jit::Resolver; +use wasmer_engine::Resolver; use wasmer_runtime::Export; /// The `LikeNamespace` trait represents objects that act as a namespace for imports. diff --git a/lib/api/src/instance.rs b/lib/api/src/instance.rs index 64d382229..71f14dbef 100644 --- a/lib/api/src/instance.rs +++ b/lib/api/src/instance.rs @@ -3,7 +3,7 @@ use crate::externals::Extern; use crate::module::Module; use crate::store::Store; use crate::InstantiationError; -use wasmer_jit::Resolver; +use wasmer_engine::Resolver; use wasmer_runtime::InstanceHandle; /// A WebAssembly Instance is a stateful, executable diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index 048e8913c..426251019 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -28,7 +28,7 @@ pub use crate::types::{ pub use wasm_common::{ValueType, WasmExternType, WasmTypeList}; pub use wasmer_compiler::{CompilerConfig, Features, Target}; -pub use wasmer_jit::{ +pub use wasmer_engine::{ DeserializeError, InstantiationError, LinkError, RuntimeError, SerializeError, }; diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index 402e06472..5bb23d6f6 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -6,7 +6,7 @@ use std::path::Path; use std::sync::Arc; use thiserror::Error; use wasmer_compiler::{CompileError, WasmError}; -use wasmer_jit::{CompiledModule, DeserializeError, Resolver, SerializeError}; +use wasmer_engine::{CompiledModule, DeserializeError, Resolver, SerializeError}; use wasmer_runtime::InstanceHandle; #[derive(Error, Debug)] @@ -30,7 +30,7 @@ pub enum IoCompileError { #[derive(Clone)] pub struct Module { store: Store, - compiled: Arc, + compiled: Arc, } impl Module { @@ -173,10 +173,11 @@ impl Module { Ok(Self::from_compiled_module(store, compiled)) } - fn from_compiled_module(store: &Store, compiled: CompiledModule) -> Self { + fn from_compiled_module(store: &Store, compiled: Arc) -> Self + { Module { store: store.clone(), - compiled: Arc::new(compiled), + compiled, } } diff --git a/lib/api/src/tunables.rs b/lib/api/src/tunables.rs index 1e73824ec..3db5513dd 100644 --- a/lib/api/src/tunables.rs +++ b/lib/api/src/tunables.rs @@ -4,6 +4,7 @@ use target_lexicon::{OperatingSystem, PointerWidth, Triple, HOST}; use wasm_common::{MemoryType, Pages, TableType}; use wasmer_runtime::{LinearMemory, Table}; use wasmer_runtime::{MemoryPlan, MemoryStyle, TablePlan, TableStyle}; +use wasmer_engine::Tunables as BaseTunables; /// Tunable parameters for WebAssembly compilation. #[derive(Clone)] @@ -57,7 +58,7 @@ impl Tunables { } } -impl wasmer_jit::Tunables for Tunables { +impl BaseTunables for Tunables { /// Get a `MemoryPlan` for the provided `MemoryType` fn memory_plan(&self, memory: MemoryType) -> MemoryPlan { // A heap with a maximum that doesn't exceed the static memory bound specified by the diff --git a/lib/engine/Cargo.toml b/lib/engine/Cargo.toml new file mode 100644 index 000000000..43d9bc592 --- /dev/null +++ b/lib/engine/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "wasmer-engine" +version = "0.16.2" +authors = ["Wasmer Engineering Team "] +description = "Wasmer Engine abstraction" +license = "(Apache-2.0 WITH LLVM-exception) or MIT" +categories = ["wasm"] +keywords = ["webassembly", "wasm"] +repository = "https://github.com/wasmerio/wasmer" +readme = "README.md" +edition = "2018" + +[dependencies] +wasm-common = { path = "../wasm-common", version = "0.16.2" } +wasmer-compiler = { path = "../compiler", version = "0.16.2", default-features = false } +wasmer-runtime = { path = "../runtime", version = "0.16.2" } +target-lexicon = { version = "0.10.0", default-features = false } +# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } +backtrace = "0.3.46" +rustc-demangle = "0.1.16" +more-asserts = "0.2.1" +thiserror = "1.0.16" +region = "2.1.2" +serde = { version = "1.0.106", sfeatures = ["derive", "rc"] } +serde_bytes = { version = "0.11.3" } +bincode = "1.2.1" +lazy_static = "1.4" +downcast-rs = "1.1.1" + +[target.'cfg(target_os = "windows")'.dependencies] +winapi = { version = "0.3.8", features = ["winnt", "impl-default"] } + +[badges] +maintenance = { status = "actively-developed" } diff --git a/lib/engine/README.md b/lib/engine/README.md new file mode 100644 index 000000000..f45e09291 --- /dev/null +++ b/lib/engine/README.md @@ -0,0 +1,12 @@ +# Wasmer Engine + +The Wasmer Engine is the general abstraction for Engines in Wasmer. +It currently has two implementations: +* Wasmer JIT +* Wasmer Native + +### Acknowledgments + +This project borrowed some of the code of the trap implementation from the [wasmtime-api](https://crates.io/crates/wasmtime), the code since then has evolved significantly. + +Please check [Wasmer ATTRIBUTIONS](https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md) to further see licenses and other attributions of the project. diff --git a/lib/engine/src/engine.rs b/lib/engine/src/engine.rs new file mode 100644 index 000000000..299fc687a --- /dev/null +++ b/lib/engine/src/engine.rs @@ -0,0 +1,49 @@ +//! JIT compilation. + +use crate::error::InstantiationError; +use crate::resolver::Resolver; +use crate::tunables::Tunables; +use crate::{CompiledModule, DeserializeError, SerializeError}; +use std::sync::Arc; +use wasm_common::FuncType; +use wasmer_compiler::CompileError; +use wasmer_runtime::{InstanceHandle, VMSharedSignatureIndex, VMTrampoline}; + +/// A unimplemented Wasmer `Engine`. +/// This trait is used by implementors to implement custom engines, +/// such as: JIT or Native. +pub trait Engine { + /// The `CompiledModule` type + type Product: CompiledModule; + + /// Get the tunables + fn tunables(&self) -> &Tunables; + + /// Register a signature + fn register_signature(&self, func_type: &FuncType) -> VMSharedSignatureIndex; + + /// Lookup a signature + fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option; + + /// Retrieves a trampoline given a signature + fn trampoline(&self, sig: VMSharedSignatureIndex) -> Option; + + /// Validates a WebAssembly module + fn validate(&self, binary: &[u8]) -> Result<(), CompileError>; + + /// Compile a WebAssembly binary + fn compile(&self, binary: &[u8]) -> Result; + + /// Instantiates a WebAssembly module + fn instantiate( + &self, + compiled_module: &Arc, + resolver: &dyn Resolver, + ) -> Result; + + /// Serializes a WebAssembly module + fn serialize(&self, compiled_module: &Arc) -> Result, SerializeError>; + + /// Deserializes a WebAssembly module + fn deserialize(&self, bytes: &[u8]) -> Result; +} diff --git a/lib/jit/src/error.rs b/lib/engine/src/error.rs similarity index 98% rename from lib/jit/src/error.rs rename to lib/engine/src/error.rs index cb6e14013..79ff95cf6 100644 --- a/lib/jit/src/error.rs +++ b/lib/engine/src/error.rs @@ -1,4 +1,3 @@ -// TODO: Move this errors into a common engine crate. //! The WebAssembly possible errors use crate::trap::RuntimeError; use thiserror::Error; diff --git a/lib/engine/src/lib.rs b/lib/engine/src/lib.rs new file mode 100644 index 000000000..0f02366f3 --- /dev/null +++ b/lib/engine/src/lib.rs @@ -0,0 +1,45 @@ +//! Generic Engine abstraction for Wasmer Engines. + +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr( + feature = "cargo-clippy", + allow(clippy::new_without_default, clippy::new_without_default) +)] +#![cfg_attr( + feature = "cargo-clippy", + warn( + clippy::float_arithmetic, + clippy::mut_mut, + clippy::nonminimal_bool, + clippy::option_map_unwrap_or, + clippy::option_map_unwrap_or_else, + clippy::print_stdout, + clippy::unicode_not_nfc, + clippy::use_self + ) +)] + +mod engine; +mod error; +mod module; +mod resolver; +mod serialize; +mod trap; +mod tunables; + +pub use crate::engine::Engine; +pub use crate::error::{ + DeserializeError, ImportError, InstantiationError, LinkError, SerializeError, +}; +pub use crate::module::CompiledModule; +pub use crate::resolver::{resolve_imports, NullResolver, Resolver}; +pub use crate::trap::*; +pub use crate::tunables::Tunables; +pub use crate::serialize::SerializableFunctionFrameInfo; + +pub use wasmer_compiler::CompilerConfig; + +/// Version number of this crate. +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/lib/engine/src/module.rs b/lib/engine/src/module.rs new file mode 100644 index 000000000..42c0bfd29 --- /dev/null +++ b/lib/engine/src/module.rs @@ -0,0 +1,19 @@ +use std::sync::Arc; +use wasmer_runtime::Module; + +use downcast_rs::{DowncastSync, impl_downcast}; + +/// The `CompiledModule` trait is used by engine implementors, such +/// as a JIT or Native execution. +pub trait CompiledModule: DowncastSync { + /// Return a reference-counting pointer to a module. + fn module(&self) -> &Arc; + + /// Return a reference-counting pointer to a module. + fn module_mut(&mut self) -> &mut Arc; + + /// Return a reference to a module. + fn module_ref(&self) -> &Module; +} + +impl_downcast!(sync CompiledModule); // `sync` => also produce `Arc` downcasts. diff --git a/lib/jit/src/resolver.rs b/lib/engine/src/resolver.rs similarity index 100% rename from lib/jit/src/resolver.rs rename to lib/engine/src/resolver.rs diff --git a/lib/engine/src/serialize.rs b/lib/engine/src/serialize.rs new file mode 100644 index 000000000..42964a24e --- /dev/null +++ b/lib/engine/src/serialize.rs @@ -0,0 +1,107 @@ +use serde::de::{Deserializer, Visitor}; +use serde::ser::Serializer; +use serde::{Deserialize, Serialize}; +use std::fmt; +use wasmer_compiler::CompiledFunctionFrameInfo; + +/// This is the unserialized verison of `CompiledFunctionFrameInfo`. +#[derive(Clone, Serialize, Deserialize)] +#[serde(transparent)] +#[repr(transparent)] +pub struct UnprocessedFunctionFrameInfo { + #[serde(with = "serde_bytes")] + bytes: Vec, +} + +impl UnprocessedFunctionFrameInfo { + /// Converts the `UnprocessedFunctionFrameInfo` to a `CompiledFunctionFrameInfo` + pub fn deserialize(&self) -> CompiledFunctionFrameInfo { + // let r = flexbuffers::Reader::get_root(&self.bytes).expect("Can't deserialize the info"); + // CompiledFunctionFrameInfo::deserialize(r).expect("Can't deserialize the info") + bincode::deserialize(&self.bytes).expect("Can't deserialize the info") + } + + /// Converts the `CompiledFunctionFrameInfo` to a `UnprocessedFunctionFrameInfo` + pub fn serialize(processed: &CompiledFunctionFrameInfo) -> Self { + // let mut s = flexbuffers::FlexbufferSerializer::new(); + // processed + // .serialize(&mut s) + // .expect("Can't serialize the info"); + // let bytes = s.take_buffer(); + let bytes = bincode::serialize(&processed).expect("Can't serialize the info"); + Self { bytes } + } +} + +/// We hold the frame info in two states, mainly because we want to +/// process it lazily to speed up execution. +/// +/// When a Trap occurs, we process the frame info lazily for each +/// function in the frame. That way we minimize as much as we can +/// the upfront effort. +/// +/// The data can also be processed upfront. This will happen in the case +/// of compiling at the same time that emiting the JIT. +/// In that case, we don't need to deserialize/process anything +/// as the data is already in memory. +#[derive(Clone)] +pub enum SerializableFunctionFrameInfo { + /// The unprocessed frame info (binary) + Unprocessed(UnprocessedFunctionFrameInfo), + /// The processed frame info (memory struct) + Processed(CompiledFunctionFrameInfo), +} + +impl SerializableFunctionFrameInfo { + /// Returns true if the extra function info is not yet + /// processed + pub fn is_unprocessed(&self) -> bool { + match self { + Self::Unprocessed(_) => true, + _ => false, + } + } +} + +// Below: +// The custom ser/de for `SerializableFunctionFrameInfo`. + +impl Serialize for SerializableFunctionFrameInfo { + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + let unprocessed = match self { + Self::Processed(processed) => UnprocessedFunctionFrameInfo::serialize(processed), + Self::Unprocessed(unprocessed) => unprocessed.clone(), + }; + s.serialize_bytes(&unprocessed.bytes) + } +} + +struct FunctionFrameInfoVisitor; + +impl<'de> Visitor<'de> for FunctionFrameInfoVisitor { + type Value = UnprocessedFunctionFrameInfo; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("bytes") + } + fn visit_byte_buf(self, v: Vec) -> Result { + Ok(UnprocessedFunctionFrameInfo { bytes: v }) + } + fn visit_bytes(self, v: &[u8]) -> Result { + Ok(UnprocessedFunctionFrameInfo { bytes: v.to_vec() }) + } +} + +impl<'de> Deserialize<'de> for SerializableFunctionFrameInfo { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(SerializableFunctionFrameInfo::Unprocessed( + deserializer.deserialize_byte_buf(FunctionFrameInfoVisitor)?, + )) + } +} diff --git a/lib/jit/src/trap/error.rs b/lib/engine/src/trap/error.rs similarity index 100% rename from lib/jit/src/trap/error.rs rename to lib/engine/src/trap/error.rs diff --git a/lib/jit/src/trap/frame_info.rs b/lib/engine/src/trap/frame_info.rs similarity index 100% rename from lib/jit/src/trap/frame_info.rs rename to lib/engine/src/trap/frame_info.rs diff --git a/lib/engine/src/trap/mod.rs b/lib/engine/src/trap/mod.rs new file mode 100644 index 000000000..0aa0e0153 --- /dev/null +++ b/lib/engine/src/trap/mod.rs @@ -0,0 +1,4 @@ +mod error; +mod frame_info; +pub use error::RuntimeError; +pub use frame_info::{register as register_frame_info, FrameInfo, GlobalFrameInfoRegistration, FRAME_INFO}; diff --git a/lib/jit/src/tunables.rs b/lib/engine/src/tunables.rs similarity index 100% rename from lib/jit/src/tunables.rs rename to lib/engine/src/tunables.rs diff --git a/lib/jit/Cargo.toml b/lib/jit/Cargo.toml index 660bf6c63..7123401d1 100644 --- a/lib/jit/Cargo.toml +++ b/lib/jit/Cargo.toml @@ -14,6 +14,7 @@ edition = "2018" wasm-common = { path = "../wasm-common", version = "0.16.2" } wasmer-compiler = { path = "../compiler", version = "0.16.2", default-features = false } wasmer-runtime = { path = "../runtime", version = "0.16.2" } +wasmer-engine = { path = "../engine", version = "0.16.2" } target-lexicon = { version = "0.10.0", default-features = false } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } backtrace = "0.3.46" diff --git a/lib/jit/src/engine.rs b/lib/jit/src/engine.rs index 9d5513b60..e0901a629 100644 --- a/lib/jit/src/engine.rs +++ b/lib/jit/src/engine.rs @@ -1,10 +1,7 @@ //! JIT compilation. -use crate::error::InstantiationError; -use crate::resolver::Resolver; -use crate::tunables::Tunables; -use crate::CodeMemory; -use crate::{CompiledModule, DeserializeError, SerializeError}; +use wasmer_engine::{Engine, InstantiationError, Resolver, Tunables, DeserializeError, SerializeError, CompiledModule as BaseCompiledModule}; +use crate::{CodeMemory, CompiledModule}; use std::cell::RefCell; use std::collections::HashMap; use std::sync::Arc; @@ -12,7 +9,7 @@ use wasm_common::entity::PrimaryMap; use wasm_common::{FuncType, LocalFuncIndex, MemoryIndex, TableIndex}; use wasmer_compiler::{ Compilation, CompileError, Compiler as BaseCompiler, CompilerConfig, FunctionBody, - FunctionBodyData, ModuleTranslationState, Target, + FunctionBodyData, ModuleTranslationState, }; use wasmer_runtime::{ InstanceHandle, MemoryPlan, Module, SignatureRegistry, TablePlan, VMFunctionBody, @@ -44,11 +41,6 @@ impl JITEngine { } } - /// Get the tunables - pub fn tunables(&self) -> &dyn Tunables { - &**self.tunables - } - pub(crate) fn compiler(&self) -> std::cell::Ref<'_, JITEngineInner> { self.inner.borrow() } @@ -57,6 +49,13 @@ impl JITEngine { self.inner.borrow_mut() } + + /// Get the tunables + pub fn tunables(&self) -> &dyn Tunables { + &**self.tunables + } +// } +// impl Engine for JITEngine { /// Register a signature pub fn register_signature(&self, func_type: &FuncType) -> VMSharedSignatureIndex { let compiler = self.compiler(); @@ -80,27 +79,30 @@ impl JITEngine { } /// Compile a WebAssembly binary - pub fn compile(&self, binary: &[u8]) -> Result { - CompiledModule::new(&self, binary) + pub fn compile(&self, binary: &[u8]) -> Result, CompileError> { + Ok(Arc::new(CompiledModule::new(&self, binary)?)) } /// Instantiates a WebAssembly module pub fn instantiate( &self, - compiled_module: &CompiledModule, + compiled_module: &Arc, resolver: &dyn Resolver, - ) -> Result { + ) -> Result + { + let compiled_module = compiled_module.downcast_ref::().unwrap(); unsafe { compiled_module.instantiate(&self, resolver, Box::new(())) } } /// Serializes a WebAssembly module - pub fn serialize(&self, compiled_module: &CompiledModule) -> Result, SerializeError> { + pub fn serialize(&self, compiled_module: &Arc) -> Result, SerializeError> { + let compiled_module = compiled_module.downcast_ref::().unwrap(); compiled_module.serialize() } /// Deserializes a WebAssembly module - pub fn deserialize(&self, bytes: &[u8]) -> Result { - CompiledModule::deserialize(&self, bytes) + pub fn deserialize(&self, bytes: &[u8]) -> Result, DeserializeError> { + Ok(Arc::new(CompiledModule::deserialize(&self, bytes)?)) } } diff --git a/lib/jit/src/lib.rs b/lib/jit/src/lib.rs index c1bcc8114..0d0a026ec 100644 --- a/lib/jit/src/lib.rs +++ b/lib/jit/src/lib.rs @@ -27,28 +27,16 @@ mod code_memory; mod engine; -mod error; mod function_table; mod link; mod module; -mod resolver; mod serialize; -mod trap; -mod tunables; pub use crate::code_memory::CodeMemory; pub use crate::engine::JITEngine; -pub use crate::error::{ - DeserializeError, ImportError, InstantiationError, LinkError, SerializeError, -}; pub use crate::function_table::FunctionTable; pub use crate::link::link_module; pub use crate::module::CompiledModule; -pub use crate::resolver::{resolve_imports, NullResolver, Resolver}; -pub use crate::trap::*; -pub use crate::tunables::Tunables; - -pub use wasmer_compiler::CompilerConfig; /// Version number of this crate. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/lib/jit/src/link.rs b/lib/jit/src/link.rs index 12430189e..78f75e08d 100644 --- a/lib/jit/src/link.rs +++ b/lib/jit/src/link.rs @@ -7,9 +7,8 @@ use wasmer_compiler::{JumpTable, JumpTableOffsets, RelocationKind, RelocationTar use wasmer_runtime::Module; use wasmer_runtime::VMFunctionBody; -/// Links a module that has been compiled with `compiled_module` in `wasmer-compiler::Compiler`. -/// -/// Performs all required relocations inside the function code, provided the necessary metadata. +/// Links a module, patching the allocated functions with the +/// requiredd relocations and jump tables. pub fn link_module( module: &Module, allocated_functions: &PrimaryMap, @@ -68,10 +67,8 @@ pub fn link_module( .wrapping_add(reloc_addend as u32); write_unaligned(reloc_address as *mut u32, reloc_delta_u32); } - RelocationKind::X86PCRelRodata4 => { - // ignore - } - _ => panic!("unsupported reloc kind"), + RelocationKind::X86PCRelRodata4 => {} + _ => panic!("Relocation kind unsupported"), } } } diff --git a/lib/jit/src/module.rs b/lib/jit/src/module.rs index 655980303..2a7b76681 100644 --- a/lib/jit/src/module.rs +++ b/lib/jit/src/module.rs @@ -4,16 +4,14 @@ //! steps. use crate::engine::{JITEngine, JITEngineInner}; -use crate::error::{DeserializeError, SerializeError}; -use crate::error::{InstantiationError, LinkError}; -use crate::link::link_module; -use crate::resolver::{resolve_imports, Resolver}; -use crate::serialize::{ - SerializableCompilation, SerializableFunctionFrameInfo, SerializableModule, +use wasmer_engine::{DeserializeError, SerializeError, InstantiationError, LinkError, SerializableFunctionFrameInfo, + resolve_imports, Resolver, register_frame_info, GlobalFrameInfoRegistration, RuntimeError, + CompiledModule as BaseCompiledModule +}; +use crate::link::link_module; +use crate::serialize::{ + SerializableCompilation, SerializableModule, }; -use crate::trap::register as register_frame_info; -use crate::trap::GlobalFrameInfoRegistration; -use crate::trap::RuntimeError; use serde::{Deserialize, Serialize}; use std::any::Any; use std::sync::{Arc, Mutex}; @@ -168,15 +166,7 @@ impl CompiledModule { &self.serializable.table_plans } - /// Crate an `Instance` from this `CompiledModule`. - /// - /// Note that if only one instance of this module is needed, it may be more - /// efficient to call the top-level `instantiate`, since that avoids copying - /// the data initializers. - /// - /// # Unsafety - /// - /// See `InstanceHandle::new` + /// Instantiate the module pub unsafe fn instantiate( &self, jit: &JITEngine, @@ -227,21 +217,6 @@ impl CompiledModule { .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap))) } - /// Return a reference-counting pointer to a module. - pub fn module(&self) -> &Arc { - &self.serializable.module - } - - /// Return a reference-counting pointer to a module. - pub fn module_mut(&mut self) -> &mut Arc { - &mut self.serializable.module - } - - /// Return a reference to a module. - pub fn module_ref(&self) -> &Module { - &self.serializable.module - } - /// Register this module's stack frame information into the global scope. /// /// This is required to ensure that any traps can be properly symbolicated. @@ -259,6 +234,22 @@ impl CompiledModule { )); } } +unsafe impl Sync for CompiledModule {} +unsafe impl Send for CompiledModule {} + +impl BaseCompiledModule for CompiledModule { + fn module(&self) -> &Arc { + &self.serializable.module + } + + fn module_mut(&mut self) -> &mut Arc { + &mut self.serializable.module + } + + fn module_ref(&self) -> &Module { + &self.serializable.module + } +} /// Allocate memory for just the memories of the current module. fn create_memories( diff --git a/lib/jit/src/serialize.rs b/lib/jit/src/serialize.rs index 835775c47..7f5eb3db3 100644 --- a/lib/jit/src/serialize.rs +++ b/lib/jit/src/serialize.rs @@ -1,11 +1,8 @@ -use serde::de::{Deserializer, Visitor}; -use serde::ser::Serializer; use serde::{Deserialize, Serialize}; -use std::fmt; use std::sync::Arc; -use wasmer_compiler::{CompiledFunctionFrameInfo, FunctionBody, JumpTableOffsets, Relocation}; +use wasmer_compiler::{FunctionBody, JumpTableOffsets, Relocation}; use wasmer_runtime::Module; - +use wasmer_engine::SerializableFunctionFrameInfo; use wasm_common::entity::PrimaryMap; use wasm_common::{LocalFuncIndex, MemoryIndex, OwnedDataInitializer, TableIndex}; use wasmer_runtime::{MemoryPlan, TablePlan}; @@ -33,105 +30,3 @@ pub struct SerializableModule { pub memory_plans: PrimaryMap, pub table_plans: PrimaryMap, } - -/// This is the unserialized verison of `CompiledFunctionFrameInfo`. -#[derive(Clone, Serialize, Deserialize)] -#[serde(transparent)] -#[repr(transparent)] -pub struct UnprocessedFunctionFrameInfo { - #[serde(with = "serde_bytes")] - bytes: Vec, -} - -impl UnprocessedFunctionFrameInfo { - /// Converts the `UnprocessedFunctionFrameInfo` to a `CompiledFunctionFrameInfo` - pub fn deserialize(&self) -> CompiledFunctionFrameInfo { - // let r = flexbuffers::Reader::get_root(&self.bytes).expect("Can't deserialize the info"); - // CompiledFunctionFrameInfo::deserialize(r).expect("Can't deserialize the info") - bincode::deserialize(&self.bytes).expect("Can't deserialize the info") - } - - /// Converts the `CompiledFunctionFrameInfo` to a `UnprocessedFunctionFrameInfo` - pub fn serialize(processed: &CompiledFunctionFrameInfo) -> Self { - // let mut s = flexbuffers::FlexbufferSerializer::new(); - // processed - // .serialize(&mut s) - // .expect("Can't serialize the info"); - // let bytes = s.take_buffer(); - let bytes = bincode::serialize(&processed).expect("Can't serialize the info"); - Self { bytes } - } -} - -/// We hold the frame info in two states, mainly because we want to -/// process it lazily to speed up execution. -/// -/// When a Trap occurs, we process the frame info lazily for each -/// function in the frame. That way we minimize as much as we can -/// the upfront effort. -/// -/// The data can also be processed upfront. This will happen in the case -/// of compiling at the same time that emiting the JIT. -/// In that case, we don't need to deserialize/process anything -/// as the data is already in memory. -#[derive(Clone)] -pub enum SerializableFunctionFrameInfo { - /// The unprocessed frame info (binary) - Unprocessed(UnprocessedFunctionFrameInfo), - /// The processed frame info (memory struct) - Processed(CompiledFunctionFrameInfo), -} - -impl SerializableFunctionFrameInfo { - /// Returns true if the extra function info is not yet - /// processed - pub fn is_unprocessed(&self) -> bool { - match self { - Self::Unprocessed(_) => true, - _ => false, - } - } -} - -// Below: -// The custom ser/de for `SerializableFunctionFrameInfo`. - -impl Serialize for SerializableFunctionFrameInfo { - fn serialize(&self, s: S) -> Result - where - S: Serializer, - { - let unprocessed = match self { - Self::Processed(processed) => UnprocessedFunctionFrameInfo::serialize(processed), - Self::Unprocessed(unprocessed) => unprocessed.clone(), - }; - s.serialize_bytes(&unprocessed.bytes) - } -} - -struct FunctionFrameInfoVisitor; - -impl<'de> Visitor<'de> for FunctionFrameInfoVisitor { - type Value = UnprocessedFunctionFrameInfo; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("bytes") - } - fn visit_byte_buf(self, v: Vec) -> Result { - Ok(UnprocessedFunctionFrameInfo { bytes: v }) - } - fn visit_bytes(self, v: &[u8]) -> Result { - Ok(UnprocessedFunctionFrameInfo { bytes: v.to_vec() }) - } -} - -impl<'de> Deserialize<'de> for SerializableFunctionFrameInfo { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(SerializableFunctionFrameInfo::Unprocessed( - deserializer.deserialize_byte_buf(FunctionFrameInfoVisitor)?, - )) - } -} diff --git a/lib/jit/src/trap/mod.rs b/lib/jit/src/trap/mod.rs deleted file mode 100644 index 1a37b64af..000000000 --- a/lib/jit/src/trap/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod error; -mod frame_info; -pub use error::RuntimeError; -pub use frame_info::{register, FrameInfo, GlobalFrameInfoRegistration, FRAME_INFO};