diff --git a/lib/clif-backend/src/cache.rs b/lib/clif-backend/src/cache.rs index aef6adf4c..cf1b9c919 100644 --- a/lib/clif-backend/src/cache.rs +++ b/lib/clif-backend/src/cache.rs @@ -2,15 +2,41 @@ use crate::relocation::{ExternalRelocation, TrapSink}; use hashbrown::HashMap; use wasmer_runtime_core::{ - backend::sys::Memory, + backend::{ + sys::Memory, + CacheGen, + }, cache::{Cache, Error}, - module::ModuleInfo, + module::{ModuleInfo, ModuleInner}, structures::Map, types::{LocalFuncIndex, SigIndex}, }; +use std::{ + sync::Arc, + cell::UnsafeCell, +}; use serde_bench::{deserialize, serialize}; +pub struct CacheGenerator { + backend_cache: BackendCache, + memory: Arc, +} + +impl CacheGenerator { + pub fn new(backend_cache: BackendCache, memory: Arc) -> Self { + Self { backend_cache, memory } + } +} + +impl CacheGen for CacheGenerator { + fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), Error> { + let info = Box::new(module.info.clone()); + + Err(Error::Unknown("".to_string())) + } +} + #[derive(Serialize, Deserialize)] pub struct TrampolineCache { #[serde(with = "serde_bytes")] @@ -22,7 +48,7 @@ pub struct TrampolineCache { pub struct BackendCache { pub external_relocs: Map>, pub offsets: Map, - pub trap_sink: TrapSink, + pub trap_sink: Arc, pub trampolines: TrampolineCache, } diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index cbe455b93..621d5b59e 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -62,36 +62,36 @@ impl Compiler for CraneliftCompiler { module::Module::from_cache(cache) } - #[cfg(feature = "cache")] - fn compile_to_backend_cache_data( - &self, - wasm: &[u8], - _: Token, - ) -> CompileResult<(Box, Vec, Memory)> { - validate(wasm)?; + // #[cfg(feature = "cache")] + // fn compile_to_backend_cache_data( + // &self, + // wasm: &[u8], + // _: Token, + // ) -> CompileResult<(Box, Vec, Memory)> { + // validate(wasm)?; - let isa = get_isa(); + // let isa = get_isa(); - let mut module = module::Module::new(wasm); - let module_env = module_env::ModuleEnv::new(&mut module, &*isa); + // let mut module = module::Module::new(wasm); + // let module_env = module_env::ModuleEnv::new(&mut module, &*isa); - let func_bodies = module_env.translate(wasm)?; + // let func_bodies = module_env.translate(wasm)?; - let (info, backend_cache, compiled_code) = module - .compile_to_backend_cache(&*isa, func_bodies) - .map_err(|e| CompileError::InternalError { - msg: format!("{:?}", e), - })?; + // let (info, backend_cache, compiled_code) = module + // .compile_to_backend_cache(&*isa, func_bodies) + // .map_err(|e| CompileError::InternalError { + // msg: format!("{:?}", e), + // })?; - let buffer = - backend_cache - .into_backend_data() - .map_err(|e| CompileError::InternalError { - msg: format!("{:?}", e), - })?; + // let buffer = + // backend_cache + // .into_backend_data() + // .map_err(|e| CompileError::InternalError { + // msg: format!("{:?}", e), + // })?; - Ok((Box::new(info), buffer, compiled_code)) - } + // Ok((Box::new(info), buffer, compiled_code)) + // } } fn get_isa() -> Box { diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index e2ee8efe8..23f07eac9 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -1,11 +1,12 @@ #[cfg(feature = "cache")] -use crate::cache::BackendCache; +use crate::cache::{BackendCache, CacheGenerator}; use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines}; use cranelift_codegen::{ir, isa}; use cranelift_entity::EntityRef; use cranelift_wasm; use hashbrown::HashMap; +use std::sync::Arc; #[cfg(feature = "cache")] use wasmer_runtime_core::{ @@ -67,42 +68,44 @@ impl Module { ) -> CompileResult { let (func_resolver_builder, handler_data) = FuncResolverBuilder::new(isa, functions, &self.info)?; - - let func_resolver = - Box::new(func_resolver_builder.finalize(&self.info.signatures)?); + let trampolines = Arc::new(Trampolines::new(isa, &self.info)); - let trampolines = Trampolines::new(isa, &self.info); + let (func_resolver, backend_cache) = + func_resolver_builder.finalize(&self.info.signatures, Arc::clone(&trampolines), handler_data.clone())?; let protected_caller = - Box::new(Caller::new(&self.info, handler_data, trampolines)); + 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, - protected_caller, + func_resolver: Box::new(func_resolver), + protected_caller: Box::new(protected_caller), + cache_gen, info: self.info, }) } - #[cfg(feature = "cache")] - pub fn compile_to_backend_cache( - self, - isa: &isa::TargetIsa, - functions: Map, - ) -> CompileResult<(ModuleInfo, BackendCache, Memory)> { - let (func_resolver_builder, handler_data) = - FuncResolverBuilder::new(isa, functions, &self.info)?; + // #[cfg(feature = "cache")] + // pub fn compile_to_backend_cache( + // self, + // isa: &isa::TargetIsa, + // functions: Map, + // ) -> CompileResult<(ModuleInfo, BackendCache, Memory)> { + // let (func_resolver_builder, handler_data) = + // FuncResolverBuilder::new(isa, functions, &self.info)?; - let trampolines = Trampolines::new(isa, &self.info); + // let trampolines = Trampolines::new(isa, &self.info); - let trampoline_cache = trampolines.to_trampoline_cache(); + // let trampoline_cache = trampolines.to_trampoline_cache(); - let (backend_cache, compiled_code) = - func_resolver_builder.to_backend_cache(trampoline_cache, handler_data); + // let (backend_cache, compiled_code) = + // func_resolver_builder.to_backend_cache(trampoline_cache, handler_data); - Ok((self.info, backend_cache, compiled_code)) - } + // Ok((self.info, backend_cache, compiled_code)) + // } #[cfg(feature = "cache")] pub fn from_cache(cache: Cache) -> Result { @@ -111,17 +114,19 @@ impl Module { let (func_resolver_builder, trampolines, handler_data) = FuncResolverBuilder::new_from_backend_cache(backend_cache, compiled_code, &info)?; - let func_resolver = Box::new( + let (func_resolver, backend_cache) = func_resolver_builder - .finalize(&info.signatures) - .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?, - ); + .finalize(&info.signatures, Arc::clone(&trampolines), handler_data.clone()) + .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?; - let protected_caller = Box::new(Caller::new(&info, handler_data, trampolines)); + let protected_caller = Caller::new(&info, handler_data, trampolines); + let cache_gen = Box::new(CacheGenerator::new(backend_cache, Arc::clone(&func_resolver.memory))); Ok(ModuleInner { - func_resolver, - protected_caller, + func_resolver: Box::new(func_resolver), + protected_caller: Box::new(protected_caller), + cache_gen, + info, }) } diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 48ea5c7e5..1eccb2715 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -17,6 +17,7 @@ use cranelift_codegen::{ir, isa, Context}; use std::{ mem, ptr::{write_unaligned, NonNull}, + cell::UnsafeCell, sync::Arc, }; #[cfg(feature = "cache")] @@ -56,7 +57,7 @@ impl FuncResolverBuilder { backend_cache: BackendCache, mut code: Memory, info: &ModuleInfo, - ) -> Result<(Self, Trampolines, HandlerData), CacheError> { + ) -> Result<(Self, Arc, HandlerData), CacheError> { unsafe { code.protect(.., Protect::ReadWrite) .map_err(|e| CacheError::Unknown(e.to_string()))?; @@ -69,35 +70,17 @@ impl FuncResolverBuilder { Self { resolver: FuncResolver { map: backend_cache.offsets, - memory: code, + memory: Arc::new(UnsafeCell::new(code)), }, local_relocs: Map::new(), external_relocs: backend_cache.external_relocs, import_len: info.imported_functions.len(), }, - Trampolines::from_trampoline_cache(backend_cache.trampolines), + Arc::new(Trampolines::from_trampoline_cache(backend_cache.trampolines)), handler_data, )) } - #[cfg(feature = "cache")] - pub fn to_backend_cache( - mut self, - trampolines: TrampolineCache, - handler_data: HandlerData, - ) -> (BackendCache, Memory) { - self.relocate_locals(); - ( - BackendCache { - external_relocs: self.external_relocs, - offsets: self.resolver.map, - trap_sink: handler_data.trap_data, - trampolines, - }, - self.resolver.memory, - ) - } - pub fn new( isa: &isa::TargetIsa, function_bodies: Map, @@ -169,10 +152,10 @@ impl FuncResolverBuilder { previous_end = new_end; } - let handler_data = HandlerData::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 { - resolver: FuncResolver { map, memory }, + resolver: FuncResolver { map, memory: Arc::new(UnsafeCell::new(memory)) }, local_relocs, external_relocs, import_len: info.imported_functions.len(), @@ -207,128 +190,143 @@ impl FuncResolverBuilder { } pub fn finalize( - mut self, + self, signatures: &SliceMap>, - ) -> CompileResult { - for (index, relocs) in self.external_relocs.iter() { - for ref reloc in relocs.iter() { - let target_func_address: isize = match reloc.target { - RelocationType::LibCall(libcall) => match libcall { - LibCall::CeilF32 => libcalls::ceilf32 as isize, - LibCall::FloorF32 => libcalls::floorf32 as isize, - LibCall::TruncF32 => libcalls::truncf32 as isize, - LibCall::NearestF32 => libcalls::nearbyintf32 as isize, - LibCall::CeilF64 => libcalls::ceilf64 as isize, - LibCall::FloorF64 => libcalls::floorf64 as isize, - LibCall::TruncF64 => libcalls::truncf64 as isize, - LibCall::NearestF64 => libcalls::nearbyintf64 as isize, - #[cfg(all(target_pointer_width = "64", target_os = "windows"))] - LibCall::Probestack => __chkstk as isize, - #[cfg(not(target_os = "windows"))] - LibCall::Probestack => __rust_probestack as isize, - }, - RelocationType::Intrinsic(ref name) => match name.as_str() { - "i32print" => i32_print as isize, - "i64print" => i64_print as isize, - "f32print" => f32_print as isize, - "f64print" => f64_print as isize, - "strtdbug" => start_debug as isize, - "enddbug" => end_debug as isize, - _ => Err(CompileError::InternalError { - msg: format!("unexpected intrinsic: {}", name), - })?, - }, - RelocationType::VmCall(vmcall) => match vmcall { - VmCall::Local(kind) => match kind { - VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _, - VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _, + trampolines: Arc, + handler_data: HandlerData, + ) -> CompileResult<(FuncResolver, BackendCache)> { + { + let mut memory = unsafe { (*self.resolver.memory.get()) }; - VmCallKind::SharedStaticMemoryGrow => unimplemented!(), - VmCallKind::SharedStaticMemorySize => unimplemented!(), - - VmCallKind::DynamicMemoryGrow => { - vmcalls::local_dynamic_memory_grow as _ - } - VmCallKind::DynamicMemorySize => { - vmcalls::local_dynamic_memory_size as _ - } + for (index, relocs) in self.external_relocs.iter() { + for ref reloc in relocs.iter() { + let target_func_address: isize = match reloc.target { + RelocationType::LibCall(libcall) => match libcall { + LibCall::CeilF32 => libcalls::ceilf32 as isize, + LibCall::FloorF32 => libcalls::floorf32 as isize, + LibCall::TruncF32 => libcalls::truncf32 as isize, + LibCall::NearestF32 => libcalls::nearbyintf32 as isize, + LibCall::CeilF64 => libcalls::ceilf64 as isize, + LibCall::FloorF64 => libcalls::floorf64 as isize, + LibCall::TruncF64 => libcalls::truncf64 as isize, + LibCall::NearestF64 => libcalls::nearbyintf64 as isize, + #[cfg(all(target_pointer_width = "64", target_os = "windows"))] + LibCall::Probestack => __chkstk as isize, + #[cfg(not(target_os = "windows"))] + LibCall::Probestack => __rust_probestack as isize, }, - VmCall::Import(kind) => match kind { - VmCallKind::StaticMemoryGrow => { - vmcalls::imported_static_memory_grow as _ - } - VmCallKind::StaticMemorySize => { - vmcalls::imported_static_memory_size as _ - } - - VmCallKind::SharedStaticMemoryGrow => unimplemented!(), - VmCallKind::SharedStaticMemorySize => unimplemented!(), - - VmCallKind::DynamicMemoryGrow => { - vmcalls::imported_dynamic_memory_grow as _ - } - VmCallKind::DynamicMemorySize => { - vmcalls::imported_dynamic_memory_size as _ - } + RelocationType::Intrinsic(ref name) => match name.as_str() { + "i32print" => i32_print as isize, + "i64print" => i64_print as isize, + "f32print" => f32_print as isize, + "f64print" => f64_print as isize, + "strtdbug" => start_debug as isize, + "enddbug" => end_debug as isize, + _ => Err(CompileError::InternalError { + msg: format!("unexpected intrinsic: {}", name), + })?, + }, + RelocationType::VmCall(vmcall) => match vmcall { + VmCall::Local(kind) => match kind { + VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _, + VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _, + + VmCallKind::SharedStaticMemoryGrow => unimplemented!(), + VmCallKind::SharedStaticMemorySize => unimplemented!(), + + VmCallKind::DynamicMemoryGrow => { + vmcalls::local_dynamic_memory_grow as _ + } + VmCallKind::DynamicMemorySize => { + vmcalls::local_dynamic_memory_size as _ + } + }, + VmCall::Import(kind) => match kind { + VmCallKind::StaticMemoryGrow => { + vmcalls::imported_static_memory_grow as _ + } + VmCallKind::StaticMemorySize => { + vmcalls::imported_static_memory_size as _ + } + + VmCallKind::SharedStaticMemoryGrow => unimplemented!(), + VmCallKind::SharedStaticMemorySize => unimplemented!(), + + VmCallKind::DynamicMemoryGrow => { + vmcalls::imported_dynamic_memory_grow as _ + } + VmCallKind::DynamicMemorySize => { + vmcalls::imported_dynamic_memory_size as _ + } + }, + }, + RelocationType::Signature(sig_index) => { + let sig_index = + SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index])); + sig_index.index() as _ + } + }; + + // We need the address of the current function + // because some of these calls are relative. + let func_addr = self.resolver.lookup(index).unwrap().as_ptr(); + + // Determine relocation type and apply relocation. + match reloc.reloc { + Reloc::Abs8 => { + let ptr_to_write = (target_func_address as u64) + .checked_add(reloc.addend as u64) + .unwrap(); + let empty_space_offset = self.resolver.map[index] + reloc.offset as usize; + let ptr_slice = unsafe { + &mut memory.as_slice_mut() + [empty_space_offset..empty_space_offset + 8] + }; + LittleEndian::write_u64(ptr_slice, ptr_to_write); + } + Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => unsafe { + let reloc_address = (func_addr as usize) + reloc.offset as usize; + let reloc_delta = target_func_address + .wrapping_sub(reloc_address as isize) + .wrapping_add(reloc.addend as isize); + + write_unaligned(reloc_address as *mut u32, reloc_delta as u32); }, - }, - RelocationType::Signature(sig_index) => { - let sig_index = - SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index])); - sig_index.index() as _ } - }; - - // We need the address of the current function - // because some of these calls are relative. - let func_addr = self.resolver.lookup(index).unwrap().as_ptr(); - - // Determine relocation type and apply relocation. - match reloc.reloc { - Reloc::Abs8 => { - let ptr_to_write = (target_func_address as u64) - .checked_add(reloc.addend as u64) - .unwrap(); - let empty_space_offset = self.resolver.map[index] + reloc.offset as usize; - let ptr_slice = unsafe { - &mut self.resolver.memory.as_slice_mut() - [empty_space_offset..empty_space_offset + 8] - }; - LittleEndian::write_u64(ptr_slice, ptr_to_write); - } - Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => unsafe { - let reloc_address = (func_addr as usize) + reloc.offset as usize; - let reloc_delta = target_func_address - .wrapping_sub(reloc_address as isize) - .wrapping_add(reloc.addend as isize); - - write_unaligned(reloc_address as *mut u32, reloc_delta as u32); - }, } } + + unsafe { + memory + .protect(.., Protect::ReadExec) + .map_err(|e| CompileError::InternalError { msg: e.to_string() })?; + } } - unsafe { - self.resolver - .memory - .protect(.., Protect::ReadExec) - .map_err(|e| CompileError::InternalError { msg: e.to_string() })?; - } + let backend_cache = BackendCache { + external_relocs: self.external_relocs.clone(), + offsets: self.resolver.map.clone(), + trap_sink: handler_data.trap_data, + trampolines: trampolines.to_trampoline_cache(), + }; - Ok(self.resolver) + Ok((self.resolver, backend_cache)) } } +unsafe impl Sync for FuncResolver {} +unsafe impl Send for FuncResolver {} + /// Resolves a function index to a function address. pub struct FuncResolver { map: Map, - memory: Memory, + pub(crate) memory: Arc>, } impl FuncResolver { fn lookup(&self, local_func_index: LocalFuncIndex) -> Option> { let offset = *self.map.get(local_func_index)?; - let ptr = unsafe { self.memory.as_ptr().add(offset) }; + let ptr = unsafe { (*self.memory.get()).as_ptr().add(offset) }; NonNull::new(ptr).map(|nonnull| nonnull.cast()) } diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index 1468d99eb..bedcff87a 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -40,11 +40,11 @@ impl UserTrapper for Trapper { pub struct Caller { func_export_set: HashSet, handler_data: HandlerData, - trampolines: Trampolines, + trampolines: Arc, } impl Caller { - pub fn new(module: &ModuleInfo, handler_data: HandlerData, trampolines: Trampolines) -> 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 { @@ -187,15 +187,16 @@ fn get_func_from_index( unsafe impl Send for HandlerData {} unsafe impl Sync for HandlerData {} +#[derive(Clone)] pub struct HandlerData { - pub trap_data: TrapSink, + pub trap_data: Arc, exec_buffer_ptr: *const c_void, exec_buffer_size: usize, } impl HandlerData { pub fn new( - trap_data: TrapSink, + trap_data: Arc, exec_buffer_ptr: *const c_void, exec_buffer_size: usize, ) -> Self { diff --git a/lib/clif-backend/src/trampoline.rs b/lib/clif-backend/src/trampoline.rs index 76fb521d6..492314c14 100644 --- a/lib/clif-backend/src/trampoline.rs +++ b/lib/clif-backend/src/trampoline.rs @@ -58,7 +58,7 @@ impl Trampolines { } #[cfg(feature = "cache")] - pub fn to_trampoline_cache(self) -> TrampolineCache { + pub fn to_trampoline_cache(&self) -> TrampolineCache { let mut code = vec![0; self.memory.size()]; unsafe { @@ -67,7 +67,7 @@ impl Trampolines { TrampolineCache { code, - offsets: self.offsets, + offsets: self.offsets.clone(), } } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index 328e3c826..769281ff2 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -45,13 +45,6 @@ pub trait Compiler { #[cfg(feature = "cache")] unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result; - - #[cfg(feature = "cache")] - fn compile_to_backend_cache_data( - &self, - wasm: &[u8], - _: Token, - ) -> CompileResult<(Box, Vec, Memory)>; } /// The functionality exposed by this trait is expected to be used @@ -101,5 +94,5 @@ pub trait FuncResolver: Send + Sync { } pub trait CacheGen: Send + Sync { - fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Memory), CacheError>; + fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Arc), CacheError>; } \ No newline at end of file diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index d130b8899..6edc85e9b 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -90,17 +90,17 @@ pub fn validate(wasm: &[u8]) -> bool { } } -#[cfg(feature = "cache")] -pub fn compile_to_cache_with( - wasm: &[u8], - compiler: &dyn backend::Compiler, -) -> CompileResult { - let token = backend::Token::generate(); - let (info, backend_metadata, compiled_code) = - compiler.compile_to_backend_cache_data(wasm, token)?; +// #[cfg(feature = "cache")] +// pub fn compile_to_cache_with( +// wasm: &[u8], +// compiler: &dyn backend::Compiler, +// ) -> CompileResult { +// let token = backend::Token::generate(); +// let (info, backend_metadata, compiled_code) = +// compiler.compile_to_backend_cache_data(wasm, token)?; - Ok(Cache::new(wasm, info, backend_metadata, compiled_code)) -} +// Ok(Cache::new(wasm, info, backend_metadata, compiled_code)) +// } #[cfg(feature = "cache")] pub unsafe fn load_cache_with( diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index aca3fc221..2a398d53e 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -1,5 +1,5 @@ use crate::{ - backend::{Backend, FuncResolver, ProtectedCaller}, + backend::{Backend, FuncResolver, ProtectedCaller, CacheGen}, error::Result, import::ImportObject, structures::{Map, TypedIndex}, @@ -21,10 +21,12 @@ use std::sync::Arc; pub struct ModuleInner { pub func_resolver: Box, pub protected_caller: Box, + pub cache_gen: Box, pub info: ModuleInfo, } +#[derive(Clone)] #[cfg_attr(feature = "cache", derive(Serialize, Deserialize))] pub struct ModuleInfo { // This are strictly local and the typsystem ensures that. diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index abea76db8..79d18255a 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -494,7 +494,8 @@ mod vm_ctx_tests { fn generate_module() -> ModuleInner { use super::Func; - use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper}; + use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper, CacheGen, sys::Memory}; + use crate::cache::Error as CacheError; use crate::error::RuntimeResult; use crate::types::{FuncIndex, LocalFuncIndex, Value}; use crate::module::WasmHash; @@ -526,10 +527,17 @@ mod vm_ctx_tests { unimplemented!() } } + impl CacheGen for Placeholder { + fn generate_cache(&self, module: &ModuleInner) -> Result<(Box, Box<[u8]>, Memory), CacheError> { + unimplemented!() + } + } + ModuleInner { func_resolver: Box::new(Placeholder), protected_caller: Box::new(Placeholder), + cache_gen: Box::new(Placeholder), info: ModuleInfo { memories: Map::new(), globals: Map::new(),