diff --git a/lib/clif-backend/src/cache.rs b/lib/clif-backend/src/cache.rs index 7e805271b..84db980b0 100644 --- a/lib/clif-backend/src/cache.rs +++ b/lib/clif-backend/src/cache.rs @@ -1,20 +1,14 @@ use crate::relocation::{ExternalRelocation, TrapSink}; use hashbrown::HashMap; +use std::sync::Arc; use wasmer_runtime_core::{ - backend::{ - sys::Memory, - CacheGen, - }, + backend::{sys::Memory, CacheGen}, cache::{Cache, Error}, module::{ModuleInfo, ModuleInner}, structures::Map, types::{LocalFuncIndex, SigIndex}, }; -use std::{ - sync::Arc, - cell::UnsafeCell, -}; use serde_bench::{deserialize, serialize}; @@ -25,14 +19,29 @@ pub struct CacheGenerator { impl CacheGenerator { pub fn new(backend_cache: BackendCache, memory: Arc) -> Self { - Self { backend_cache, memory } + Self { + backend_cache, + memory, + } } } impl CacheGen for CacheGenerator { - fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), Error> { + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), Error> { let info = Box::new(module.info.clone()); - Ok((info, self.backend_cache.into_backend_data()?.into_boxed_slice(), Arc::clone(&self.memory))) + + // Clone the memory to a new location. This could take a long time, + // depending on the throughput of your memcpy implementation. + let compiled_code = (*self.memory).clone(); + + Ok(( + info, + self.backend_cache.into_backend_data()?.into_boxed_slice(), + compiled_code, + )) } } @@ -53,18 +62,10 @@ pub struct BackendCache { impl BackendCache { pub fn from_cache(cache: Cache) -> Result<(ModuleInfo, Memory, Self), Error> { - let (info, backend_data, compiled_code_arc) = cache.consume(); + let (info, backend_data, compiled_code) = cache.consume(); - // If this is the only references to this arc, move the memory out. - // else, clone the memory to a new location. This could take a long time, - // depending on the throughput of your memcpy implementation. - let compiled_code = match Arc::try_unwrap(compiled_code_arc) { - Ok(code) => code, - Err(arc) => (*arc).clone(), - }; - - let backend_cache = deserialize(&backend_data) - .map_err(|e| Error::DeserializeError(e.to_string()))?; + let backend_cache = + deserialize(&backend_data).map_err(|e| Error::DeserializeError(e.to_string()))?; Ok((info, compiled_code, backend_cache)) } diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index e222f2e07..b08f56dd2 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -145,48 +145,49 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(&self.env.module.info) { - LocalOrImport::Local(local_mem_index) => { - let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_memories() as i32).into(), - global_type: ptr_type, - readonly: true, - }); - - let local_memory_ptr_offset = - local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); - - ( - func.create_global_value(ir::GlobalValueData::IAddImm { - base: memories_base_addr, - offset: (local_memory_ptr_offset as i64).into(), + let (local_memory_ptr_ptr, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => { + let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_memories() as i32).into(), global_type: ptr_type, - }), - self.env.module.info.memories[local_mem_index], - ) - } - LocalOrImport::Import(import_mem_index) => { - let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_imported_memories() as i32).into(), - global_type: ptr_type, - readonly: true, - }); + readonly: true, + }); - let local_memory_ptr_offset = - import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); + let local_memory_ptr_offset = + local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); - ( - func.create_global_value(ir::GlobalValueData::IAddImm { - base: memories_base_addr, - offset: (local_memory_ptr_offset as i64).into(), + ( + func.create_global_value(ir::GlobalValueData::IAddImm { + base: memories_base_addr, + offset: (local_memory_ptr_offset as i64).into(), + global_type: ptr_type, + }), + self.env.module.info.memories[local_mem_index], + ) + } + LocalOrImport::Import(import_mem_index) => { + let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_imported_memories() as i32).into(), global_type: ptr_type, - }), - self.env.module.info.imported_memories[import_mem_index].1, - ) - } - }; + readonly: true, + }); + + let local_memory_ptr_offset = + import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); + + ( + func.create_global_value(ir::GlobalValueData::IAddImm { + base: memories_base_addr, + offset: (local_memory_ptr_offset as i64).into(), + global_type: ptr_type, + }), + self.env.module.info.imported_memories[import_mem_index].1, + ) + } + }; let (local_memory_ptr, local_memory_base) = { let local_memory_ptr = func.create_global_value(ir::GlobalValueData::Load { @@ -253,7 +254,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (table_struct_ptr_ptr, description) = match table_index.local_or_import(&self.env.module.info) + let (table_struct_ptr_ptr, description) = match table_index + .local_or_import(&self.env.module.info) { LocalOrImport::Local(local_table_index) => { let tables_base = func.create_global_value(ir::GlobalValueData::Load { @@ -568,18 +570,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(&self.env.module.info) { - LocalOrImport::Local(local_mem_index) => ( - call_names::LOCAL_NAMESPACE, - local_mem_index.index(), - self.env.module.info.memories[local_mem_index], - ), - LocalOrImport::Import(import_mem_index) => ( - call_names::IMPORT_NAMESPACE, - import_mem_index.index(), - self.env.module.info.imported_memories[import_mem_index].1, - ), - }; + let (namespace, mem_index, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => ( + call_names::LOCAL_NAMESPACE, + local_mem_index.index(), + self.env.module.info.memories[local_mem_index], + ), + LocalOrImport::Import(import_mem_index) => ( + call_names::IMPORT_NAMESPACE, + import_mem_index.index(), + self.env.module.info.imported_memories[import_mem_index].1, + ), + }; let name_index = match description.memory_type() { MemoryType::Dynamic => call_names::DYNAMIC_MEM_GROW, @@ -631,18 +634,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(&self.env.module.info) { - LocalOrImport::Local(local_mem_index) => ( - call_names::LOCAL_NAMESPACE, - local_mem_index.index(), - self.env.module.info.memories[local_mem_index], - ), - LocalOrImport::Import(import_mem_index) => ( - call_names::IMPORT_NAMESPACE, - import_mem_index.index(), - self.env.module.info.imported_memories[import_mem_index].1, - ), - }; + let (namespace, mem_index, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => ( + call_names::LOCAL_NAMESPACE, + local_mem_index.index(), + self.env.module.info.memories[local_mem_index], + ), + LocalOrImport::Import(import_mem_index) => ( + call_names::IMPORT_NAMESPACE, + import_mem_index.index(), + self.env.module.info.imported_memories[import_mem_index].1, + ), + }; let name_index = match description.memory_type() { MemoryType::Dynamic => call_names::DYNAMIC_MEM_SIZE, diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index 42d56552b..8d756420e 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -1,4 +1,3 @@ - mod cache; mod func_env; mod libcalls; @@ -15,11 +14,7 @@ use cranelift_codegen::{ }; use target_lexicon::Triple; -use wasmer_runtime_core::{ - backend::sys::Memory, - cache::{Cache, Error as CacheError}, - module::ModuleInfo, -}; +use wasmer_runtime_core::cache::{Cache, Error as CacheError}; use wasmer_runtime_core::{ backend::{Compiler, Token}, error::{CompileError, CompileResult}, @@ -57,12 +52,12 @@ impl Compiler for CraneliftCompiler { } /// Create a wasmer Module from an already-compiled cache. - + unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result { module::Module::from_cache(cache) } - // + // // fn compile_to_backend_cache_data( // &self, // wasm: &[u8], diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 29eea5f2c..0d0c66d7c 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -1,4 +1,3 @@ - use crate::cache::{BackendCache, CacheGenerator}; use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines}; @@ -8,11 +7,7 @@ use cranelift_wasm; use hashbrown::HashMap; use std::sync::Arc; - -use wasmer_runtime_core::{ - backend::sys::Memory, - cache::{Cache, Error as CacheError}, -}; +use wasmer_runtime_core::cache::{Cache, Error as CacheError}; use wasmer_runtime_core::{ backend::Backend, @@ -58,7 +53,6 @@ impl Module { namespace_table: StringTable::new(), name_table: StringTable::new(), - wasm_hash: WasmHash::generate(wasm), }, } @@ -74,45 +68,53 @@ impl Module { let trampolines = Arc::new(Trampolines::new(isa, &self.info)); - let (func_resolver, backend_cache) = - func_resolver_builder.finalize(&self.info.signatures, Arc::clone(&trampolines), handler_data.clone())?; + let (func_resolver, backend_cache) = func_resolver_builder.finalize( + &self.info.signatures, + Arc::clone(&trampolines), + handler_data.clone(), + )?; - let protected_caller = - Caller::new(&self.info, handler_data, trampolines); - - - let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); + let protected_caller = Caller::new(&self.info, handler_data, trampolines); + + let cache_gen = Box::new(CacheGenerator::new( + backend_cache, + Arc::clone(&func_resolver.memory), + )); Ok(ModuleInner { func_resolver: Box::new(func_resolver), protected_caller: Box::new(protected_caller), - cache_gen, + cache_gen, info: self.info, }) } - pub fn from_cache(cache: Cache) -> Result { let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?; let (func_resolver_builder, trampolines, handler_data) = FuncResolverBuilder::new_from_backend_cache(backend_cache, compiled_code, &info)?; - let (func_resolver, backend_cache) = - func_resolver_builder - .finalize(&info.signatures, Arc::clone(&trampolines), handler_data.clone()) - .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?; + let (func_resolver, backend_cache) = func_resolver_builder + .finalize( + &info.signatures, + Arc::clone(&trampolines), + handler_data.clone(), + ) + .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?; let protected_caller = Caller::new(&info, handler_data, trampolines); - - let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); + let cache_gen = Box::new(CacheGenerator::new( + backend_cache, + Arc::clone(&func_resolver.memory), + )); Ok(ModuleInner { func_resolver: Box::new(func_resolver), protected_caller: Box::new(protected_caller), - cache_gen, + cache_gen, info, }) diff --git a/lib/clif-backend/src/relocation.rs b/lib/clif-backend/src/relocation.rs index 03adbc4bb..92ef0485a 100644 --- a/lib/clif-backend/src/relocation.rs +++ b/lib/clif-backend/src/relocation.rs @@ -22,16 +22,14 @@ pub mod call_names { pub const DYNAMIC_MEM_SIZE: u32 = 5; } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum Reloc { Abs8, X86PCRel4, X86CallPCRel4, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone)] pub enum LibCall { Probestack, CeilF32, @@ -44,8 +42,7 @@ pub enum LibCall { NearestF64, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct ExternalRelocation { /// The relocation code. pub reloc: Reloc, @@ -66,8 +63,7 @@ pub struct LocalRelocation { pub target: FuncIndex, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum VmCallKind { StaticMemoryGrow, StaticMemorySize, @@ -79,16 +75,14 @@ pub enum VmCallKind { DynamicMemorySize, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum VmCall { Local(VmCallKind), Import(VmCallKind), } /// Specify the type of relocation -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub enum RelocationType { Intrinsic(String), LibCall(LibCall), @@ -218,8 +212,7 @@ impl binemit::RelocSink for RelocSink { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum TrapCode { StackOverflow, HeapOutOfBounds, @@ -244,8 +237,7 @@ impl RelocSink { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct TrapData { pub trapcode: TrapCode, pub srcloc: u32, diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 06b678a5b..604778f01 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -1,8 +1,4 @@ - -use crate::{ - cache::{BackendCache, TrampolineCache}, - trampoline::Trampolines, -}; +use crate::{cache::BackendCache, trampoline::Trampolines}; use crate::{ libcalls, relocation::{ @@ -17,7 +13,6 @@ use cranelift_codegen::{ir, isa, Context}; use std::{ mem, ptr::{write_unaligned, NonNull}, - cell::UnsafeCell, sync::Arc, }; @@ -43,7 +38,11 @@ extern "C" { pub fn __chkstk(); } -fn lookup_func(map: &SliceMap, memory: &Memory, local_func_index: LocalFuncIndex) -> Option> { +fn lookup_func( + map: &SliceMap, + memory: &Memory, + local_func_index: LocalFuncIndex, +) -> Option> { let offset = *map.get(local_func_index)?; let ptr = unsafe { memory.as_ptr().add(offset) }; @@ -60,7 +59,6 @@ pub struct FuncResolverBuilder { } impl FuncResolverBuilder { - pub fn new_from_backend_cache( backend_cache: BackendCache, mut code: Memory, @@ -82,7 +80,9 @@ impl FuncResolverBuilder { external_relocs: backend_cache.external_relocs, import_len: info.imported_functions.len(), }, - Arc::new(Trampolines::from_trampoline_cache(backend_cache.trampolines)), + Arc::new(Trampolines::from_trampoline_cache( + backend_cache.trampolines, + )), handler_data, )) } @@ -158,7 +158,8 @@ impl FuncResolverBuilder { previous_end = new_end; } - let handler_data = HandlerData::new(Arc::new(trap_sink), memory.as_ptr() as _, memory.size()); + let handler_data = + HandlerData::new(Arc::new(trap_sink), memory.as_ptr() as _, memory.size()); let mut func_resolver_builder = Self { map, @@ -177,12 +178,15 @@ impl FuncResolverBuilder { for (index, relocs) in self.local_relocs.iter() { for ref reloc in relocs.iter() { let local_func_index = LocalFuncIndex::new(reloc.target.index() - self.import_len); - let target_func_address = - lookup_func(&self.map, &self.memory, local_func_index).unwrap().as_ptr() as usize; + let target_func_address = lookup_func(&self.map, &self.memory, local_func_index) + .unwrap() + .as_ptr() as usize; // We need the address of the current function // because these calls are relative. - let func_addr = lookup_func(&self.map, &self.memory, index).unwrap().as_ptr() as usize; + let func_addr = lookup_func(&self.map, &self.memory, index) + .unwrap() + .as_ptr() as usize; unsafe { let reloc_address = func_addr + reloc.offset as usize; @@ -273,7 +277,9 @@ impl FuncResolverBuilder { // We need the address of the current function // because some of these calls are relative. - let func_addr = lookup_func(&self.map, &self.memory, index).unwrap().as_ptr() as usize; + let func_addr = lookup_func(&self.map, &self.memory, index) + .unwrap() + .as_ptr() as usize; // Determine relocation type and apply relocation. match reloc.reloc { @@ -313,10 +319,13 @@ impl FuncResolverBuilder { trampolines: trampolines.to_trampoline_cache(), }; - Ok((FuncResolver { - map: self.map, - memory: Arc::new(self.memory), - }, backend_cache)) + Ok(( + FuncResolver { + map: self.map, + memory: Arc::new(self.memory), + }, + backend_cache, + )) } } diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index bedcff87a..9ccbf1822 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -44,7 +44,11 @@ pub struct Caller { } impl Caller { - pub fn new(module: &ModuleInfo, handler_data: HandlerData, trampolines: Arc) -> Self { + pub fn new( + module: &ModuleInfo, + handler_data: HandlerData, + trampolines: Arc, + ) -> Self { let mut func_export_set = HashSet::new(); for export_index in module.exports.values() { if let ExportIndex::Func(func_index) = export_index { diff --git a/lib/clif-backend/src/trampoline.rs b/lib/clif-backend/src/trampoline.rs index 7a90c085e..b20109ef0 100644 --- a/lib/clif-backend/src/trampoline.rs +++ b/lib/clif-backend/src/trampoline.rs @@ -1,4 +1,3 @@ - use crate::cache::TrampolineCache; use cranelift_codegen::{ binemit::{NullTrapSink, Reloc, RelocSink}, @@ -33,7 +32,6 @@ pub struct Trampolines { } impl Trampolines { - pub fn from_trampoline_cache(cache: TrampolineCache) -> Self { // pub struct TrampolineCache { // #[serde(with = "serde_bytes")] @@ -57,7 +55,6 @@ impl Trampolines { } } - pub fn to_trampoline_cache(&self) -> TrampolineCache { let mut code = vec![0; self.memory.size()]; diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 3ed5c36dd..5c2a04e57 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -220,13 +220,13 @@ impl EmscriptenGlobals { namespace_index, name_index, }, - ) in &module.0.info.imported_functions + ) in &module.info().imported_functions { - let namespace = module.0.info.namespace_table.get(*namespace_index); - let name = module.0.info.name_table.get(*name_index); + let namespace = module.info().namespace_table.get(*namespace_index); + let name = module.info().name_table.get(*name_index); if name == "abortOnCannotGrowMemory" && namespace == "env" { - let sig_index = module.0.info.func_assoc[index.convert_up(&module.0)]; - let expected_sig = &module.0.info.signatures[sig_index]; + let sig_index = module.info().func_assoc[index.convert_up(module.info())]; + let expected_sig = &module.info().signatures[sig_index]; if **expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG { use_old_abort_on_cannot_grow_memory = true; } diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index 82ab0f251..678032374 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -16,13 +16,12 @@ use wasmer_runtime_core::{ /// We check if a provided module is an Emscripten generated one pub fn is_emscripten_module(module: &Module) -> bool { - for (_, import_name) in &module.0.info.imported_functions { + for (_, import_name) in &module.info().imported_functions { let namespace = module - .0 - .info + .info() .namespace_table .get(import_name.namespace_index); - let field = module.0.info.name_table.get(import_name.name_index); + let field = module.info().name_table.get(import_name.name_index); if field == "_emscripten_memcpy_big" && namespace == "env" { return true; } @@ -31,12 +30,12 @@ pub fn is_emscripten_module(module: &Module) -> bool { } pub fn get_emscripten_table_size(module: &Module) -> (u32, Option) { - let (_, table) = &module.0.info.imported_tables[ImportedTableIndex::new(0)]; + let (_, table) = &module.info().imported_tables[ImportedTableIndex::new(0)]; (table.minimum, table.maximum) } pub fn get_emscripten_memory_size(module: &Module) -> (Pages, Option) { - let (_, memory) = &module.0.info.imported_memories[ImportedMemoryIndex::new(0)]; + let (_, memory) = &module.info().imported_memories[ImportedMemoryIndex::new(0)]; (memory.minimum, memory.maximum) } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index a4afe2ee5..e490b5e3e 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -2,7 +2,7 @@ use crate::{ backing::ImportBacking, error::CompileResult, error::RuntimeResult, - module::{ModuleInner}, + module::ModuleInner, types::{FuncIndex, LocalFuncIndex, Value}, vm, }; @@ -21,8 +21,7 @@ pub mod sys { } pub use crate::sig_registry::SigRegistry; -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum Backend { Cranelift, } @@ -45,7 +44,6 @@ pub trait Compiler { /// be called from inside the runtime. fn compile(&self, wasm: &[u8], _: Token) -> CompileResult; - unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result; } @@ -95,7 +93,9 @@ pub trait FuncResolver: Send + Sync { ) -> Option>; } - pub trait CacheGen: Send + Sync { - fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), CacheError>; -} \ No newline at end of file + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), CacheError>; +} diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index b60301e94..d49dd4215 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -6,9 +6,9 @@ use std::{ fs::File, io::{self, Seek, SeekFrom, Write}, mem, - sync::Arc, path::Path, slice, + sync::Arc, }; #[derive(Debug)] @@ -69,7 +69,7 @@ struct CacheInner { info: Box, #[serde(with = "serde_bytes")] backend_metadata: Box<[u8]>, - compiled_code: Arc, + compiled_code: Memory, } pub struct Cache { @@ -80,7 +80,7 @@ impl Cache { pub(crate) fn from_parts( info: Box, backend_metadata: Box<[u8]>, - compiled_code: Arc, + compiled_code: Memory, ) -> Self { Self { inner: CacheInner { @@ -104,9 +104,7 @@ impl Cache { let inner = deserialize(body_slice).map_err(|e| Error::DeserializeError(format!("{:#?}", e)))?; - Ok(Cache { - inner, - }) + Ok(Cache { inner }) } pub fn info(&self) -> &ModuleInfo { @@ -114,7 +112,7 @@ impl Cache { } #[doc(hidden)] - pub fn consume(self) -> (ModuleInfo, Box<[u8]>, Arc) { + pub fn consume(self) -> (ModuleInfo, Box<[u8]>, Memory) { ( *self.inner.info, self.inner.backend_metadata, diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 18cf2a703..7025acf5a 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -2,7 +2,6 @@ #[macro_use] extern crate field_offset; - #[macro_use] extern crate serde_derive; @@ -44,7 +43,6 @@ pub use self::module::Module; pub use self::typed_func::Func; use std::sync::Arc; - use self::cache::{Cache, Error as CacheError}; pub mod prelude { @@ -90,7 +88,7 @@ pub fn validate(wasm: &[u8]) -> bool { } } -// +// // pub fn compile_to_cache_with( // wasm: &[u8], // compiler: &dyn backend::Compiler, @@ -102,7 +100,6 @@ pub fn validate(wasm: &[u8]) -> bool { // Ok(Cache::new(wasm, info, backend_metadata, compiled_code)) // } - pub unsafe fn load_cache_with( cache: Cache, compiler: &dyn backend::Compiler, diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 0526c0ad4..5cb1b5b21 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,5 +1,6 @@ use crate::{ backend::{Backend, FuncResolver, ProtectedCaller}, + cache::{Cache, Error as CacheError}, error, import::ImportObject, structures::{Map, TypedIndex}, @@ -10,7 +11,6 @@ use crate::{ LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor, TableIndex, }, - cache::{Cache, Error as CacheError}, Instance, }; @@ -25,14 +25,12 @@ pub struct ModuleInner { pub func_resolver: Box, pub protected_caller: Box, - pub cache_gen: Box, pub info: ModuleInfo, } -#[derive(Clone)] -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] pub struct ModuleInfo { // This are strictly local and the typsystem ensures that. pub memories: Map, @@ -62,12 +60,9 @@ pub struct ModuleInfo { pub wasm_hash: WasmHash, } - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -#[derive(Serialize, Deserialize)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct WasmHash([u8; 32]); - impl WasmHash { pub fn generate(wasm: &[u8]) -> Self { WasmHash(crate::cache::hash_data(wasm)) @@ -125,23 +120,25 @@ impl Module { } pub fn cache(&self) -> Result { - let (info, backend_cache, code) = self.inner.cache_gen.generate_cache(&self.inner)?; - + let (info, backend_metadata, code) = self.inner.cache_gen.generate_cache(&self.inner)?; + Ok(Cache::from_parts(info, backend_metadata, code)) + } + + pub fn info(&self) -> &ModuleInfo { + &self.inner.info } } impl ModuleInner {} #[doc(hidden)] -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct ImportName { pub namespace_index: NamespaceIndex, pub name_index: NameIndex, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub enum ExportIndex { Func(FuncIndex), Memory(MemoryIndex), @@ -150,8 +147,7 @@ pub enum ExportIndex { } /// A data initializer for linear memory. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct DataInitializer { /// The index of the memory to initialize. pub memory_index: MemoryIndex, @@ -163,8 +159,7 @@ pub struct DataInitializer { } /// A WebAssembly table initializer. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct TableInitializer { /// The index of a table to initialize. pub table_index: TableIndex, @@ -225,8 +220,7 @@ impl StringTableBuilder { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct StringTable { table: Map, buffer: String, @@ -249,8 +243,7 @@ impl StringTable { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NamespaceIndex(u32); impl TypedIndex for NamespaceIndex { @@ -265,8 +258,7 @@ impl TypedIndex for NamespaceIndex { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NameIndex(u32); impl TypedIndex for NameIndex { diff --git a/lib/runtime-core/src/structures/map.rs b/lib/runtime-core/src/structures/map.rs index df95fe652..d7177c427 100644 --- a/lib/runtime-core/src/structures/map.rs +++ b/lib/runtime-core/src/structures/map.rs @@ -8,8 +8,7 @@ use std::{ }; /// Dense item map -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Map where K: TypedIndex, diff --git a/lib/runtime-core/src/sys/mod.rs b/lib/runtime-core/src/sys/mod.rs index 2fdc1ef0f..0bfc134c2 100644 --- a/lib/runtime-core/src/sys/mod.rs +++ b/lib/runtime-core/src/sys/mod.rs @@ -10,7 +10,6 @@ pub use self::unix::*; #[cfg(windows)] pub use self::windows::*; - use serde::{ de::{self, SeqAccess, Visitor}, ser::SerializeStruct, @@ -21,7 +20,6 @@ use serde_bytes::Bytes; use std::fmt; - impl Serialize for Memory { fn serialize(&self, serializer: S) -> Result where @@ -36,7 +34,6 @@ impl Serialize for Memory { } } - impl<'de> Deserialize<'de> for Memory { fn deserialize(deserializer: D) -> Result where diff --git a/lib/runtime-core/src/sys/unix/memory.rs b/lib/runtime-core/src/sys/unix/memory.rs index 7154f34f9..8c76e6c14 100644 --- a/lib/runtime-core/src/sys/unix/memory.rs +++ b/lib/runtime-core/src/sys/unix/memory.rs @@ -207,16 +207,26 @@ impl Drop for Memory { impl Clone for Memory { fn clone(&self) -> Self { - let mut new = Memory::with_size_protect(self.size, self.protection).unwrap(); + let temp_protection = if self.protection.is_writable() { + self.protection + } else { + Protect::ReadWrite + }; + + let mut new = Memory::with_size_protect(self.size, temp_protection).unwrap(); unsafe { new.as_slice_mut().copy_from_slice(self.as_slice()); + + if temp_protection != self.protection { + new.protect(.., self.protection).unwrap(); + } } + new } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] #[allow(dead_code)] pub enum Protect { None, diff --git a/lib/runtime-core/src/sys/windows/memory.rs b/lib/runtime-core/src/sys/windows/memory.rs index 578070a3e..771ac6788 100644 --- a/lib/runtime-core/src/sys/windows/memory.rs +++ b/lib/runtime-core/src/sys/windows/memory.rs @@ -158,16 +158,26 @@ impl Drop for Memory { impl Clone for Memory { fn clone(&self) -> Self { - let mut new = Memory::with_size_protect(self.size, self.protection).unwrap(); + let temp_protection = if self.protection.is_writable() { + self.protection + } else { + Protect::ReadWrite + }; + + let mut new = Memory::with_size_protect(self.size, temp_protection).unwrap(); unsafe { new.as_slice_mut().copy_from_slice(self.as_slice()); + + if temp_protection != self.protection { + new.protect(.., self.protection).unwrap(); + } } + new } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] #[allow(dead_code)] pub enum Protect { None, diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index f19e73a6e..9ee5270dd 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -2,8 +2,7 @@ use crate::{memory::MemoryType, module::ModuleInfo, structures::TypedIndex, unit use std::{borrow::Cow, mem}; /// Represents a WebAssembly type. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Type { /// The `i32` type. I32, @@ -25,8 +24,7 @@ impl std::fmt::Display for Type { /// /// As the number of types in WebAssembly expand, /// this structure will expand as well. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum Value { /// The `i32` type. I32(i32), @@ -171,15 +169,13 @@ impl ValueType for f64 { } } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub enum ElementType { /// Any wasm function. Anyfunc, } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct TableDescriptor { /// Type of data stored in this table. pub element: ElementType, @@ -203,8 +199,7 @@ impl TableDescriptor { /// A const value initializer. /// Over time, this will be able to represent more and more /// complex expressions. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum Initializer { /// Corresponds to a `const.*` instruction. Const(Value), @@ -212,24 +207,21 @@ pub enum Initializer { GetGlobal(ImportedGlobalIndex), } -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub struct GlobalDescriptor { pub mutable: bool, pub ty: Type, } /// A wasm global. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct GlobalInit { pub desc: GlobalDescriptor, pub init: Initializer, } /// A wasm memory. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub struct MemoryDescriptor { /// The minimum number of allowed pages. pub minimum: Pages, @@ -261,8 +253,7 @@ impl MemoryDescriptor { /// The signature of a function that is either implemented /// in a wasm module or exposed to wasm by the host. -#[derive(Serialize, Deserialize)] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] pub struct FuncSig { params: Cow<'static, [Type]>, returns: Cow<'static, [Type]>, @@ -400,8 +391,7 @@ define_local_or_import![ (GlobalIndex | (LocalGlobalIndex, ImportedGlobalIndex): imported_globals), ]; -#[derive(Serialize, Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct SigIndex(u32); impl TypedIndex for SigIndex { #[doc(hidden)] diff --git a/lib/runtime-core/src/units.rs b/lib/runtime-core/src/units.rs index 6a1582e9e..2486c5738 100644 --- a/lib/runtime-core/src/units.rs +++ b/lib/runtime-core/src/units.rs @@ -7,8 +7,7 @@ const WASM_PAGE_SIZE: usize = 65_536; const WASM_MAX_PAGES: usize = 65_536; /// Units of WebAssembly pages (as specified to be 65,536 bytes). -#[derive(Serialize, Deserialize)] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Pages(pub u32); impl Pages { @@ -33,8 +32,7 @@ impl fmt::Debug for Pages { } /// Units of WebAssembly memory in terms of 8-bit bytes. -#[derive(Serialize, Deserialize)] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Bytes(pub usize); impl fmt::Debug for Bytes { diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 79d18255a..4d6e6880d 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -494,11 +494,13 @@ mod vm_ctx_tests { fn generate_module() -> ModuleInner { use super::Func; - use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper, CacheGen, sys::Memory}; + use crate::backend::{ + sys::Memory, Backend, CacheGen, FuncResolver, ProtectedCaller, Token, UserTrapper, + }; use crate::cache::Error as CacheError; use crate::error::RuntimeResult; - use crate::types::{FuncIndex, LocalFuncIndex, Value}; use crate::module::WasmHash; + use crate::types::{FuncIndex, LocalFuncIndex, Value}; use hashbrown::HashMap; use std::ptr::NonNull; struct Placeholder; @@ -528,11 +530,13 @@ mod vm_ctx_tests { } } impl CacheGen for Placeholder { - fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Memory), CacheError> { + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), CacheError> { unimplemented!() } } - ModuleInner { func_resolver: Box::new(Placeholder),