From d7154fe791645410c4419a85d41e32d736e025ee Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 20 Dec 2019 20:11:56 -0800 Subject: [PATCH] Remove Backend dependency --- Cargo.lock | 2 + lib/clif-backend/src/code.rs | 6 +-- lib/llvm-backend/src/code.rs | 4 +- lib/middleware-common-tests/src/lib.rs | 21 +++++---- lib/runtime-core/src/cache.rs | 25 ++--------- lib/runtime-core/src/codegen.rs | 9 ++-- lib/runtime-core/src/module.rs | 4 +- lib/runtime-core/src/parse.rs | 5 +-- lib/runtime-core/src/state.rs | 4 +- lib/runtime-core/src/tiering.rs | 12 ++--- lib/runtime-core/src/vm.rs | 4 +- lib/runtime/Cargo.toml | 8 ++++ lib/runtime/src/cache.rs | 25 +++++++++-- lib/runtime/src/lib.rs | 54 +++++++++++++++++++++-- lib/singlepass-backend/src/codegen_x64.rs | 8 +++- 15 files changed, 127 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f5d6d7c8..27ee3e30d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1752,6 +1752,8 @@ dependencies = [ "criterion", "lazy_static", "memmap", + "serde", + "serde_derive", "tempfile", "wabt", "wasmer-clif-backend", diff --git a/lib/clif-backend/src/code.rs b/lib/clif-backend/src/code.rs index 1811afb24..390dbfecb 100644 --- a/lib/clif-backend/src/code.rs +++ b/lib/clif-backend/src/code.rs @@ -18,7 +18,7 @@ use std::mem; use std::sync::{Arc, RwLock}; use wasmer_runtime_core::error::CompileError; use wasmer_runtime_core::{ - backend::{Backend, CacheGen, Token}, + backend::{CacheGen, Token}, cache::{Artifact, Error as CacheError}, codegen::*, memory::MemoryType, @@ -58,8 +58,8 @@ impl ModuleCodeGenerator unimplemented!("cross compilation is not available for clif backend") } - fn backend_id() -> Backend { - Backend::Cranelift + fn backend_id() -> String { + "cranelift".to_string() } fn check_precondition(&mut self, _module_info: &ModuleInfo) -> Result<(), CodegenError> { diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index d8761e44a..871d5d48f 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -8721,8 +8721,8 @@ impl<'ctx> ModuleCodeGenerator, LLVMBackend, Cod } } - fn backend_id() -> Backend { - Backend::LLVM + fn backend_id() -> String { + "llvm".to_string() } fn check_precondition(&mut self, _module_info: &ModuleInfo) -> Result<(), CodegenError> { diff --git a/lib/middleware-common-tests/src/lib.rs b/lib/middleware-common-tests/src/lib.rs index e3c0596d1..55ce39a91 100644 --- a/lib/middleware-common-tests/src/lib.rs +++ b/lib/middleware-common-tests/src/lib.rs @@ -8,40 +8,40 @@ mod tests { use wasmer_runtime_core::fault::{pop_code_version, push_code_version}; use wasmer_runtime_core::state::CodeVersion; use wasmer_runtime_core::{ - backend::{Backend, Compiler}, + backend::Compiler, compile_with, imports, Func, }; #[cfg(feature = "llvm")] - fn get_compiler(limit: u64) -> (impl Compiler, Backend) { + fn get_compiler(limit: u64) -> impl Compiler { use wasmer_llvm_backend::ModuleCodeGenerator as LLVMMCG; let c: StreamingCompiler = StreamingCompiler::new(move || { let mut chain = MiddlewareChain::new(); chain.push(Metering::new(limit)); chain }); - (c, Backend::LLVM) + c } #[cfg(feature = "singlepass")] - fn get_compiler(limit: u64) -> (impl Compiler, Backend) { + fn get_compiler(limit: u64) -> impl Compiler { use wasmer_singlepass_backend::ModuleCodeGenerator as SinglePassMCG; let c: StreamingCompiler = StreamingCompiler::new(move || { let mut chain = MiddlewareChain::new(); chain.push(Metering::new(limit)); chain }); - (c, Backend::Singlepass) + c } #[cfg(not(any(feature = "llvm", feature = "clif", feature = "singlepass")))] compile_error!("compiler not specified, activate a compiler via features"); #[cfg(feature = "clif")] - fn get_compiler(_limit: u64) -> (impl Compiler, Backend) { + fn get_compiler(_limit: u64) -> impl Compiler { compile_error!("cranelift does not implement metering"); use wasmer_clif_backend::CraneliftCompiler; - (CraneliftCompiler::new(), Backend::Cranelift) + CraneliftCompiler::new() } // Assemblyscript @@ -161,7 +161,12 @@ mod tests { let add_to: Func<(i32, i32), i32> = instance.func("add_to").unwrap(); - let cv_pushed = if let Some(msm) = instance.module.runnable_module.get_module_state_map() { + let cv_pushed = if let Some(msm) = instance + .module + .runnable_module + .borrow() + .get_module_state_map() + { push_code_version(CodeVersion { baseline: true, msm: msm, diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index e924cd9f5..376a4ba60 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -3,12 +3,11 @@ //! and loaded to allow skipping compilation and fast startup. use crate::{ - backend::Backend, - module::{Module, ModuleInfo}, + module::ModuleInfo, sys::Memory, }; use blake2b_simd::blake2bp; -use std::{fmt, io, mem, slice}; +use std::{io, mem, slice}; /// Indicates the invalid type of invalid cache file #[derive(Debug)] @@ -35,7 +34,7 @@ pub enum Error { /// The cached binary has been invalidated. InvalidatedCache, /// The current backend does not support caching. - UnsupportedBackend(Backend), + UnsupportedBackend(String), } impl From for Error { @@ -246,24 +245,6 @@ impl Artifact { } } -/// A generic cache for storing and loading compiled wasm modules. -/// -/// The `wasmer-runtime` supplies a naive `FileSystemCache` api. -pub trait Cache { - /// Error type to return when load error occurs - type LoadError: fmt::Debug; - /// Error type to return when store error occurs - type StoreError: fmt::Debug; - - /// loads a module using the default `Backend` - fn load(&self, key: WasmHash) -> Result; - /// loads a cached module using a specific `Backend` - fn load_with_backend(&self, key: WasmHash, backend: Backend) - -> Result; - /// Store a module into the cache with the given key - fn store(&mut self, key: WasmHash, module: Module) -> Result<(), Self::StoreError>; -} - /// A unique ID generated from the version of Wasmer for use with cache versioning pub const WASMER_VERSION_HASH: &'static str = include_str!(concat!(env!("OUT_DIR"), "/wasmer_version_hash.txt")); diff --git a/lib/runtime-core/src/codegen.rs b/lib/runtime-core/src/codegen.rs index e7c65b29c..e6f7558e1 100644 --- a/lib/runtime-core/src/codegen.rs +++ b/lib/runtime-core/src/codegen.rs @@ -92,10 +92,10 @@ pub trait ModuleCodeGenerator, RM: RunnableModule, ) -> Self; /// Returns the backend id associated with this MCG. - fn backend_id() -> Backend; + fn backend_id() -> String; /// It sets if the current compiler requires validation before compilation - fn requires_pre_validation(&self) -> bool { + fn requires_pre_validation() -> bool { true } @@ -231,8 +231,8 @@ impl< validate_with_features(wasm, &compiler_config.features)?; } - let mut mcg = match MCG::backend_id() { - Backend::LLVM => MCG::new_with_target( + let mut mcg = match MCG::backend_id().as_ref() { + "llvm" => MCG::new_with_target( compiler_config.triple.clone(), compiler_config.cpu_name.clone(), compiler_config.cpu_features.clone(), @@ -242,7 +242,6 @@ impl< let mut chain = (self.middleware_chain_generator)(); let info = crate::parse::read_module( wasm, - MCG::backend_id(), &mut mcg, &mut chain, &compiler_config, diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 9b991edcc..cf99abc27 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,7 +1,7 @@ //! The module module contains the implementation data structures and helper functions used to //! manipulate and access wasm modules. use crate::{ - backend::{Backend, RunnableModule}, + backend::RunnableModule, cache::{Artifact, Error as CacheError}, error, import::ImportObject, @@ -65,7 +65,7 @@ pub struct ModuleInfo { /// Map signature index to function signature. pub signatures: Map, /// Backend. - pub backend: Backend, + pub backend: String, /// Table of namespace indexes. pub namespace_table: StringTable, diff --git a/lib/runtime-core/src/parse.rs b/lib/runtime-core/src/parse.rs index d41efedcb..5a050f5c1 100644 --- a/lib/runtime-core/src/parse.rs +++ b/lib/runtime-core/src/parse.rs @@ -3,7 +3,7 @@ use crate::codegen::*; use crate::{ - backend::{Backend, CompilerConfig, RunnableModule}, + backend::{CompilerConfig, RunnableModule}, error::CompileError, module::{ DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder, @@ -57,7 +57,6 @@ pub fn read_module< E: Debug, >( wasm: &[u8], - backend: Backend, mcg: &mut MCG, middlewares: &mut MiddlewareChain, compiler_config: &CompilerConfig, @@ -83,7 +82,7 @@ pub fn read_module< func_assoc: Map::new(), signatures: Map::new(), - backend: backend, + backend: MCG::backend_id(), namespace_table: StringTable::new(), name_table: StringTable::new(), diff --git a/lib/runtime-core/src/state.rs b/lib/runtime-core/src/state.rs index 06dc92400..870e955a5 100644 --- a/lib/runtime-core/src/state.rs +++ b/lib/runtime-core/src/state.rs @@ -2,7 +2,7 @@ //! state could read or updated at runtime. Use cases include generating stack traces, switching //! generated code from one tier to another, or serializing state of a running instace. -use crate::backend::{Backend, RunnableModule}; +use crate::backend::RunnableModule; use std::collections::BTreeMap; use std::ops::Bound::{Included, Unbounded}; use std::sync::Arc; @@ -186,7 +186,7 @@ pub struct CodeVersion { pub base: usize, /// The backend used to compile this module. - pub backend: Backend, + pub backend: String, /// `RunnableModule` for this code version. pub runnable_module: Arc>, diff --git a/lib/runtime-core/src/tiering.rs b/lib/runtime-core/src/tiering.rs index 697348ae3..15dc1bd19 100644 --- a/lib/runtime-core/src/tiering.rs +++ b/lib/runtime-core/src/tiering.rs @@ -1,6 +1,6 @@ //! The tiering module supports switching between code compiled with different optimization levels //! as runtime. -use crate::backend::{Backend, Compiler, CompilerConfig}; +use crate::backend::{Compiler, CompilerConfig}; use crate::compile_with_config; use crate::fault::{ catch_unsafe_unwind, ensure_sighandler, pop_code_version, push_code_version, with_ctx, @@ -43,7 +43,7 @@ struct OptimizationState { } struct OptimizationOutcome { - backend_id: Backend, + backend_id: String, module: Module, } @@ -54,7 +54,7 @@ unsafe impl Sync for CtxWrapper {} unsafe fn do_optimize( binary: &[u8], - backend_id: Backend, + backend_id: String, compiler: Box, ctx: &Mutex, state: &OptimizationState, @@ -87,8 +87,8 @@ pub unsafe fn run_tiering ShellExitOperation>( import_object: &ImportObject, start_raw: extern "C" fn(&mut Ctx), baseline: &mut Instance, - baseline_backend: Backend, - optimized_backends: Vec<(Backend, Box Box + Send>)>, + baseline_backend: String, + optimized_backends: Vec<(String, Box Box + Send>)>, interactive_shell: F, ) -> Result<(), String> { ensure_sighandler(); @@ -140,7 +140,7 @@ pub unsafe fn run_tiering ShellExitOperation>( })); loop { - let new_optimized: Option<(Backend, &mut Instance)> = { + let new_optimized: Option<(String, &mut Instance)> = { let mut outcome = opt_state.outcome.lock().unwrap(); if let Some(x) = outcome.take() { let instance = x diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index f6f1c39a9..2cbb32d32 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -1064,7 +1064,7 @@ mod vm_ctx_tests { fn generate_module() -> ModuleInner { use super::Func; - use crate::backend::{sys::Memory, Backend, CacheGen, RunnableModule}; + use crate::backend::{sys::Memory, CacheGen, RunnableModule}; use crate::cache::Error as CacheError; use crate::typed_func::Wasm; use crate::types::{LocalFuncIndex, SigIndex}; @@ -1118,7 +1118,7 @@ mod vm_ctx_tests { func_assoc: Map::new(), signatures: Map::new(), - backend: Backend::Cranelift, + backend: "".to_string(), namespace_table: StringTable::new(), name_table: StringTable::new(), diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index f90d57272..e3b135226 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -24,6 +24,14 @@ path = "../clif-backend" version = "0.12.0" optional = true +# Dependencies for caching. +[dependencies.serde] +version = "1.0" +# This feature is required for serde to support serializing/deserializing reference counted pointers (e.g. Rc and Arc). +features = ["rc"] +[dependencies.serde_derive] +version = "1.0" + [dev-dependencies] tempfile = "3.1" criterion = "0.2" diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index 30e08c1a0..dd27d54aa 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -5,6 +5,7 @@ use crate::Module; use memmap::Mmap; use std::{ + fmt, fs::{create_dir_all, File}, io::{self, Write}, path::PathBuf, @@ -12,9 +13,27 @@ use std::{ use wasmer_runtime_core::cache::Error as CacheError; pub use wasmer_runtime_core::{ - backend::Backend, - cache::{Artifact, Cache, WasmHash}, + cache::{Artifact, WasmHash}, }; +pub use super::Backend; + +/// A generic cache for storing and loading compiled wasm modules. +/// +/// The `wasmer-runtime` supplies a naive `FileSystemCache` api. +pub trait Cache { + /// Error type to return when load error occurs + type LoadError: fmt::Debug; + /// Error type to return when store error occurs + type StoreError: fmt::Debug; + + /// loads a module using the default `Backend` + fn load(&self, key: WasmHash) -> Result; + /// loads a cached module using a specific `Backend` + fn load_with_backend(&self, key: WasmHash, backend: Backend) + -> Result; + /// Store a module into the cache with the given key + fn store(&mut self, key: WasmHash, module: Module) -> Result<(), Self::StoreError>; +} /// Representation of a directory that contains compiled wasm artifacts. /// @@ -105,7 +124,7 @@ impl Cache for FileSystemCache { wasmer_runtime_core::load_cache_with( serialized_cache, crate::compiler_for_backend(backend) - .ok_or_else(|| CacheError::UnsupportedBackend(backend))? + .ok_or_else(|| CacheError::UnsupportedBackend(backend.to_string().to_owned()))? .as_ref(), ) } diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index af130f483..debd372db 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -91,7 +91,10 @@ //! [`wasmer-singlepass-backend`]: https://crates.io/crates/wasmer-singlepass-backend //! [`wasmer-clif-backend`]: https://crates.io/crates/wasmer-clif-backend -pub use wasmer_runtime_core::backend::{Backend, Features}; +#[macro_use] +extern crate serde_derive; + +pub use wasmer_runtime_core::backend::Features; pub use wasmer_runtime_core::codegen::{MiddlewareChain, StreamingCompiler}; pub use wasmer_runtime_core::export::Export; pub use wasmer_runtime_core::global::Global; @@ -144,6 +147,52 @@ pub mod cache; pub use wasmer_runtime_core::backend::{Compiler, CompilerConfig}; +/// Enum used to select which compiler should be used to generate code. +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] +pub enum Backend { + #[cfg(feature = "singlepass")] + /// Singlepass backend + Singlepass, + #[cfg(feature = "cranelift")] + /// Cranelift backend + Cranelift, + #[cfg(feature = "llvm")] + /// LLVM backend + LLVM, + /// Auto backend + Auto, +} + +impl Backend { + /// Stable string representation of the backend. + /// It can be used as part of a cache key, for example. + pub fn to_string(&self) -> &'static str { + match self { + #[cfg(feature = "cranelift")] + Backend::Cranelift => "cranelift", + #[cfg(feature = "singlepass")] + Backend::Singlepass => "singlepass", + #[cfg(feature = "llvm")] + Backend::LLVM => "llvm", + Backend::Auto => "auto", + } + } +} + +impl Default for Backend { + fn default() -> Self { + #[cfg(all(feature = "default-backend-singlepass", not(feature = "docs")))] + return Backend::Singlepass; + + #[cfg(any(feature = "default-backend-cranelift", feature = "docs"))] + return Backend::Cranelift; + + #[cfg(all(feature = "default-backend-llvm", not(feature = "docs")))] + return Backend::LLVM; + } +} + + /// Compile WebAssembly binary code into a [`Module`]. /// This function is useful if it is necessary to /// compile a module before it can be instantiated @@ -268,9 +317,6 @@ pub fn compiler_for_backend(backend: Backend) -> Option> { #[cfg(feature = "default-backend-llvm")] return Some(Box::new(wasmer_llvm_backend::LLVMCompiler::new())); } - - #[cfg(not(all(feature = "llvm", feature = "singlepass", feature = "cranelift")))] - _ => None, } } diff --git a/lib/singlepass-backend/src/codegen_x64.rs b/lib/singlepass-backend/src/codegen_x64.rs index 091658e58..e10b0fc98 100644 --- a/lib/singlepass-backend/src/codegen_x64.rs +++ b/lib/singlepass-backend/src/codegen_x64.rs @@ -23,7 +23,7 @@ use std::{ use wasmer_runtime_core::{ backend::{ sys::{Memory, Protect}, - Architecture, Backend, CacheGen, CompilerConfig, InlineBreakpoint, InlineBreakpointType, + Architecture, CacheGen, CompilerConfig, InlineBreakpoint, InlineBreakpointType, MemoryBoundCheckMode, RunnableModule, Token, }, cache::{Artifact, Error as CacheError}, @@ -647,10 +647,14 @@ impl ModuleCodeGenerator } /// Singlepass does validation as it compiles - fn requires_pre_validation(&self) -> bool { + fn requires_pre_validation() -> bool { false } + fn backend_id() -> String { + "singlepass".to_string() + } + fn new_with_target(_: Option, _: Option, _: Option) -> Self { unimplemented!("cross compilation is not available for singlepass backend") }