mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-21 04:31:33 +00:00
Use ModuleInfo instead of ModuleInner when possible
This commit is contained in:
@ -75,7 +75,7 @@ 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_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) => {
|
||||
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
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 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) => {
|
||||
let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
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 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) => {
|
||||
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> {
|
||||
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(_) => {
|
||||
// this is an internal function
|
||||
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 (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) => (
|
||||
call_names::LOCAL_NAMESPACE,
|
||||
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 (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) => (
|
||||
call_names::LOCAL_NAMESPACE,
|
||||
local_mem_index.index(),
|
||||
|
@ -48,7 +48,7 @@ impl Compiler for CraneliftCompiler {
|
||||
|
||||
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 func_bodies = module_env.translate(wasm)?;
|
||||
@ -72,7 +72,7 @@ impl Compiler for CraneliftCompiler {
|
||||
|
||||
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 func_bodies = module_env.translate(wasm)?;
|
||||
|
@ -6,70 +6,31 @@ use cranelift_codegen::{ir, isa};
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_wasm;
|
||||
use hashbrown::HashMap;
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
use wasmer_runtime_core::{
|
||||
backend::sys::Memory,
|
||||
cache::{Cache, Error as CacheError},
|
||||
};
|
||||
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper},
|
||||
error::{CompileResult, RuntimeResult},
|
||||
module::{ModuleInfo, ModuleInner, StringTable},
|
||||
backend::Backend,
|
||||
error::CompileResult,
|
||||
module::{ModuleInfo, ModuleInner, StringTable, WasmHash},
|
||||
structures::{Map, TypedIndex},
|
||||
types::{
|
||||
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`.
|
||||
pub struct Module {
|
||||
pub module: ModuleInner,
|
||||
pub info: ModuleInfo,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub fn empty() -> Self {
|
||||
pub fn new(wasm: &[u8]) -> Self {
|
||||
Self {
|
||||
module: ModuleInner {
|
||||
// this is a placeholder
|
||||
func_resolver: Box::new(Placeholder),
|
||||
protected_caller: Box::new(Placeholder),
|
||||
|
||||
info: ModuleInfo {
|
||||
memories: Map::new(),
|
||||
globals: Map::new(),
|
||||
@ -93,28 +54,35 @@ impl Module {
|
||||
|
||||
namespace_table: StringTable::new(),
|
||||
name_table: StringTable::new(),
|
||||
},
|
||||
|
||||
wasm_hash: WasmHash::generate(wasm),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile(
|
||||
mut self,
|
||||
self,
|
||||
isa: &isa::TargetIsa,
|
||||
functions: Map<LocalFuncIndex, ir::Function>,
|
||||
) -> CompileResult<ModuleInner> {
|
||||
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 =
|
||||
Box::new(Caller::new(&self.module.info, handler_data, trampolines));
|
||||
let trampolines = Trampolines::new(isa, &self.info);
|
||||
|
||||
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")]
|
||||
@ -124,16 +92,16 @@ impl Module {
|
||||
functions: Map<LocalFuncIndex, ir::Function>,
|
||||
) -> CompileResult<(ModuleInfo, BackendCache, Memory)> {
|
||||
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 (backend_cache, compiled_code) =
|
||||
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")]
|
||||
@ -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);
|
||||
|
||||
macro_rules! convert_clif_to_runtime_index {
|
||||
|
@ -139,7 +139,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
// assert!(!desc.mutable);
|
||||
let global_index: GlobalIndex = Converter(global_index).into();
|
||||
let imported_global_index = global_index
|
||||
.local_or_import(self.module)
|
||||
.local_or_import(&self.module.info)
|
||||
.import()
|
||||
.expect("invalid global initializer when declaring an imported global");
|
||||
Initializer::GetGlobal(imported_global_index)
|
||||
@ -249,7 +249,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
let base = match base {
|
||||
Some(global_index) => {
|
||||
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::Local(_) => {
|
||||
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 {
|
||||
Some(global_index) => {
|
||||
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::Local(_) => {
|
||||
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 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);
|
||||
|
@ -160,7 +160,7 @@ fn get_func_from_index(
|
||||
.get(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) => (
|
||||
module
|
||||
.func_resolver
|
||||
|
@ -99,3 +99,7 @@ pub trait FuncResolver: Send + Sync {
|
||||
local_func_index: LocalFuncIndex,
|
||||
) -> Option<NonNull<vm::Func>>;
|
||||
}
|
||||
|
||||
pub trait CacheGen: Send + Sync {
|
||||
fn generate_cache(&self, module: &ModuleInner) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError>;
|
||||
}
|
@ -91,7 +91,7 @@ impl LocalBacking {
|
||||
}
|
||||
} as usize;
|
||||
|
||||
match init.memory_index.local_or_import(module) {
|
||||
match init.memory_index.local_or_import(&module.info) {
|
||||
LocalOrImport::Local(local_memory_index) => {
|
||||
let memory_desc = module.info.memories[local_memory_index];
|
||||
let data_top = init_base + init.data.len();
|
||||
@ -159,7 +159,7 @@ impl LocalBacking {
|
||||
}
|
||||
} as usize;
|
||||
|
||||
match init.table_index.local_or_import(module) {
|
||||
match init.table_index.local_or_import(&module.info) {
|
||||
LocalOrImport::Local(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,
|
||||
);
|
||||
|
||||
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) => (
|
||||
module
|
||||
.func_resolver
|
||||
@ -215,7 +215,7 @@ impl LocalBacking {
|
||||
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) => (
|
||||
module
|
||||
.func_resolver
|
||||
@ -364,7 +364,7 @@ fn import_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 namespace = module.info.namespace_table.get(*namespace_index);
|
||||
|
@ -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::Import(imported_func_index) => {
|
||||
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
|
||||
.module
|
||||
.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::Import(imported_func_index) => {
|
||||
self.inner.import_backing.vm_functions[imported_func_index].vmctx
|
||||
@ -355,7 +355,7 @@ impl InstanceInner {
|
||||
.get(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) => (
|
||||
module
|
||||
.func_resolver
|
||||
@ -384,7 +384,7 @@ impl InstanceInner {
|
||||
}
|
||||
|
||||
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::Import(imported_mem_index) => {
|
||||
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 {
|
||||
match global_index.local_or_import(module) {
|
||||
match global_index.local_or_import(&module.info) {
|
||||
LocalOrImport::Local(local_global_index) => {
|
||||
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 {
|
||||
match table_index.local_or_import(module) {
|
||||
match table_index.local_or_import(&module.info) {
|
||||
LocalOrImport::Local(local_table_index) => {
|
||||
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::Import(imported_func_index) => {
|
||||
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 {
|
||||
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
|
||||
.module
|
||||
.func_resolver
|
||||
|
@ -51,6 +51,18 @@ pub struct ModuleInfo {
|
||||
|
||||
pub namespace_table: StringTable<NamespaceIndex>,
|
||||
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.
|
||||
@ -60,7 +72,9 @@ pub struct ModuleInfo {
|
||||
///
|
||||
/// [`compile`]: fn.compile.html
|
||||
/// [`compile_with`]: fn.compile_with.html
|
||||
pub struct Module(#[doc(hidden)] pub Arc<ModuleInner>);
|
||||
pub struct Module {
|
||||
inner: Arc<ModuleInner>,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub(crate) fn new(inner: Arc<ModuleInner>) -> Self {
|
||||
@ -68,7 +82,7 @@ impl Module {
|
||||
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`].
|
||||
@ -94,7 +108,7 @@ impl Module {
|
||||
/// # }
|
||||
/// ```
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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};
|
||||
|
||||
/// Represents a WebAssembly type.
|
||||
@ -364,23 +364,23 @@ define_map_index![
|
||||
macro_rules! define_local_or_import {
|
||||
($ty:ident, $local_ty:ident, $imported_ty:ident, $imports:ident) => {
|
||||
impl $ty {
|
||||
pub fn local_or_import(self, module: &ModuleInner) -> LocalOrImport<$ty> {
|
||||
if self.index() < module.info.$imports.len() {
|
||||
pub fn local_or_import(self, info: &ModuleInfo) -> LocalOrImport<$ty> {
|
||||
if self.index() < info.$imports.len() {
|
||||
LocalOrImport::Import(<Self as LocalImport>::Import::new(self.index()))
|
||||
} 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 {
|
||||
pub fn convert_up(self, module: &ModuleInner) -> $ty {
|
||||
$ty ((self.index() + module.info.$imports.len()) as u32)
|
||||
pub fn convert_up(self, info: &ModuleInfo) -> $ty {
|
||||
$ty ((self.index() + info.$imports.len()) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl $imported_ty {
|
||||
pub fn convert_up(self, _module: &ModuleInner) -> $ty {
|
||||
pub fn convert_up(self, _info: &ModuleInfo) -> $ty {
|
||||
$ty (self.index() as u32)
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ impl Ctx {
|
||||
pub fn memory(&self, mem_index: u32) -> &Memory {
|
||||
let module = unsafe { &*self.module };
|
||||
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 {
|
||||
let local_backing = &*self.local_backing;
|
||||
&local_backing.memories[local_mem_index]
|
||||
@ -497,6 +497,7 @@ mod vm_ctx_tests {
|
||||
use crate::backend::{Backend, FuncResolver, ProtectedCaller, Token, UserTrapper};
|
||||
use crate::error::RuntimeResult;
|
||||
use crate::types::{FuncIndex, LocalFuncIndex, Value};
|
||||
use crate::module::WasmHash;
|
||||
use hashbrown::HashMap;
|
||||
use std::ptr::NonNull;
|
||||
struct Placeholder;
|
||||
@ -553,6 +554,8 @@ mod vm_ctx_tests {
|
||||
|
||||
namespace_table: StringTable::new(),
|
||||
name_table: StringTable::new(),
|
||||
|
||||
wasm_hash: WasmHash::generate(&[]),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,9 @@ readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
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"
|
||||
|
||||
[features]
|
||||
default = ["default-compiler", "cache"]
|
||||
default-compiler = ["wasmer-clif-backend/cache", "wasmer-runtime-core/cache"]
|
||||
cache = ["default-compiler"]
|
||||
default = ["wasmer-clif-backend/cache", "wasmer-runtime-core/cache"]
|
||||
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
|
@ -1,128 +1,139 @@
|
||||
use crate::Module;
|
||||
use std::path::Path;
|
||||
use wasmer_runtime_core::cache::{hash_data, Cache as CoreCache};
|
||||
use wasmer_runtime_core::module::{WasmHash};
|
||||
|
||||
pub use wasmer_runtime_core::cache::Error;
|
||||
|
||||
/// On-disk storage of compiled WebAssembly.
|
||||
///
|
||||
/// A `Cache` can be used to quickly reload already
|
||||
/// compiled WebAssembly from a previous execution
|
||||
/// during which the wasm was explicitly compiled
|
||||
/// as a `Cache`.
|
||||
///
|
||||
/// # Usage:
|
||||
///
|
||||
/// ```
|
||||
/// use wasmer_runtime::{compile_cache, Cache};
|
||||
///
|
||||
/// # use wasmer_runtime::error::{CompileResult, CacheError};
|
||||
/// # fn make_cache(wasm: &[u8]) -> CompileResult<()> {
|
||||
/// // Make a cache.
|
||||
/// let cache = compile_cache(wasm)?;
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// # fn usage_cache(cache: Cache) -> Result<(), CacheError> {
|
||||
/// // Store the cache in a file.
|
||||
/// cache.store("some_cache_file")?;
|
||||
///
|
||||
/// // Load the cache.
|
||||
/// let cache = Cache::load("some_cache_file")?;
|
||||
/// let module = unsafe { cache.into_module()? };
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// # Performance Characteristics:
|
||||
///
|
||||
/// Loading caches from files has been optimized for latency.
|
||||
/// There is still more work to do that will reduce
|
||||
/// loading time, especially for very large modules,
|
||||
/// but it will require signifigant internal work.
|
||||
///
|
||||
/// # Drawbacks:
|
||||
///
|
||||
/// Due to internal shortcomings, you cannot convert
|
||||
/// a module into a `Cache`. This means that compiling
|
||||
/// into a `Cache` and then converting into a module
|
||||
/// has more overhead than directly compiling
|
||||
/// into a [`Module`].
|
||||
///
|
||||
/// [`Module`]: struct.Module.html
|
||||
pub struct Cache(pub(crate) CoreCache);
|
||||
// /// On-disk storage of compiled WebAssembly.
|
||||
// ///
|
||||
// /// A `Cache` can be used to quickly reload already
|
||||
// /// compiled WebAssembly from a previous execution
|
||||
// /// during which the wasm was explicitly compiled
|
||||
// /// as a `Cache`.
|
||||
// ///
|
||||
// /// # Usage:
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer_runtime::{compile_cache, Cache};
|
||||
// ///
|
||||
// /// # use wasmer_runtime::error::{CompileResult, CacheError};
|
||||
// /// # fn make_cache(wasm: &[u8]) -> CompileResult<()> {
|
||||
// /// // Make a cache.
|
||||
// /// let cache = compile_cache(wasm)?;
|
||||
// ///
|
||||
// /// # Ok(())
|
||||
// /// # }
|
||||
// /// # fn usage_cache(cache: Cache) -> Result<(), CacheError> {
|
||||
// /// // Store the cache in a file.
|
||||
// /// cache.store("some_cache_file")?;
|
||||
// ///
|
||||
// /// // Load the cache.
|
||||
// /// let cache = Cache::load("some_cache_file")?;
|
||||
// /// let module = unsafe { cache.into_module()? };
|
||||
// /// # Ok(())
|
||||
// /// # }
|
||||
// /// ```
|
||||
// ///
|
||||
// /// # Performance Characteristics:
|
||||
// ///
|
||||
// /// Loading caches from files has been optimized for latency.
|
||||
// /// There is still more work to do that will reduce
|
||||
// /// loading time, especially for very large modules,
|
||||
// /// but it will require signifigant internal work.
|
||||
// ///
|
||||
// /// # Drawbacks:
|
||||
// ///
|
||||
// /// Due to internal shortcomings, you cannot convert
|
||||
// /// a module into a `Cache`. This means that compiling
|
||||
// /// into a `Cache` and then converting into a module
|
||||
// /// has more overhead than directly compiling
|
||||
// /// into a [`Module`].
|
||||
// ///
|
||||
// /// [`Module`]: struct.Module.html
|
||||
// pub struct Cache(pub(crate) CoreCache);
|
||||
|
||||
impl Cache {
|
||||
/// Load a `Cache` from the file specified by `path`.
|
||||
///
|
||||
/// # Usage:
|
||||
///
|
||||
/// ```
|
||||
/// use wasmer_runtime::Cache;
|
||||
/// # use wasmer_runtime::error::CacheError;
|
||||
///
|
||||
/// # fn load_cache() -> Result<(), CacheError> {
|
||||
/// let cache = Cache::load("some_file.cache")?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||
CoreCache::open(path).map(|core_cache| Cache(core_cache))
|
||||
}
|
||||
// impl Cache {
|
||||
// /// Load a `Cache` from the file specified by `path`.
|
||||
// ///
|
||||
// /// # Usage:
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer_runtime::Cache;
|
||||
// /// # use wasmer_runtime::error::CacheError;
|
||||
// ///
|
||||
// /// # fn load_cache() -> Result<(), CacheError> {
|
||||
// /// let cache = Cache::load("some_file.cache")?;
|
||||
// /// # Ok(())
|
||||
// /// # }
|
||||
// /// ```
|
||||
// pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||
// CoreCache::open(path).map(|core_cache| Cache(core_cache))
|
||||
// }
|
||||
|
||||
/// Convert a `Cache` into a [`Module`].
|
||||
///
|
||||
/// [`Module`]: struct.Module.html
|
||||
///
|
||||
/// # Usage:
|
||||
///
|
||||
/// ```
|
||||
/// use wasmer_runtime::Cache;
|
||||
///
|
||||
/// # use wasmer_runtime::error::CacheError;
|
||||
/// # fn cache2module(cache: Cache) -> Result<(), CacheError> {
|
||||
/// let module = unsafe { cache.into_module()? };
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// # Notes:
|
||||
///
|
||||
/// This method is unsafe because the runtime cannot confirm
|
||||
/// that this cache was not tampered with or corrupted.
|
||||
pub unsafe fn into_module(self) -> Result<Module, Error> {
|
||||
let default_compiler = super::default_compiler();
|
||||
// /// Convert a `Cache` into a [`Module`].
|
||||
// ///
|
||||
// /// [`Module`]: struct.Module.html
|
||||
// ///
|
||||
// /// # Usage:
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer_runtime::Cache;
|
||||
// ///
|
||||
// /// # use wasmer_runtime::error::CacheError;
|
||||
// /// # fn cache2module(cache: Cache) -> Result<(), CacheError> {
|
||||
// /// let module = unsafe { cache.into_module()? };
|
||||
// /// # Ok(())
|
||||
// /// # }
|
||||
// /// ```
|
||||
// ///
|
||||
// /// # Notes:
|
||||
// ///
|
||||
// /// This method is unsafe because the runtime cannot confirm
|
||||
// /// that this cache was not tampered with or corrupted.
|
||||
// pub unsafe fn into_module(self) -> Result<Module, Error> {
|
||||
// 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
|
||||
/// from with some other WebAssembly.
|
||||
///
|
||||
/// The main use-case for this is invalidating old caches.
|
||||
pub fn compare_wasm(&self, wasm: &[u8]) -> bool {
|
||||
let param_wasm_hash = hash_data(wasm);
|
||||
self.0.wasm_hash() as &[u8] == ¶m_wasm_hash as &[u8]
|
||||
}
|
||||
// /// Compare the Sha256 hash of the wasm this cache was build
|
||||
// /// from with some other WebAssembly.
|
||||
// ///
|
||||
// /// The main use-case for this is invalidating old caches.
|
||||
// pub fn compare_wasm(&self, wasm: &[u8]) -> bool {
|
||||
// let param_wasm_hash = hash_data(wasm);
|
||||
// self.0.wasm_hash() as &[u8] == ¶m_wasm_hash as &[u8]
|
||||
// }
|
||||
|
||||
/// Store this cache in a file.
|
||||
///
|
||||
/// # Notes:
|
||||
///
|
||||
/// If a file exists at the specified path, it will be overwritten.
|
||||
///
|
||||
/// # Usage:
|
||||
///
|
||||
/// ```
|
||||
/// use wasmer_runtime::Cache;
|
||||
///
|
||||
/// # use wasmer_runtime::error::CacheError;
|
||||
/// # fn store_cache(cache: Cache) -> Result<(), CacheError> {
|
||||
/// cache.store("some_file.cache")?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn store<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
|
||||
self.0.store(path)
|
||||
}
|
||||
// /// Store this cache in a file.
|
||||
// ///
|
||||
// /// # Notes:
|
||||
// ///
|
||||
// /// If a file exists at the specified path, it will be overwritten.
|
||||
// ///
|
||||
// /// # Usage:
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer_runtime::Cache;
|
||||
// ///
|
||||
// /// # use wasmer_runtime::error::CacheError;
|
||||
// /// # fn store_cache(cache: Cache) -> Result<(), CacheError> {
|
||||
// /// cache.store("some_file.cache")?;
|
||||
// /// # Ok(())
|
||||
// /// # }
|
||||
// /// ```
|
||||
// pub fn store<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
|
||||
// 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>;
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,6 @@ pub mod wasm {
|
||||
}
|
||||
|
||||
pub mod error {
|
||||
#[cfg(feature = "cache")]
|
||||
pub use super::cache::Error as CacheError;
|
||||
pub use wasmer_runtime_core::error::*;
|
||||
}
|
||||
@ -109,13 +108,10 @@ pub mod units {
|
||||
pub use wasmer_runtime_core::units::{Bytes, Pages};
|
||||
}
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
mod cache;
|
||||
|
||||
#[cfg(feature = "default-compiler")]
|
||||
use wasmer_runtime_core::backend::Compiler;
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
pub use self::cache::Cache;
|
||||
|
||||
/// 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.
|
||||
/// # Errors:
|
||||
/// If the operation fails, the function returns `Err(error::CompileError::...)`.
|
||||
#[cfg(feature = "default-compiler")]
|
||||
pub fn compile(wasm: &[u8]) -> error::CompileResult<Module> {
|
||||
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::RuntimeError` (all combined into an `error::Error`),
|
||||
/// depending on the cause of the failure.
|
||||
#[cfg(feature = "default-compiler")]
|
||||
pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result<Instance> {
|
||||
let module = compile(wasm)?;
|
||||
module.instantiate(import_object)
|
||||
}
|
||||
|
||||
/// Compile wasm into a [`Cache`] that can be stored to a file or
|
||||
/// converted into [`Module`].
|
||||
///
|
||||
/// [`Cache`]: struct.Cache.html
|
||||
/// [`Module`]: struct.Module.html
|
||||
///
|
||||
/// # Usage:
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer_runtime::error::CompileResult;
|
||||
/// use wasmer_runtime::compile_cache;
|
||||
///
|
||||
/// # fn make_cache(wasm: &[u8]) -> CompileResult<()> {
|
||||
/// let cache = compile_cache(wasm)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(feature = "cache")]
|
||||
pub fn compile_cache(wasm: &[u8]) -> error::CompileResult<Cache> {
|
||||
let default_compiler = default_compiler();
|
||||
// /// Compile wasm into a [`Cache`] that can be stored to a file or
|
||||
// /// converted into [`Module`].
|
||||
// ///
|
||||
// /// [`Cache`]: struct.Cache.html
|
||||
// /// [`Module`]: struct.Module.html
|
||||
// ///
|
||||
// /// # Usage:
|
||||
// ///
|
||||
// /// ```
|
||||
// /// # use wasmer_runtime::error::CompileResult;
|
||||
// /// use wasmer_runtime::compile_cache;
|
||||
// ///
|
||||
// /// # fn make_cache(wasm: &[u8]) -> CompileResult<()> {
|
||||
// /// let cache = compile_cache(wasm)?;
|
||||
// /// # Ok(())
|
||||
// /// # }
|
||||
// /// ```
|
||||
// pub fn compile_cache(wasm: &[u8]) -> error::CompileResult<Cache> {
|
||||
// let default_compiler = default_compiler();
|
||||
|
||||
wasmer_runtime_core::compile_to_cache_with(wasm, default_compiler)
|
||||
.map(|core_cache| Cache(core_cache))
|
||||
}
|
||||
// wasmer_runtime_core::compile_to_cache_with(wasm, default_compiler)
|
||||
// .map(|core_cache| Cache(core_cache))
|
||||
// }
|
||||
|
||||
#[cfg(feature = "default-compiler")]
|
||||
fn default_compiler() -> &'static dyn Compiler {
|
||||
use lazy_static::lazy_static;
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
|
Reference in New Issue
Block a user