mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 08:10:49 +00:00
Get caching working again
This commit is contained in:
parent
82eea00a02
commit
9f40eedba8
@ -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<Memory>) -> Self {
|
||||
Self { backend_cache, memory }
|
||||
Self {
|
||||
backend_cache,
|
||||
memory,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CacheGen for CacheGenerator {
|
||||
fn generate_cache(&self, module: &ModuleInner) -> Result<(Box<ModuleInfo>, Box<[u8]>, Arc<Memory>), Error> {
|
||||
fn generate_cache(
|
||||
&self,
|
||||
module: &ModuleInner,
|
||||
) -> Result<(Box<ModuleInfo>, 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))
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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<ModuleInner, CacheError> {
|
||||
module::Module::from_cache(cache)
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// fn compile_to_backend_cache_data(
|
||||
// &self,
|
||||
// wasm: &[u8],
|
||||
|
@ -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<ModuleInner, CacheError> {
|
||||
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,
|
||||
})
|
||||
|
@ -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,
|
||||
|
@ -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<LocalFuncIndex, usize>, memory: &Memory, local_func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
|
||||
fn lookup_func(
|
||||
map: &SliceMap<LocalFuncIndex, usize>,
|
||||
memory: &Memory,
|
||||
local_func_index: LocalFuncIndex,
|
||||
) -> Option<NonNull<vm::Func>> {
|
||||
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,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,11 @@ pub struct Caller {
|
||||
}
|
||||
|
||||
impl Caller {
|
||||
pub fn new(module: &ModuleInfo, handler_data: HandlerData, trampolines: Arc<Trampolines>) -> Self {
|
||||
pub fn new(
|
||||
module: &ModuleInfo,
|
||||
handler_data: HandlerData,
|
||||
trampolines: Arc<Trampolines>,
|
||||
) -> Self {
|
||||
let mut func_export_set = HashSet::new();
|
||||
for export_index in module.exports.values() {
|
||||
if let ExportIndex::Func(func_index) = export_index {
|
||||
|
@ -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()];
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<u32>) {
|
||||
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<Pages>) {
|
||||
let (_, memory) = &module.0.info.imported_memories[ImportedMemoryIndex::new(0)];
|
||||
let (_, memory) = &module.info().imported_memories[ImportedMemoryIndex::new(0)];
|
||||
(memory.minimum, memory.maximum)
|
||||
}
|
||||
|
||||
|
@ -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<ModuleInner>;
|
||||
|
||||
|
||||
unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result<ModuleInner, CacheError>;
|
||||
}
|
||||
|
||||
@ -95,7 +93,9 @@ pub trait FuncResolver: Send + Sync {
|
||||
) -> Option<NonNull<vm::Func>>;
|
||||
}
|
||||
|
||||
|
||||
pub trait CacheGen: Send + Sync {
|
||||
fn generate_cache(&self, module: &ModuleInner) -> Result<(Box<ModuleInfo>, Box<[u8]>, Arc<Memory>), CacheError>;
|
||||
}
|
||||
fn generate_cache(
|
||||
&self,
|
||||
module: &ModuleInner,
|
||||
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError>;
|
||||
}
|
||||
|
@ -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<ModuleInfo>,
|
||||
#[serde(with = "serde_bytes")]
|
||||
backend_metadata: Box<[u8]>,
|
||||
compiled_code: Arc<Memory>,
|
||||
compiled_code: Memory,
|
||||
}
|
||||
|
||||
pub struct Cache {
|
||||
@ -80,7 +80,7 @@ impl Cache {
|
||||
pub(crate) fn from_parts(
|
||||
info: Box<ModuleInfo>,
|
||||
backend_metadata: Box<[u8]>,
|
||||
compiled_code: Arc<Memory>,
|
||||
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<Memory>) {
|
||||
pub fn consume(self) -> (ModuleInfo, Box<[u8]>, Memory) {
|
||||
(
|
||||
*self.inner.info,
|
||||
self.inner.backend_metadata,
|
||||
|
@ -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,
|
||||
|
@ -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<dyn FuncResolver>,
|
||||
pub protected_caller: Box<dyn ProtectedCaller>,
|
||||
|
||||
|
||||
pub cache_gen: Box<dyn CacheGen>,
|
||||
|
||||
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<LocalMemoryIndex, MemoryDescriptor>,
|
||||
@ -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<Cache, CacheError> {
|
||||
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<K: TypedIndex> StringTableBuilder<K> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct StringTable<K: TypedIndex> {
|
||||
table: Map<K, (u32, u32)>,
|
||||
buffer: String,
|
||||
@ -249,8 +243,7 @@ impl<K: TypedIndex> StringTable<K> {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
|
@ -8,8 +8,7 @@ use std::{
|
||||
};
|
||||
|
||||
/// Dense item map
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Map<K, V>
|
||||
where
|
||||
K: TypedIndex,
|
||||
|
@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -36,7 +34,6 @@ impl Serialize for Memory {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'de> Deserialize<'de> for Memory {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)]
|
||||
|
@ -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 {
|
||||
|
@ -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<ModuleInfo>, Box<[u8]>, Memory), CacheError> {
|
||||
fn generate_cache(
|
||||
&self,
|
||||
module: &ModuleInner,
|
||||
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ModuleInner {
|
||||
func_resolver: Box::new(Placeholder),
|
||||
|
Loading…
x
Reference in New Issue
Block a user