Use ModuleInfo instead of ModuleInner when possible

This commit is contained in:
Lachlan Sneff
2019-02-18 11:56:20 -08:00
parent 7602071e1a
commit e381bbd07b
14 changed files with 252 additions and 276 deletions

View File

@ -75,7 +75,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
let ptr_type = self.pointer_type(); let ptr_type = self.pointer_type();
let local_global_addr = match global_index.local_or_import(self.env.module) { let local_global_addr = match global_index.local_or_import(&self.env.module.info) {
LocalOrImport::Local(local_global_index) => { LocalOrImport::Local(local_global_index) => {
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load { let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
base: vmctx, base: vmctx,
@ -145,7 +145,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
let ptr_type = self.pointer_type(); let ptr_type = self.pointer_type();
let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(self.env.module) { let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(&self.env.module.info) {
LocalOrImport::Local(local_mem_index) => { LocalOrImport::Local(local_mem_index) => {
let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load {
base: vmctx, base: vmctx,
@ -253,7 +253,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
let ptr_type = self.pointer_type(); let ptr_type = self.pointer_type();
let (table_struct_ptr_ptr, description) = match table_index.local_or_import(self.env.module) let (table_struct_ptr_ptr, description) = match table_index.local_or_import(&self.env.module.info)
{ {
LocalOrImport::Local(local_table_index) => { LocalOrImport::Local(local_table_index) => {
let tables_base = func.create_global_value(ir::GlobalValueData::Load { let tables_base = func.create_global_value(ir::GlobalValueData::Load {
@ -476,7 +476,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
) -> cranelift_wasm::WasmResult<ir::Inst> { ) -> cranelift_wasm::WasmResult<ir::Inst> {
let callee_index: FuncIndex = Converter(clif_callee_index).into(); let callee_index: FuncIndex = Converter(clif_callee_index).into();
match callee_index.local_or_import(self.env.module) { match callee_index.local_or_import(&self.env.module.info) {
LocalOrImport::Local(_) => { LocalOrImport::Local(_) => {
// this is an internal function // this is an internal function
let vmctx = pos let vmctx = pos
@ -568,7 +568,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
let mem_index: MemoryIndex = Converter(clif_mem_index).into(); let mem_index: MemoryIndex = Converter(clif_mem_index).into();
let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) { let (namespace, mem_index, description) = match mem_index.local_or_import(&self.env.module.info) {
LocalOrImport::Local(local_mem_index) => ( LocalOrImport::Local(local_mem_index) => (
call_names::LOCAL_NAMESPACE, call_names::LOCAL_NAMESPACE,
local_mem_index.index(), local_mem_index.index(),
@ -631,7 +631,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
let mem_index: MemoryIndex = Converter(clif_mem_index).into(); let mem_index: MemoryIndex = Converter(clif_mem_index).into();
let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) { let (namespace, mem_index, description) = match mem_index.local_or_import(&self.env.module.info) {
LocalOrImport::Local(local_mem_index) => ( LocalOrImport::Local(local_mem_index) => (
call_names::LOCAL_NAMESPACE, call_names::LOCAL_NAMESPACE,
local_mem_index.index(), local_mem_index.index(),

View File

@ -48,7 +48,7 @@ impl Compiler for CraneliftCompiler {
let isa = get_isa(); let isa = get_isa();
let mut module = module::Module::empty(); let mut module = module::Module::new(wasm);
let module_env = module_env::ModuleEnv::new(&mut module, &*isa); let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
let func_bodies = module_env.translate(wasm)?; let func_bodies = module_env.translate(wasm)?;
@ -72,7 +72,7 @@ impl Compiler for CraneliftCompiler {
let isa = get_isa(); let isa = get_isa();
let mut module = module::Module::empty(); let mut module = module::Module::new(wasm);
let module_env = module_env::ModuleEnv::new(&mut module, &*isa); let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
let func_bodies = module_env.translate(wasm)?; let func_bodies = module_env.translate(wasm)?;

View File

@ -6,70 +6,31 @@ use cranelift_codegen::{ir, isa};
use cranelift_entity::EntityRef; use cranelift_entity::EntityRef;
use cranelift_wasm; use cranelift_wasm;
use hashbrown::HashMap; use hashbrown::HashMap;
use std::{
ops::{Deref, DerefMut},
ptr::NonNull,
};
#[cfg(feature = "cache")] #[cfg(feature = "cache")]
use wasmer_runtime_core::{ use wasmer_runtime_core::{
backend::sys::Memory, backend::sys::Memory,
cache::{Cache, Error as CacheError}, cache::{Cache, Error as CacheError},
}; };
use wasmer_runtime_core::{ use wasmer_runtime_core::{
backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper}, backend::Backend,
error::{CompileResult, RuntimeResult}, error::CompileResult,
module::{ModuleInfo, ModuleInner, StringTable}, module::{ModuleInfo, ModuleInner, StringTable, WasmHash},
structures::{Map, TypedIndex}, structures::{Map, TypedIndex},
types::{ types::{
FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type, FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type,
Value,
}, },
vm::{self, ImportBacking},
}; };
struct Placeholder;
impl FuncResolver for Placeholder {
fn get(
&self,
_module: &ModuleInner,
_local_func_index: LocalFuncIndex,
) -> Option<NonNull<vm::Func>> {
None
}
}
impl ProtectedCaller for Placeholder {
fn call(
&self,
_module: &ModuleInner,
_func_index: FuncIndex,
_params: &[Value],
_import_backing: &ImportBacking,
_vmctx: *mut vm::Ctx,
_: Token,
) -> RuntimeResult<Vec<Value>> {
Ok(vec![])
}
fn get_early_trapper(&self) -> Box<dyn UserTrapper> {
unimplemented!()
}
}
/// This contains all of the items in a `ModuleInner` except the `func_resolver`. /// This contains all of the items in a `ModuleInner` except the `func_resolver`.
pub struct Module { pub struct Module {
pub module: ModuleInner, pub info: ModuleInfo,
} }
impl Module { impl Module {
pub fn empty() -> Self { pub fn new(wasm: &[u8]) -> Self {
Self { Self {
module: ModuleInner {
// this is a placeholder
func_resolver: Box::new(Placeholder),
protected_caller: Box::new(Placeholder),
info: ModuleInfo { info: ModuleInfo {
memories: Map::new(), memories: Map::new(),
globals: Map::new(), globals: Map::new(),
@ -93,28 +54,35 @@ impl Module {
namespace_table: StringTable::new(), namespace_table: StringTable::new(),
name_table: StringTable::new(), name_table: StringTable::new(),
},
wasm_hash: WasmHash::generate(wasm),
}, },
} }
} }
pub fn compile( pub fn compile(
mut self, self,
isa: &isa::TargetIsa, isa: &isa::TargetIsa,
functions: Map<LocalFuncIndex, ir::Function>, functions: Map<LocalFuncIndex, ir::Function>,
) -> CompileResult<ModuleInner> { ) -> CompileResult<ModuleInner> {
let (func_resolver_builder, handler_data) = let (func_resolver_builder, handler_data) =
FuncResolverBuilder::new(isa, functions, &self.module.info)?; FuncResolverBuilder::new(isa, functions, &self.info)?;
self.module.func_resolver =
Box::new(func_resolver_builder.finalize(&self.module.info.signatures)?);
let trampolines = Trampolines::new(isa, &self.module.info); let func_resolver =
Box::new(func_resolver_builder.finalize(&self.info.signatures)?);
self.module.protected_caller = let trampolines = Trampolines::new(isa, &self.info);
Box::new(Caller::new(&self.module.info, handler_data, trampolines));
Ok(self.module) let protected_caller =
Box::new(Caller::new(&self.info, handler_data, trampolines));
Ok(ModuleInner {
func_resolver,
protected_caller,
info: self.info,
})
} }
#[cfg(feature = "cache")] #[cfg(feature = "cache")]
@ -124,16 +92,16 @@ impl Module {
functions: Map<LocalFuncIndex, ir::Function>, functions: Map<LocalFuncIndex, ir::Function>,
) -> CompileResult<(ModuleInfo, BackendCache, Memory)> { ) -> CompileResult<(ModuleInfo, BackendCache, Memory)> {
let (func_resolver_builder, handler_data) = let (func_resolver_builder, handler_data) =
FuncResolverBuilder::new(isa, functions, &self.module.info)?; FuncResolverBuilder::new(isa, functions, &self.info)?;
let trampolines = Trampolines::new(isa, &self.module.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) = let (backend_cache, compiled_code) =
func_resolver_builder.to_backend_cache(trampoline_cache, handler_data); func_resolver_builder.to_backend_cache(trampoline_cache, handler_data);
Ok((self.module.info, backend_cache, compiled_code)) Ok((self.info, backend_cache, compiled_code))
} }
#[cfg(feature = "cache")] #[cfg(feature = "cache")]
@ -159,20 +127,6 @@ impl Module {
} }
} }
impl Deref for Module {
type Target = ModuleInner;
fn deref(&self) -> &ModuleInner {
&self.module
}
}
impl DerefMut for Module {
fn deref_mut(&mut self) -> &mut ModuleInner {
&mut self.module
}
}
pub struct Converter<T>(pub T); pub struct Converter<T>(pub T);
macro_rules! convert_clif_to_runtime_index { macro_rules! convert_clif_to_runtime_index {

View File

@ -139,7 +139,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
// assert!(!desc.mutable); // assert!(!desc.mutable);
let global_index: GlobalIndex = Converter(global_index).into(); let global_index: GlobalIndex = Converter(global_index).into();
let imported_global_index = global_index let imported_global_index = global_index
.local_or_import(self.module) .local_or_import(&self.module.info)
.import() .import()
.expect("invalid global initializer when declaring an imported global"); .expect("invalid global initializer when declaring an imported global");
Initializer::GetGlobal(imported_global_index) Initializer::GetGlobal(imported_global_index)
@ -249,7 +249,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
let base = match base { let base = match base {
Some(global_index) => { Some(global_index) => {
let global_index: GlobalIndex = Converter(global_index).into(); let global_index: GlobalIndex = Converter(global_index).into();
Initializer::GetGlobal(match global_index.local_or_import(self.module) { Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) {
LocalOrImport::Import(imported_global_index) => imported_global_index, LocalOrImport::Import(imported_global_index) => imported_global_index,
LocalOrImport::Local(_) => { LocalOrImport::Local(_) => {
panic!("invalid global initializer when declaring an imported global") panic!("invalid global initializer when declaring an imported global")
@ -319,7 +319,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
let base = match base { let base = match base {
Some(global_index) => { Some(global_index) => {
let global_index: GlobalIndex = Converter(global_index).into(); let global_index: GlobalIndex = Converter(global_index).into();
Initializer::GetGlobal(match global_index.local_or_import(self.module) { Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) {
LocalOrImport::Import(imported_global_index) => imported_global_index, LocalOrImport::Import(imported_global_index) => imported_global_index,
LocalOrImport::Local(_) => { LocalOrImport::Local(_) => {
panic!("invalid global initializer when declaring an imported global") panic!("invalid global initializer when declaring an imported global")
@ -389,7 +389,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
let name = ir::ExternalName::user(0, func_index.index() as u32); let name = ir::ExternalName::user(0, func_index.index() as u32);
let sig = func_env.generate_signature( let sig = func_env.generate_signature(
self.get_func_type(Converter(func_index.convert_up(self.module)).into()), self.get_func_type(Converter(func_index.convert_up(&self.module.info)).into()),
); );
let mut func = ir::Function::with_name_signature(name, sig); let mut func = ir::Function::with_name_signature(name, sig);

View File

@ -160,7 +160,7 @@ fn get_func_from_index(
.get(func_index) .get(func_index)
.expect("broken invariant, incorrect func index"); .expect("broken invariant, incorrect func index");
let (func_ptr, ctx) = match func_index.local_or_import(module) { let (func_ptr, ctx) = match func_index.local_or_import(&module.info) {
LocalOrImport::Local(local_func_index) => ( LocalOrImport::Local(local_func_index) => (
module module
.func_resolver .func_resolver

View File

@ -99,3 +99,7 @@ pub trait FuncResolver: Send + Sync {
local_func_index: LocalFuncIndex, local_func_index: LocalFuncIndex,
) -> Option<NonNull<vm::Func>>; ) -> Option<NonNull<vm::Func>>;
} }
pub trait CacheGen: Send + Sync {
fn generate_cache(&self, module: &ModuleInner) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError>;
}

View File

@ -91,7 +91,7 @@ impl LocalBacking {
} }
} as usize; } as usize;
match init.memory_index.local_or_import(module) { match init.memory_index.local_or_import(&module.info) {
LocalOrImport::Local(local_memory_index) => { LocalOrImport::Local(local_memory_index) => {
let memory_desc = module.info.memories[local_memory_index]; let memory_desc = module.info.memories[local_memory_index];
let data_top = init_base + init.data.len(); let data_top = init_base + init.data.len();
@ -159,7 +159,7 @@ impl LocalBacking {
} }
} as usize; } as usize;
match init.table_index.local_or_import(module) { match init.table_index.local_or_import(&module.info) {
LocalOrImport::Local(local_table_index) => { LocalOrImport::Local(local_table_index) => {
let table = &tables[local_table_index]; let table = &tables[local_table_index];
@ -177,7 +177,7 @@ impl LocalBacking {
SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32, SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32,
); );
let (func, ctx) = match func_index.local_or_import(module) { let (func, ctx) = match func_index.local_or_import(&module.info) {
LocalOrImport::Local(local_func_index) => ( LocalOrImport::Local(local_func_index) => (
module module
.func_resolver .func_resolver
@ -215,7 +215,7 @@ impl LocalBacking {
SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32, SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32,
); );
let (func, ctx) = match func_index.local_or_import(module) { let (func, ctx) = match func_index.local_or_import(&module.info) {
LocalOrImport::Local(local_func_index) => ( LocalOrImport::Local(local_func_index) => (
module module
.func_resolver .func_resolver
@ -364,7 +364,7 @@ fn import_functions(
}, },
) in &module.info.imported_functions ) in &module.info.imported_functions
{ {
let sig_index = module.info.func_assoc[index.convert_up(module)]; let sig_index = module.info.func_assoc[index.convert_up(&module.info)];
let expected_sig = &module.info.signatures[sig_index]; let expected_sig = &module.info.signatures[sig_index];
let namespace = module.info.namespace_table.get(*namespace_index); let namespace = module.info.namespace_table.get(*namespace_index);

View File

@ -121,14 +121,14 @@ impl Instance {
})?; })?;
} }
let ctx = match func_index.local_or_import(&*self.module) { let ctx = match func_index.local_or_import(&self.module.info) {
LocalOrImport::Local(_) => self.inner.vmctx, LocalOrImport::Local(_) => self.inner.vmctx,
LocalOrImport::Import(imported_func_index) => { LocalOrImport::Import(imported_func_index) => {
self.inner.import_backing.vm_functions[imported_func_index].vmctx self.inner.import_backing.vm_functions[imported_func_index].vmctx
} }
}; };
let func_ptr = match func_index.local_or_import(&self.module) { let func_ptr = match func_index.local_or_import(&self.module.info) {
LocalOrImport::Local(local_func_index) => self LocalOrImport::Local(local_func_index) => self
.module .module
.func_resolver .func_resolver
@ -288,7 +288,7 @@ impl Instance {
})? })?
} }
let vmctx = match func_index.local_or_import(&self.module) { let vmctx = match func_index.local_or_import(&self.module.info) {
LocalOrImport::Local(_) => self.inner.vmctx, LocalOrImport::Local(_) => self.inner.vmctx,
LocalOrImport::Import(imported_func_index) => { LocalOrImport::Import(imported_func_index) => {
self.inner.import_backing.vm_functions[imported_func_index].vmctx self.inner.import_backing.vm_functions[imported_func_index].vmctx
@ -355,7 +355,7 @@ impl InstanceInner {
.get(func_index) .get(func_index)
.expect("broken invariant, incorrect func index"); .expect("broken invariant, incorrect func index");
let (func_ptr, ctx) = match func_index.local_or_import(module) { let (func_ptr, ctx) = match func_index.local_or_import(&module.info) {
LocalOrImport::Local(local_func_index) => ( LocalOrImport::Local(local_func_index) => (
module module
.func_resolver .func_resolver
@ -384,7 +384,7 @@ impl InstanceInner {
} }
fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory { fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory {
match mem_index.local_or_import(module) { match mem_index.local_or_import(&module.info) {
LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(), LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(),
LocalOrImport::Import(imported_mem_index) => { LocalOrImport::Import(imported_mem_index) => {
self.import_backing.memories[imported_mem_index].clone() self.import_backing.memories[imported_mem_index].clone()
@ -393,7 +393,7 @@ impl InstanceInner {
} }
fn get_global_from_index(&self, module: &ModuleInner, global_index: GlobalIndex) -> Global { fn get_global_from_index(&self, module: &ModuleInner, global_index: GlobalIndex) -> Global {
match global_index.local_or_import(module) { match global_index.local_or_import(&module.info) {
LocalOrImport::Local(local_global_index) => { LocalOrImport::Local(local_global_index) => {
self.backing.globals[local_global_index].clone() self.backing.globals[local_global_index].clone()
} }
@ -404,7 +404,7 @@ impl InstanceInner {
} }
fn get_table_from_index(&self, module: &ModuleInner, table_index: TableIndex) -> Table { fn get_table_from_index(&self, module: &ModuleInner, table_index: TableIndex) -> Table {
match table_index.local_or_import(module) { match table_index.local_or_import(&module.info) {
LocalOrImport::Local(local_table_index) => { LocalOrImport::Local(local_table_index) => {
self.backing.tables[local_table_index].clone() self.backing.tables[local_table_index].clone()
} }
@ -462,7 +462,7 @@ impl<'a> DynFunc<'a> {
})? })?
} }
let vmctx = match self.func_index.local_or_import(self.module) { let vmctx = match self.func_index.local_or_import(&self.module.info) {
LocalOrImport::Local(_) => self.instance_inner.vmctx, LocalOrImport::Local(_) => self.instance_inner.vmctx,
LocalOrImport::Import(imported_func_index) => { LocalOrImport::Import(imported_func_index) => {
self.instance_inner.import_backing.vm_functions[imported_func_index].vmctx self.instance_inner.import_backing.vm_functions[imported_func_index].vmctx
@ -488,7 +488,7 @@ impl<'a> DynFunc<'a> {
} }
pub fn raw(&self) -> *const vm::Func { pub fn raw(&self) -> *const vm::Func {
match self.func_index.local_or_import(self.module) { match self.func_index.local_or_import(&self.module.info) {
LocalOrImport::Local(local_func_index) => self LocalOrImport::Local(local_func_index) => self
.module .module
.func_resolver .func_resolver

View File

@ -51,6 +51,18 @@ pub struct ModuleInfo {
pub namespace_table: StringTable<NamespaceIndex>, pub namespace_table: StringTable<NamespaceIndex>,
pub name_table: StringTable<NameIndex>, pub name_table: StringTable<NameIndex>,
pub wasm_hash: WasmHash,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "cache", derive(Serialize, Deserialize))]
pub struct WasmHash([u8; 32]);
impl WasmHash {
pub fn generate(wasm: &[u8]) -> Self {
WasmHash(super::cache::hash_data(wasm))
}
} }
/// A compiled WebAssembly module. /// A compiled WebAssembly module.
@ -60,7 +72,9 @@ pub struct ModuleInfo {
/// ///
/// [`compile`]: fn.compile.html /// [`compile`]: fn.compile.html
/// [`compile_with`]: fn.compile_with.html /// [`compile_with`]: fn.compile_with.html
pub struct Module(#[doc(hidden)] pub Arc<ModuleInner>); pub struct Module {
inner: Arc<ModuleInner>,
}
impl Module { impl Module {
pub(crate) fn new(inner: Arc<ModuleInner>) -> Self { pub(crate) fn new(inner: Arc<ModuleInner>) -> Self {
@ -68,7 +82,7 @@ impl Module {
EARLY_TRAPPER EARLY_TRAPPER
.with(|ucell| *ucell.get() = Some(inner.protected_caller.get_early_trapper())); .with(|ucell| *ucell.get() = Some(inner.protected_caller.get_early_trapper()));
} }
Module(inner) Module { inner }
} }
/// Instantiate a WebAssembly module with the provided [`ImportObject`]. /// Instantiate a WebAssembly module with the provided [`ImportObject`].
@ -94,7 +108,7 @@ impl Module {
/// # } /// # }
/// ``` /// ```
pub fn instantiate(&self, import_object: &ImportObject) -> Result<Instance> { pub fn instantiate(&self, import_object: &ImportObject) -> Result<Instance> {
Instance::new(Arc::clone(&self.0), import_object) Instance::new(Arc::clone(&self.inner), import_object)
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{memory::MemoryType, module::ModuleInner, structures::TypedIndex, units::Pages}; use crate::{memory::MemoryType, module::ModuleInfo, structures::TypedIndex, units::Pages};
use std::{borrow::Cow, mem}; use std::{borrow::Cow, mem};
/// Represents a WebAssembly type. /// Represents a WebAssembly type.
@ -364,23 +364,23 @@ define_map_index![
macro_rules! define_local_or_import { macro_rules! define_local_or_import {
($ty:ident, $local_ty:ident, $imported_ty:ident, $imports:ident) => { ($ty:ident, $local_ty:ident, $imported_ty:ident, $imports:ident) => {
impl $ty { impl $ty {
pub fn local_or_import(self, module: &ModuleInner) -> LocalOrImport<$ty> { pub fn local_or_import(self, info: &ModuleInfo) -> LocalOrImport<$ty> {
if self.index() < module.info.$imports.len() { if self.index() < info.$imports.len() {
LocalOrImport::Import(<Self as LocalImport>::Import::new(self.index())) LocalOrImport::Import(<Self as LocalImport>::Import::new(self.index()))
} else { } else {
LocalOrImport::Local(<Self as LocalImport>::Local::new(self.index() - module.info.$imports.len())) LocalOrImport::Local(<Self as LocalImport>::Local::new(self.index() - info.$imports.len()))
} }
} }
} }
impl $local_ty { impl $local_ty {
pub fn convert_up(self, module: &ModuleInner) -> $ty { pub fn convert_up(self, info: &ModuleInfo) -> $ty {
$ty ((self.index() + module.info.$imports.len()) as u32) $ty ((self.index() + info.$imports.len()) as u32)
} }
} }
impl $imported_ty { impl $imported_ty {
pub fn convert_up(self, _module: &ModuleInner) -> $ty { pub fn convert_up(self, _info: &ModuleInfo) -> $ty {
$ty (self.index() as u32) $ty (self.index() as u32)
} }
} }

View File

@ -116,7 +116,7 @@ impl Ctx {
pub fn memory(&self, mem_index: u32) -> &Memory { pub fn memory(&self, mem_index: u32) -> &Memory {
let module = unsafe { &*self.module }; let module = unsafe { &*self.module };
let mem_index = MemoryIndex::new(mem_index as usize); let mem_index = MemoryIndex::new(mem_index as usize);
match mem_index.local_or_import(module) { match mem_index.local_or_import(&module.info) {
LocalOrImport::Local(local_mem_index) => unsafe { LocalOrImport::Local(local_mem_index) => unsafe {
let local_backing = &*self.local_backing; let local_backing = &*self.local_backing;
&local_backing.memories[local_mem_index] &local_backing.memories[local_mem_index]
@ -497,6 +497,7 @@ mod vm_ctx_tests {
use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper}; use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper};
use crate::error::RuntimeResult; use crate::error::RuntimeResult;
use crate::types::{FuncIndex, LocalFuncIndex, Value}; use crate::types::{FuncIndex, LocalFuncIndex, Value};
use crate::module::WasmHash;
use hashbrown::HashMap; use hashbrown::HashMap;
use std::ptr::NonNull; use std::ptr::NonNull;
struct Placeholder; struct Placeholder;
@ -553,6 +554,8 @@ mod vm_ctx_tests {
namespace_table: StringTable::new(), namespace_table: StringTable::new(),
name_table: StringTable::new(), name_table: StringTable::new(),
wasm_hash: WasmHash::generate(&[]),
}, },
} }
} }

View File

@ -10,11 +10,9 @@ readme = "README.md"
[dependencies] [dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" }
wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2", optional = true } wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2" }
lazy_static = "1.2.0" lazy_static = "1.2.0"
[features] [features]
default = ["default-compiler", "cache"] default = ["wasmer-clif-backend/cache", "wasmer-runtime-core/cache"]
default-compiler = ["wasmer-clif-backend/cache", "wasmer-runtime-core/cache"]
cache = ["default-compiler"]
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]

View File

@ -1,128 +1,139 @@
use crate::Module; use crate::Module;
use std::path::Path; use std::path::Path;
use wasmer_runtime_core::cache::{hash_data, Cache as CoreCache}; use wasmer_runtime_core::cache::{hash_data, Cache as CoreCache};
use wasmer_runtime_core::module::{WasmHash};
pub use wasmer_runtime_core::cache::Error; pub use wasmer_runtime_core::cache::Error;
/// On-disk storage of compiled WebAssembly. // /// On-disk storage of compiled WebAssembly.
/// // ///
/// A `Cache` can be used to quickly reload already // /// A `Cache` can be used to quickly reload already
/// compiled WebAssembly from a previous execution // /// compiled WebAssembly from a previous execution
/// during which the wasm was explicitly compiled // /// during which the wasm was explicitly compiled
/// as a `Cache`. // /// as a `Cache`.
/// // ///
/// # Usage: // /// # Usage:
/// // ///
/// ``` // /// ```
/// use wasmer_runtime::{compile_cache, Cache}; // /// use wasmer_runtime::{compile_cache, Cache};
/// // ///
/// # use wasmer_runtime::error::{CompileResult, CacheError}; // /// # use wasmer_runtime::error::{CompileResult, CacheError};
/// # fn make_cache(wasm: &[u8]) -> CompileResult<()> { // /// # fn make_cache(wasm: &[u8]) -> CompileResult<()> {
/// // Make a cache. // /// // Make a cache.
/// let cache = compile_cache(wasm)?; // /// let cache = compile_cache(wasm)?;
/// // ///
/// # Ok(()) // /// # Ok(())
/// # } // /// # }
/// # fn usage_cache(cache: Cache) -> Result<(), CacheError> { // /// # fn usage_cache(cache: Cache) -> Result<(), CacheError> {
/// // Store the cache in a file. // /// // Store the cache in a file.
/// cache.store("some_cache_file")?; // /// cache.store("some_cache_file")?;
/// // ///
/// // Load the cache. // /// // Load the cache.
/// let cache = Cache::load("some_cache_file")?; // /// let cache = Cache::load("some_cache_file")?;
/// let module = unsafe { cache.into_module()? }; // /// let module = unsafe { cache.into_module()? };
/// # Ok(()) // /// # Ok(())
/// # } // /// # }
/// ``` // /// ```
/// // ///
/// # Performance Characteristics: // /// # Performance Characteristics:
/// // ///
/// Loading caches from files has been optimized for latency. // /// Loading caches from files has been optimized for latency.
/// There is still more work to do that will reduce // /// There is still more work to do that will reduce
/// loading time, especially for very large modules, // /// loading time, especially for very large modules,
/// but it will require signifigant internal work. // /// but it will require signifigant internal work.
/// // ///
/// # Drawbacks: // /// # Drawbacks:
/// // ///
/// Due to internal shortcomings, you cannot convert // /// Due to internal shortcomings, you cannot convert
/// a module into a `Cache`. This means that compiling // /// a module into a `Cache`. This means that compiling
/// into a `Cache` and then converting into a module // /// into a `Cache` and then converting into a module
/// has more overhead than directly compiling // /// has more overhead than directly compiling
/// into a [`Module`]. // /// into a [`Module`].
/// // ///
/// [`Module`]: struct.Module.html // /// [`Module`]: struct.Module.html
pub struct Cache(pub(crate) CoreCache); // pub struct Cache(pub(crate) CoreCache);
impl Cache { // impl Cache {
/// Load a `Cache` from the file specified by `path`. // /// Load a `Cache` from the file specified by `path`.
/// // ///
/// # Usage: // /// # Usage:
/// // ///
/// ``` // /// ```
/// use wasmer_runtime::Cache; // /// use wasmer_runtime::Cache;
/// # use wasmer_runtime::error::CacheError; // /// # use wasmer_runtime::error::CacheError;
/// // ///
/// # fn load_cache() -> Result<(), CacheError> { // /// # fn load_cache() -> Result<(), CacheError> {
/// let cache = Cache::load("some_file.cache")?; // /// let cache = Cache::load("some_file.cache")?;
/// # Ok(()) // /// # Ok(())
/// # } // /// # }
/// ``` // /// ```
pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, Error> { // pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
CoreCache::open(path).map(|core_cache| Cache(core_cache)) // CoreCache::open(path).map(|core_cache| Cache(core_cache))
} // }
/// Convert a `Cache` into a [`Module`]. // /// Convert a `Cache` into a [`Module`].
/// // ///
/// [`Module`]: struct.Module.html // /// [`Module`]: struct.Module.html
/// // ///
/// # Usage: // /// # Usage:
/// // ///
/// ``` // /// ```
/// use wasmer_runtime::Cache; // /// use wasmer_runtime::Cache;
/// // ///
/// # use wasmer_runtime::error::CacheError; // /// # use wasmer_runtime::error::CacheError;
/// # fn cache2module(cache: Cache) -> Result<(), CacheError> { // /// # fn cache2module(cache: Cache) -> Result<(), CacheError> {
/// let module = unsafe { cache.into_module()? }; // /// let module = unsafe { cache.into_module()? };
/// # Ok(()) // /// # Ok(())
/// # } // /// # }
/// ``` // /// ```
/// // ///
/// # Notes: // /// # Notes:
/// // ///
/// This method is unsafe because the runtime cannot confirm // /// This method is unsafe because the runtime cannot confirm
/// that this cache was not tampered with or corrupted. // /// that this cache was not tampered with or corrupted.
pub unsafe fn into_module(self) -> Result<Module, Error> { // pub unsafe fn into_module(self) -> Result<Module, Error> {
let default_compiler = super::default_compiler(); // let default_compiler = super::default_compiler();
wasmer_runtime_core::load_cache_with(self.0, default_compiler) // wasmer_runtime_core::load_cache_with(self.0, default_compiler)
} // }
/// Compare the Sha256 hash of the wasm this cache was build // /// Compare the Sha256 hash of the wasm this cache was build
/// from with some other WebAssembly. // /// from with some other WebAssembly.
/// // ///
/// The main use-case for this is invalidating old caches. // /// The main use-case for this is invalidating old caches.
pub fn compare_wasm(&self, wasm: &[u8]) -> bool { // pub fn compare_wasm(&self, wasm: &[u8]) -> bool {
let param_wasm_hash = hash_data(wasm); // let param_wasm_hash = hash_data(wasm);
self.0.wasm_hash() as &[u8] == &param_wasm_hash as &[u8] // self.0.wasm_hash() as &[u8] == &param_wasm_hash as &[u8]
} // }
/// Store this cache in a file. // /// Store this cache in a file.
/// // ///
/// # Notes: // /// # Notes:
/// // ///
/// If a file exists at the specified path, it will be overwritten. // /// If a file exists at the specified path, it will be overwritten.
/// // ///
/// # Usage: // /// # Usage:
/// // ///
/// ``` // /// ```
/// use wasmer_runtime::Cache; // /// use wasmer_runtime::Cache;
/// // ///
/// # use wasmer_runtime::error::CacheError; // /// # use wasmer_runtime::error::CacheError;
/// # fn store_cache(cache: Cache) -> Result<(), CacheError> { // /// # fn store_cache(cache: Cache) -> Result<(), CacheError> {
/// cache.store("some_file.cache")?; // /// cache.store("some_file.cache")?;
/// # Ok(()) // /// # Ok(())
/// # } // /// # }
/// ``` // /// ```
pub fn store<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> { // pub fn store<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
self.0.store(path) // self.0.store(path)
} // }
// }
pub trait Cache {
type Key;
type LoadError;
type StoreError;
unsafe fn load(&self, key: Self::Key) -> Result<Module, Self::LoadError>;
fn store(&mut self, module: Module) -> Result<Self::Key, Self::StoreError>;
} }

View File

@ -99,7 +99,6 @@ pub mod wasm {
} }
pub mod error { pub mod error {
#[cfg(feature = "cache")]
pub use super::cache::Error as CacheError; pub use super::cache::Error as CacheError;
pub use wasmer_runtime_core::error::*; pub use wasmer_runtime_core::error::*;
} }
@ -109,13 +108,10 @@ pub mod units {
pub use wasmer_runtime_core::units::{Bytes, Pages}; pub use wasmer_runtime_core::units::{Bytes, Pages};
} }
#[cfg(feature = "cache")]
mod cache; mod cache;
#[cfg(feature = "default-compiler")]
use wasmer_runtime_core::backend::Compiler; use wasmer_runtime_core::backend::Compiler;
#[cfg(feature = "cache")]
pub use self::cache::Cache; pub use self::cache::Cache;
/// Compile WebAssembly binary code into a [`Module`]. /// Compile WebAssembly binary code into a [`Module`].
@ -131,7 +127,6 @@ pub use self::cache::Cache;
/// binary code of the wasm module you want to compile. /// binary code of the wasm module you want to compile.
/// # Errors: /// # Errors:
/// If the operation fails, the function returns `Err(error::CompileError::...)`. /// If the operation fails, the function returns `Err(error::CompileError::...)`.
#[cfg(feature = "default-compiler")]
pub fn compile(wasm: &[u8]) -> error::CompileResult<Module> { pub fn compile(wasm: &[u8]) -> error::CompileResult<Module> {
wasmer_runtime_core::compile_with(&wasm[..], default_compiler()) wasmer_runtime_core::compile_with(&wasm[..], default_compiler())
} }
@ -154,38 +149,35 @@ pub fn compile(wasm: &[u8]) -> error::CompileResult<Module> {
/// `error::CompileError`, `error::LinkError`, or /// `error::CompileError`, `error::LinkError`, or
/// `error::RuntimeError` (all combined into an `error::Error`), /// `error::RuntimeError` (all combined into an `error::Error`),
/// depending on the cause of the failure. /// depending on the cause of the failure.
#[cfg(feature = "default-compiler")]
pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result<Instance> { pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result<Instance> {
let module = compile(wasm)?; let module = compile(wasm)?;
module.instantiate(import_object) module.instantiate(import_object)
} }
/// Compile wasm into a [`Cache`] that can be stored to a file or // /// Compile wasm into a [`Cache`] that can be stored to a file or
/// converted into [`Module`]. // /// converted into [`Module`].
/// // ///
/// [`Cache`]: struct.Cache.html // /// [`Cache`]: struct.Cache.html
/// [`Module`]: struct.Module.html // /// [`Module`]: struct.Module.html
/// // ///
/// # Usage: // /// # Usage:
/// // ///
/// ``` // /// ```
/// # use wasmer_runtime::error::CompileResult; // /// # use wasmer_runtime::error::CompileResult;
/// use wasmer_runtime::compile_cache; // /// use wasmer_runtime::compile_cache;
/// // ///
/// # fn make_cache(wasm: &[u8]) -> CompileResult<()> { // /// # fn make_cache(wasm: &[u8]) -> CompileResult<()> {
/// let cache = compile_cache(wasm)?; // /// let cache = compile_cache(wasm)?;
/// # Ok(()) // /// # Ok(())
/// # } // /// # }
/// ``` // /// ```
#[cfg(feature = "cache")] // pub fn compile_cache(wasm: &[u8]) -> error::CompileResult<Cache> {
pub fn compile_cache(wasm: &[u8]) -> error::CompileResult<Cache> { // let default_compiler = default_compiler();
let default_compiler = default_compiler();
wasmer_runtime_core::compile_to_cache_with(wasm, default_compiler) // wasmer_runtime_core::compile_to_cache_with(wasm, default_compiler)
.map(|core_cache| Cache(core_cache)) // .map(|core_cache| Cache(core_cache))
} // }
#[cfg(feature = "default-compiler")]
fn default_compiler() -> &'static dyn Compiler { fn default_compiler() -> &'static dyn Compiler {
use lazy_static::lazy_static; use lazy_static::lazy_static;
use wasmer_clif_backend::CraneliftCompiler; use wasmer_clif_backend::CraneliftCompiler;