From da8e6b42196fec4633eea35ee36c8082a0c3d77b Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 00:11:29 -0700 Subject: [PATCH 01/10] First move from vmexports --- lib/api/src/externals/function.rs | 12 +++--- lib/api/src/externals/global.rs | 16 ++++---- lib/api/src/externals/memory.rs | 16 ++++---- lib/api/src/externals/table.rs | 16 ++++---- lib/api/src/import_object.rs | 6 +-- lib/api/src/module.rs | 2 +- lib/api/src/native.rs | 2 +- lib/api/src/types.rs | 2 +- lib/engine/src/export.rs | 59 ++++++++++------------------- lib/engine/src/lib.rs | 2 +- lib/engine/src/resolver.rs | 20 +++++----- lib/vm/src/export.rs | 62 +++++++++++++++---------------- lib/vm/src/instance/mod.rs | 10 ++--- 13 files changed, 99 insertions(+), 126 deletions(-) diff --git a/lib/api/src/externals/function.rs b/lib/api/src/externals/function.rs index 0980d88ba7e..d9c2ad55ab8 100644 --- a/lib/api/src/externals/function.rs +++ b/lib/api/src/externals/function.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use wasmer_engine::{Export, ExportFunction, ExportFunctionMetadata}; use wasmer_vm::{ raise_user_trap, resume_panic, wasmer_call_trampoline, ImportInitializerFuncPtr, - VMCallerCheckedAnyfunc, VMDynamicFunctionContext, VMExportFunction, VMFuncRef, VMFunctionBody, + VMCallerCheckedAnyfunc, VMDynamicFunctionContext, VMFunction, VMFuncRef, VMFunctionBody, VMFunctionEnvironment, VMFunctionKind, VMTrampoline, }; @@ -218,7 +218,7 @@ impl Function { ) }, )), - vm_function: VMExportFunction { + vm_function: VMFunction { address, kind: VMFunctionKind::Dynamic, vmctx, @@ -311,7 +311,7 @@ impl Function { definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { metadata: Some(Arc::new(metadata)), - vm_function: VMExportFunction { + vm_function: VMFunction { address, kind: VMFunctionKind::Dynamic, vmctx, @@ -365,7 +365,7 @@ impl Function { // TODO: figure out what's going on in this function: it takes an `Env` // param but also marks itself as not having an env metadata: None, - vm_function: VMExportFunction { + vm_function: VMFunction { address, vmctx, signature, @@ -424,7 +424,7 @@ impl Function { definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { metadata: Some(Arc::new(metadata)), - vm_function: VMExportFunction { + vm_function: VMFunction { address, kind: VMFunctionKind::Static, vmctx, @@ -472,7 +472,7 @@ impl Function { definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { metadata: Some(Arc::new(metadata)), - vm_function: VMExportFunction { + vm_function: VMFunction { address, kind: VMFunctionKind::Static, vmctx, diff --git a/lib/api/src/externals/global.rs b/lib/api/src/externals/global.rs index 0d111e0eeea..b35034002db 100644 --- a/lib/api/src/externals/global.rs +++ b/lib/api/src/externals/global.rs @@ -8,8 +8,8 @@ use crate::RuntimeError; use loupe::MemoryUsage; use std::fmt; use std::sync::Arc; -use wasmer_engine::{Export, ExportGlobal}; -use wasmer_vm::{Global as RuntimeGlobal, VMExportGlobal}; +use wasmer_engine::Export; +use wasmer_vm::{Global as RuntimeGlobal, VMGlobal}; /// A WebAssembly `global` instance. /// @@ -182,10 +182,10 @@ impl Global { Ok(()) } - pub(crate) fn from_vm_export(store: &Store, wasmer_export: ExportGlobal) -> Self { + pub(crate) fn from_vm_export(store: &Store, vm_global: VMGlobal) -> Self { Self { store: store.clone(), - global: wasmer_export.vm_global.from, + global: vm_global.from, } } @@ -218,11 +218,9 @@ impl fmt::Debug for Global { impl<'a> Exportable<'a> for Global { fn to_export(&self) -> Export { - ExportGlobal { - vm_global: VMExportGlobal { - from: self.global.clone(), - instance_ref: None, - }, + VMGlobal { + from: self.global.clone(), + instance_ref: None, } .into() } diff --git a/lib/api/src/externals/memory.rs b/lib/api/src/externals/memory.rs index 8cfe9f876b3..b5b8d0d30a4 100644 --- a/lib/api/src/externals/memory.rs +++ b/lib/api/src/externals/memory.rs @@ -6,9 +6,9 @@ use loupe::MemoryUsage; use std::convert::TryInto; use std::slice; use std::sync::Arc; -use wasmer_engine::{Export, ExportMemory}; +use wasmer_engine::Export; use wasmer_types::{Pages, ValueType}; -use wasmer_vm::{Memory as RuntimeMemory, MemoryError, VMExportMemory}; +use wasmer_vm::{Memory as RuntimeMemory, MemoryError, VMMemory}; /// A WebAssembly `memory` instance. /// @@ -221,10 +221,10 @@ impl Memory { unsafe { MemoryView::new(base as _, length as u32) } } - pub(crate) fn from_vm_export(store: &Store, wasmer_export: ExportMemory) -> Self { + pub(crate) fn from_vm_export(store: &Store, vm_memory: VMMemory) -> Self { Self { store: store.clone(), - memory: wasmer_export.vm_memory.from, + memory: vm_memory.from, } } @@ -247,11 +247,9 @@ impl Memory { impl<'a> Exportable<'a> for Memory { fn to_export(&self) -> Export { - ExportMemory { - vm_memory: VMExportMemory { - from: self.memory.clone(), - instance_ref: None, - }, + VMMemory { + from: self.memory.clone(), + instance_ref: None, } .into() } diff --git a/lib/api/src/externals/table.rs b/lib/api/src/externals/table.rs index 6806067d2bc..478393fdbe5 100644 --- a/lib/api/src/externals/table.rs +++ b/lib/api/src/externals/table.rs @@ -6,8 +6,8 @@ use crate::RuntimeError; use crate::TableType; use loupe::MemoryUsage; use std::sync::Arc; -use wasmer_engine::{Export, ExportTable}; -use wasmer_vm::{Table as RuntimeTable, TableElement, VMExportTable}; +use wasmer_engine::Export; +use wasmer_vm::{Table as RuntimeTable, TableElement, VMTable}; /// A WebAssembly `table` instance. /// @@ -131,10 +131,10 @@ impl Table { Ok(()) } - pub(crate) fn from_vm_export(store: &Store, wasmer_export: ExportTable) -> Self { + pub(crate) fn from_vm_export(store: &Store, vm_table: VMTable) -> Self { Self { store: store.clone(), - table: wasmer_export.vm_table.from, + table: vm_table.from, } } @@ -146,11 +146,9 @@ impl Table { impl<'a> Exportable<'a> for Table { fn to_export(&self) -> Export { - ExportTable { - vm_table: VMExportTable { - from: self.table.clone(), - instance_ref: None, - }, + VMTable { + from: self.table.clone(), + instance_ref: None, } .into() } diff --git a/lib/api/src/import_object.rs b/lib/api/src/import_object.rs index 1d507baa7c9..ab4b61d36fd 100644 --- a/lib/api/src/import_object.rs +++ b/lib/api/src/import_object.rs @@ -304,7 +304,7 @@ mod test { let happy_dog_entry = resolver.resolve_by_name("dog", "happy").unwrap(); assert!(if let Export::Global(happy_dog_global) = happy_dog_entry { - happy_dog_global.vm_global.from.ty().ty == Type::I64 + happy_dog_global.from.ty().ty == Type::I64 } else { false }); @@ -330,7 +330,7 @@ mod test { let happy_dog_entry = resolver.resolve_by_name("dog", "happy").unwrap(); assert!(if let Export::Global(happy_dog_global) = happy_dog_entry { - happy_dog_global.vm_global.from.ty().ty == Type::I32 + happy_dog_global.from.ty().ty == Type::I32 } else { false }); @@ -350,7 +350,7 @@ mod test { let happy_dog_entry = imports1.resolve_by_name("dog", "happy").unwrap(); assert!(if let Export::Global(happy_dog_global) = happy_dog_entry { - happy_dog_global.vm_global.from.ty().ty == Type::I32 + happy_dog_global.from.ty().ty == Type::I32 } else { false }); diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index ea2b8b8d8a8..b4bda945789 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -266,7 +266,7 @@ impl Module { unsafe { let instance_handle = self.artifact - .instantiate(self.store.tunables(), resolver, Box::new(()))?; + .instantiate(self.store.tunables(), resolver, Box::new((self.store.clone(), self.artifact.clone())))?; // After the instance handle is created, we need to initialize // the data, call the start function and so. However, if any diff --git a/lib/api/src/native.rs b/lib/api/src/native.rs index 2229dc01f64..fa9457c1393 100644 --- a/lib/api/src/native.rs +++ b/lib/api/src/native.rs @@ -63,7 +63,7 @@ where } /* -impl From<&NativeFunc> for VMExportFunction +impl From<&NativeFunc> for VMFunction where Args: WasmTypeList, Rets: WasmTypeList, diff --git a/lib/api/src/types.rs b/lib/api/src/types.rs index 5a0ab3db634..70c7a196173 100644 --- a/lib/api/src/types.rs +++ b/lib/api/src/types.rs @@ -74,7 +74,7 @@ impl ValFuncRef for Val { // TODO: // figure out if we ever need a value here: need testing with complicated import patterns metadata: None, - vm_function: wasmer_vm::VMExportFunction { + vm_function: wasmer_vm::VMFunction { address: item.func_ptr, signature, // TODO: review this comment (unclear if it's still correct): diff --git a/lib/engine/src/export.rs b/lib/engine/src/export.rs index d0014eb8c2c..080dcbbff99 100644 --- a/lib/engine/src/export.rs +++ b/lib/engine/src/export.rs @@ -1,8 +1,8 @@ use loupe::MemoryUsage; use std::sync::Arc; use wasmer_vm::{ - ImportInitializerFuncPtr, VMExport, VMExportFunction, VMExportGlobal, VMExportMemory, - VMExportTable, + ImportInitializerFuncPtr, VMExport, VMFunction, VMGlobal, VMMemory, + VMTable, }; /// The value of an export passed from one instance to another. @@ -12,22 +12,22 @@ pub enum Export { Function(ExportFunction), /// A table export value. - Table(ExportTable), + Table(VMTable), /// A memory export value. - Memory(ExportMemory), + Memory(VMMemory), /// A global export value. - Global(ExportGlobal), + Global(VMGlobal), } impl From for VMExport { fn from(other: Export) -> Self { match other { Export::Function(ExportFunction { vm_function, .. }) => Self::Function(vm_function), - Export::Memory(ExportMemory { vm_memory }) => Self::Memory(vm_memory), - Export::Table(ExportTable { vm_table }) => Self::Table(vm_table), - Export::Global(ExportGlobal { vm_global }) => Self::Global(vm_global), + Export::Memory(vm_memory) => Self::Memory(vm_memory), + Export::Table(vm_table) => Self::Table(vm_table), + Export::Global(vm_global) => Self::Global(vm_global), } } } @@ -39,9 +39,9 @@ impl From for Export { vm_function, metadata: None, }), - VMExport::Memory(vm_memory) => Self::Memory(ExportMemory { vm_memory }), - VMExport::Table(vm_table) => Self::Table(ExportTable { vm_table }), - VMExport::Global(vm_global) => Self::Global(ExportGlobal { vm_global }), + VMExport::Memory(vm_memory) => Self::Memory(vm_memory), + VMExport::Table(vm_table) => Self::Table(vm_table), + VMExport::Global(vm_global) => Self::Global(vm_global), } } } @@ -66,7 +66,7 @@ pub struct ExportFunctionMetadata { /// Thus, we only bother to store the master copy at all here so that /// we can free it. /// - /// See `wasmer_vm::export::VMExportFunction::vmctx` for the version of + /// See `wasmer_vm::export::VMFunction::vmctx` for the version of /// this pointer that is used by the VM when creating an `Instance`. pub(crate) host_env: *mut std::ffi::c_void, @@ -141,7 +141,7 @@ impl Drop for ExportFunctionMetadata { #[derive(Debug, Clone, PartialEq, MemoryUsage)] pub struct ExportFunction { /// The VM function, containing most of the data. - pub vm_function: VMExportFunction, + pub vm_function: VMFunction, /// Contains functions necessary to create and initialize host envs /// with each `Instance` as well as being responsible for the /// underlying memory of the host env. @@ -154,41 +154,20 @@ impl From for Export { } } -/// A table export value. -#[derive(Debug, Clone)] -pub struct ExportTable { - /// The VM table, containing info about the table. - pub vm_table: VMExportTable, -} - -impl From for Export { - fn from(table: ExportTable) -> Self { +impl From for Export { + fn from(table: VMTable) -> Self { Self::Table(table) } } -/// A memory export value. -#[derive(Debug, Clone)] -pub struct ExportMemory { - /// The VM memory, containing info about the table. - pub vm_memory: VMExportMemory, -} - -impl From for Export { - fn from(memory: ExportMemory) -> Self { +impl From for Export { + fn from(memory: VMMemory) -> Self { Self::Memory(memory) } } -/// A global export value. -#[derive(Debug, Clone)] -pub struct ExportGlobal { - /// The VM global, containing info about the global. - pub vm_global: VMExportGlobal, -} - -impl From for Export { - fn from(global: ExportGlobal) -> Self { +impl From for Export { + fn from(global: VMGlobal) -> Self { Self::Global(global) } } diff --git a/lib/engine/src/lib.rs b/lib/engine/src/lib.rs index 203d84e868b..0d0b43ce38e 100644 --- a/lib/engine/src/lib.rs +++ b/lib/engine/src/lib.rs @@ -34,7 +34,7 @@ pub use crate::error::{ DeserializeError, ImportError, InstantiationError, LinkError, SerializeError, }; pub use crate::export::{ - Export, ExportFunction, ExportFunctionMetadata, ExportGlobal, ExportMemory, ExportTable, + Export, ExportFunction, ExportFunctionMetadata, }; pub use crate::resolver::{ resolve_imports, ChainableNamedResolver, NamedResolver, NamedResolverChain, NullResolver, diff --git a/lib/engine/src/resolver.rs b/lib/engine/src/resolver.rs index cc0123015f4..a447899c3ea 100644 --- a/lib/engine/src/resolver.rs +++ b/lib/engine/src/resolver.rs @@ -105,10 +105,10 @@ fn get_extern_from_import(module: &ModuleInfo, import_index: &ImportIndex) -> Ex fn get_extern_from_export(_module: &ModuleInfo, export: &Export) -> ExternType { match export { Export::Function(ref f) => ExternType::Function(f.vm_function.signature.clone()), - Export::Table(ref t) => ExternType::Table(*t.vm_table.ty()), - Export::Memory(ref m) => ExternType::Memory(*m.vm_memory.ty()), + Export::Table(ref t) => ExternType::Table(*t.ty()), + Export::Memory(ref m) => ExternType::Memory(*m.ty()), Export::Global(ref g) => { - let global = g.vm_global.from.ty(); + let global = g.from.ty(); ExternType::Global(*global) } } @@ -223,8 +223,8 @@ pub fn resolve_imports( } Export::Table(ref t) => { table_imports.push(VMTableImport { - definition: t.vm_table.from.vmtable(), - from: t.vm_table.from.clone(), + definition: t.from.vmtable(), + from: t.from.clone(), }); } Export::Memory(ref m) => { @@ -232,7 +232,7 @@ pub fn resolve_imports( ImportIndex::Memory(index) => { // Sanity-check: Ensure that the imported memory has at least // guard-page protections the importing module expects it to have. - let export_memory_style = m.vm_memory.style(); + let export_memory_style = m.style(); let import_memory_style = &memory_styles[*index]; if let ( MemoryStyle::Static { bound, .. }, @@ -257,15 +257,15 @@ pub fn resolve_imports( } memory_imports.push(VMMemoryImport { - definition: m.vm_memory.from.vmmemory(), - from: m.vm_memory.from.clone(), + definition: m.from.vmmemory(), + from: m.from.clone(), }); } Export::Global(ref g) => { global_imports.push(VMGlobalImport { - definition: g.vm_global.from.vmglobal(), - from: g.vm_global.from.clone(), + definition: g.from.vmglobal(), + from: g.from.clone(), }); } } diff --git a/lib/vm/src/export.rs b/lib/vm/src/export.rs index 806178ab47f..6138fa6c584 100644 --- a/lib/vm/src/export.rs +++ b/lib/vm/src/export.rs @@ -14,21 +14,21 @@ use wasmer_types::{FunctionType, MemoryType, TableType}; #[derive(Debug)] pub enum VMExport { /// A function export value. - Function(VMExportFunction), + Function(VMFunction), /// A table export value. - Table(VMExportTable), + Table(VMTable), /// A memory export value. - Memory(VMExportMemory), + Memory(VMMemory), /// A global export value. - Global(VMExportGlobal), + Global(VMGlobal), } /// A function export value. #[derive(Debug, Clone, PartialEq, MemoryUsage)] -pub struct VMExportFunction { +pub struct VMFunction { /// The address of the native-code function. pub address: *const VMFunctionBody, @@ -58,20 +58,20 @@ pub struct VMExportFunction { /// # Safety /// There is no non-threadsafe logic directly in this type. Calling the function /// may not be threadsafe. -unsafe impl Send for VMExportFunction {} +unsafe impl Send for VMFunction {} /// # Safety -/// The members of an VMExportFunction are immutable after construction. -unsafe impl Sync for VMExportFunction {} +/// The members of an VMFunction are immutable after construction. +unsafe impl Sync for VMFunction {} -impl From for VMExport { - fn from(func: VMExportFunction) -> Self { +impl From for VMExport { + fn from(func: VMFunction) -> Self { Self::Function(func) } } /// A table export value. #[derive(Debug, Clone)] -pub struct VMExportTable { +pub struct VMTable { /// Pointer to the containing `Table`. pub from: Arc, @@ -84,15 +84,15 @@ pub struct VMExportTable { /// This is correct because there is no non-threadsafe logic directly in this type; /// correct use of the raw table from multiple threads via `definition` requires `unsafe` /// and is the responsibilty of the user of this type. -unsafe impl Send for VMExportTable {} +unsafe impl Send for VMTable {} /// # Safety /// This is correct because the values directly in `definition` should be considered immutable /// and the type is both `Send` and `Clone` (thus marking it `Sync` adds no new behavior, it /// only makes this type easier to use) -unsafe impl Sync for VMExportTable {} +unsafe impl Sync for VMTable {} -impl VMExportTable { +impl VMTable { /// Get the table type for this exported table pub fn ty(&self) -> &TableType { self.from.ty() @@ -103,21 +103,21 @@ impl VMExportTable { self.from.style() } - /// Returns whether or not the two `VMExportTable`s refer to the same Memory. + /// Returns whether or not the two `VMTable`s refer to the same Memory. pub fn same(&self, other: &Self) -> bool { Arc::ptr_eq(&self.from, &other.from) } } -impl From for VMExport { - fn from(table: VMExportTable) -> Self { +impl From for VMExport { + fn from(table: VMTable) -> Self { Self::Table(table) } } /// A memory export value. #[derive(Debug, Clone)] -pub struct VMExportMemory { +pub struct VMMemory { /// Pointer to the containing `Memory`. pub from: Arc, @@ -130,15 +130,15 @@ pub struct VMExportMemory { /// This is correct because there is no non-threadsafe logic directly in this type; /// correct use of the raw memory from multiple threads via `definition` requires `unsafe` /// and is the responsibilty of the user of this type. -unsafe impl Send for VMExportMemory {} +unsafe impl Send for VMMemory {} /// # Safety /// This is correct because the values directly in `definition` should be considered immutable /// and the type is both `Send` and `Clone` (thus marking it `Sync` adds no new behavior, it /// only makes this type easier to use) -unsafe impl Sync for VMExportMemory {} +unsafe impl Sync for VMMemory {} -impl VMExportMemory { +impl VMMemory { /// Get the type for this exported memory pub fn ty(&self) -> &MemoryType { self.from.ty() @@ -149,21 +149,21 @@ impl VMExportMemory { self.from.style() } - /// Returns whether or not the two `VMExportMemory`s refer to the same Memory. + /// Returns whether or not the two `VMMemory`s refer to the same Memory. pub fn same(&self, other: &Self) -> bool { Arc::ptr_eq(&self.from, &other.from) } } -impl From for VMExport { - fn from(memory: VMExportMemory) -> Self { +impl From for VMExport { + fn from(memory: VMMemory) -> Self { Self::Memory(memory) } } /// A global export value. #[derive(Debug, Clone)] -pub struct VMExportGlobal { +pub struct VMGlobal { /// The global declaration, used for compatibility checking. pub from: Arc, @@ -176,23 +176,23 @@ pub struct VMExportGlobal { /// This is correct because there is no non-threadsafe logic directly in this type; /// correct use of the raw global from multiple threads via `definition` requires `unsafe` /// and is the responsibilty of the user of this type. -unsafe impl Send for VMExportGlobal {} +unsafe impl Send for VMGlobal {} /// # Safety /// This is correct because the values directly in `definition` should be considered immutable /// from the perspective of users of this type and the type is both `Send` and `Clone` (thus /// marking it `Sync` adds no new behavior, it only makes this type easier to use) -unsafe impl Sync for VMExportGlobal {} +unsafe impl Sync for VMGlobal {} -impl VMExportGlobal { - /// Returns whether or not the two `VMExportGlobal`s refer to the same Global. +impl VMGlobal { + /// Returns whether or not the two `VMGlobal`s refer to the same Global. pub fn same(&self, other: &Self) -> bool { Arc::ptr_eq(&self.from, &other.from) } } -impl From for VMExport { - fn from(global: VMExportGlobal) -> Self { +impl From for VMExport { + fn from(global: VMGlobal) -> Self { Self::Global(global) } } diff --git a/lib/vm/src/instance/mod.rs b/lib/vm/src/instance/mod.rs index 4108e63d320..dab303be7f7 100644 --- a/lib/vm/src/instance/mod.rs +++ b/lib/vm/src/instance/mod.rs @@ -27,7 +27,7 @@ use crate::vmcontext::{ VMTrampoline, }; use crate::{FunctionBodyPtr, ModuleInfo, VMOffsets}; -use crate::{VMExportFunction, VMExportGlobal, VMExportMemory, VMExportTable}; +use crate::{VMFunction, VMGlobal, VMMemory, VMTable}; use loupe::{MemoryUsage, MemoryUsageTracker}; use memoffset::offset_of; use more_asserts::assert_lt; @@ -1099,7 +1099,7 @@ impl InstanceHandle { let call_trampoline = Some(instance_ref.function_call_trampolines[*sig_index]); let signature = instance_ref.module.signatures[*sig_index].clone(); - VMExportFunction { + VMFunction { address, // Any function received is already static at this point as: // 1. All locally defined functions in the Wasm have a static signature. @@ -1120,7 +1120,7 @@ impl InstanceHandle { let import = instance_ref.imported_table(*index); import.from.clone() }; - VMExportTable { + VMTable { from, instance_ref: Some(instance), } @@ -1133,7 +1133,7 @@ impl InstanceHandle { let import = instance_ref.imported_memory(*index); import.from.clone() }; - VMExportMemory { + VMMemory { from, instance_ref: Some(instance), } @@ -1148,7 +1148,7 @@ impl InstanceHandle { import.from.clone() } }; - VMExportGlobal { + VMGlobal { from, instance_ref: Some(instance), } From 165152ddb81befb6181f533a53505b9001038278 Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 00:28:25 -0700 Subject: [PATCH 02/10] Simplified api Memory --- lib/api/src/externals/memory.rs | 33 +++++++++++++++++---------------- lib/vm/src/export.rs | 2 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/api/src/externals/memory.rs b/lib/api/src/externals/memory.rs index b5b8d0d30a4..316f0e42971 100644 --- a/lib/api/src/externals/memory.rs +++ b/lib/api/src/externals/memory.rs @@ -8,7 +8,7 @@ use std::slice; use std::sync::Arc; use wasmer_engine::Export; use wasmer_types::{Pages, ValueType}; -use wasmer_vm::{Memory as RuntimeMemory, MemoryError, VMMemory}; +use wasmer_vm::{MemoryError, VMMemory}; /// A WebAssembly `memory` instance. /// @@ -27,7 +27,7 @@ use wasmer_vm::{Memory as RuntimeMemory, MemoryError, VMMemory}; #[derive(Debug, Clone, MemoryUsage)] pub struct Memory { store: Store, - memory: Arc, + vm_memory: VMMemory, } impl Memory { @@ -51,7 +51,12 @@ impl Memory { Ok(Self { store: store.clone(), - memory, + vm_memory: VMMemory { + from: memory, + // We are creating it from the host, and therefore there is no + // associated instance with this memory + instance_ref: None + }, }) } @@ -69,7 +74,7 @@ impl Memory { /// assert_eq!(m.ty(), &mt); /// ``` pub fn ty(&self) -> &MemoryType { - self.memory.ty() + self.vm_memory.from.ty() } /// Returns the [`Store`] where the `Memory` belongs. @@ -110,21 +115,21 @@ impl Memory { /// by resizing this Memory. #[allow(clippy::mut_from_ref)] pub unsafe fn data_unchecked_mut(&self) -> &mut [u8] { - let definition = self.memory.vmmemory(); + let definition = self.vm_memory.from.vmmemory(); let def = definition.as_ref(); slice::from_raw_parts_mut(def.base, def.current_length.try_into().unwrap()) } /// Returns the pointer to the raw bytes of the `Memory`. pub fn data_ptr(&self) -> *mut u8 { - let definition = self.memory.vmmemory(); + let definition = self.vm_memory.from.vmmemory(); let def = unsafe { definition.as_ref() }; def.base } /// Returns the size (in bytes) of the `Memory`. pub fn data_size(&self) -> u64 { - let definition = self.memory.vmmemory(); + let definition = self.vm_memory.from.vmmemory(); let def = unsafe { definition.as_ref() }; def.current_length.into() } @@ -142,7 +147,7 @@ impl Memory { /// assert_eq!(m.size(), Pages(1)); /// ``` pub fn size(&self) -> Pages { - self.memory.size() + self.vm_memory.from.size() } /// Grow memory by the specified amount of WebAssembly [`Pages`] and return @@ -179,7 +184,7 @@ impl Memory { where IntoPages: Into, { - self.memory.grow(delta.into()) + self.vm_memory.from.grow(delta.into()) } /// Return a "view" of the currently accessible memory. By @@ -224,7 +229,7 @@ impl Memory { pub(crate) fn from_vm_export(store: &Store, vm_memory: VMMemory) -> Self { Self { store: store.clone(), - memory: vm_memory.from, + vm_memory, } } @@ -241,17 +246,13 @@ impl Memory { /// assert!(m.same(&m)); /// ``` pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.memory, &other.memory) + Arc::ptr_eq(&self.vm_memory.from, &other.vm_memory.from) } } impl<'a> Exportable<'a> for Memory { fn to_export(&self) -> Export { - VMMemory { - from: self.memory.clone(), - instance_ref: None, - } - .into() + self.vm_memory.clone().into() } fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { diff --git a/lib/vm/src/export.rs b/lib/vm/src/export.rs index 6138fa6c584..53115c89559 100644 --- a/lib/vm/src/export.rs +++ b/lib/vm/src/export.rs @@ -116,7 +116,7 @@ impl From for VMExport { } /// A memory export value. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, MemoryUsage)] pub struct VMMemory { /// Pointer to the containing `Memory`. pub from: Arc, From 12226f3d29802ff75767f5b3893dfee4688bbd57 Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 00:34:00 -0700 Subject: [PATCH 03/10] Simplified global api --- lib/api/src/externals/global.rs | 23 +++++++++++------------ lib/vm/src/export.rs | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/api/src/externals/global.rs b/lib/api/src/externals/global.rs index b35034002db..f33d2cf5233 100644 --- a/lib/api/src/externals/global.rs +++ b/lib/api/src/externals/global.rs @@ -20,7 +20,7 @@ use wasmer_vm::{Global as RuntimeGlobal, VMGlobal}; #[derive(Clone, MemoryUsage)] pub struct Global { store: Store, - global: Arc, + vm_global: VMGlobal, } impl Global { @@ -75,7 +75,10 @@ impl Global { Ok(Self { store: store.clone(), - global: Arc::new(global), + vm_global: VMGlobal { + from: Arc::new(global), + instance_ref: None, + } }) } @@ -94,7 +97,7 @@ impl Global { /// assert_eq!(v.ty(), &GlobalType::new(Type::I64, Mutability::Var)); /// ``` pub fn ty(&self) -> &GlobalType { - self.global.ty() + self.vm_global.from.ty() } /// Returns the [`Store`] where the `Global` belongs. @@ -126,7 +129,7 @@ impl Global { /// assert_eq!(g.get(), Value::I32(1)); /// ``` pub fn get(&self) -> Val { - self.global.get(&self.store) + self.vm_global.from.get(&self.store) } /// Sets a custom value [`Val`] to the runtime Global. @@ -175,7 +178,7 @@ impl Global { return Err(RuntimeError::new("cross-`Store` values are not supported")); } unsafe { - self.global + self.vm_global.from .set(val) .map_err(|e| RuntimeError::new(format!("{}", e)))?; } @@ -185,7 +188,7 @@ impl Global { pub(crate) fn from_vm_export(store: &Store, vm_global: VMGlobal) -> Self { Self { store: store.clone(), - global: vm_global.from, + vm_global, } } @@ -202,7 +205,7 @@ impl Global { /// assert!(g.same(&g)); /// ``` pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.global, &other.global) + Arc::ptr_eq(&self.vm_global.from, &other.vm_global.from) } } @@ -218,11 +221,7 @@ impl fmt::Debug for Global { impl<'a> Exportable<'a> for Global { fn to_export(&self) -> Export { - VMGlobal { - from: self.global.clone(), - instance_ref: None, - } - .into() + self.vm_global.clone().into() } fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { diff --git a/lib/vm/src/export.rs b/lib/vm/src/export.rs index 53115c89559..89d163a705d 100644 --- a/lib/vm/src/export.rs +++ b/lib/vm/src/export.rs @@ -162,7 +162,7 @@ impl From for VMExport { } /// A global export value. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, MemoryUsage)] pub struct VMGlobal { /// The global declaration, used for compatibility checking. pub from: Arc, From 07b625a9e06f94762ebf09660857bf7d47fca17d Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 00:37:28 -0700 Subject: [PATCH 04/10] Simplified table api --- lib/api/src/externals/table.rs | 31 +++++++++++++++---------------- lib/vm/src/export.rs | 2 +- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/api/src/externals/table.rs b/lib/api/src/externals/table.rs index 478393fdbe5..df5dce8fb3c 100644 --- a/lib/api/src/externals/table.rs +++ b/lib/api/src/externals/table.rs @@ -21,7 +21,7 @@ use wasmer_vm::{Table as RuntimeTable, TableElement, VMTable}; #[derive(Clone, MemoryUsage)] pub struct Table { store: Store, - table: Arc, + vm_table: VMTable, } fn set_table_item( @@ -54,13 +54,16 @@ impl Table { Ok(Self { store: store.clone(), - table, + vm_table: VMTable { + from: table, + instance_ref: None, + } }) } /// Returns the [`TableType`] of the `Table`. pub fn ty(&self) -> &TableType { - self.table.ty() + self.vm_table.from.ty() } /// Returns the [`Store`] where the `Table` belongs. @@ -70,19 +73,19 @@ impl Table { /// Retrieves an element of the table at the provided `index`. pub fn get(&self, index: u32) -> Option { - let item = self.table.get(index)?; + let item = self.vm_table.from.get(index)?; Some(ValFuncRef::from_table_reference(item, &self.store)) } /// Sets an element `val` in the Table at the provided `index`. pub fn set(&self, index: u32, val: Val) -> Result<(), RuntimeError> { let item = val.into_table_reference(&self.store)?; - set_table_item(self.table.as_ref(), index, item) + set_table_item(self.vm_table.from.as_ref(), index, item) } /// Retrieves the size of the `Table` (in elements) pub fn size(&self) -> u32 { - self.table.size() + self.vm_table.from.size() } /// Grows the size of the `Table` by `delta`, initializating @@ -96,7 +99,7 @@ impl Table { /// Returns an error if the `delta` is out of bounds for the table. pub fn grow(&self, delta: u32, init: Val) -> Result { let item = init.into_table_reference(&self.store)?; - self.table + self.vm_table.from .grow(delta, item) .ok_or_else(|| RuntimeError::new(format!("failed to grow table by `{}`", delta))) } @@ -121,8 +124,8 @@ impl Table { )); } RuntimeTable::copy( - dst_table.table.as_ref(), - src_table.table.as_ref(), + dst_table.vm_table.from.as_ref(), + src_table.vm_table.from.as_ref(), dst_index, src_index, len, @@ -134,23 +137,19 @@ impl Table { pub(crate) fn from_vm_export(store: &Store, vm_table: VMTable) -> Self { Self { store: store.clone(), - table: vm_table.from, + vm_table, } } /// Returns whether or not these two tables refer to the same data. pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.table, &other.table) + Arc::ptr_eq(&self.vm_table.from, &other.vm_table.from) } } impl<'a> Exportable<'a> for Table { fn to_export(&self) -> Export { - VMTable { - from: self.table.clone(), - instance_ref: None, - } - .into() + self.vm_table.clone().into() } fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { diff --git a/lib/vm/src/export.rs b/lib/vm/src/export.rs index 89d163a705d..e2ba8c06c3a 100644 --- a/lib/vm/src/export.rs +++ b/lib/vm/src/export.rs @@ -70,7 +70,7 @@ impl From for VMExport { } /// A table export value. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, MemoryUsage)] pub struct VMTable { /// Pointer to the containing `Table`. pub from: Arc, From 19ec7edb26de1a679b0ff5d3bd465f762471e7e0 Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 00:41:41 -0700 Subject: [PATCH 05/10] Added extra test to verify that works --- tests/compilers/imports.rs | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/compilers/imports.rs b/tests/compilers/imports.rs index 4614eb93e1d..95131274eba 100644 --- a/tests/compilers/imports.rs +++ b/tests/compilers/imports.rs @@ -390,3 +390,44 @@ fn multi_use_host_fn_manages_memory_correctly() -> Result<()> { drop(instance2); Ok(()) } + + +#[test] +fn instance_local_memory_lifetime() -> Result<()> { + let store = get_store(false); + + let memory: Memory = { + let wat = r#"(module + (memory $mem 1) + (export "memory" (memory $mem)) +)"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&module, &imports! {})?; + instance.exports.get_memory("memory")?.clone() + }; + + let wat = r#"(module + (import "env" "memory" (memory $mem 1) ) + (func $get_at (type $get_at_t) (param $idx i32) (result i32) + (i32.load (local.get $idx))) + (type $get_at_t (func (param i32) (result i32))) + (type $set_at_t (func (param i32) (param i32))) + (func $set_at (type $set_at_t) (param $idx i32) (param $val i32) + (i32.store (local.get $idx) (local.get $val))) + (export "get_at" (func $get_at)) + (export "set_at" (func $set_at)) +)"#; + let module = Module::new(&store, wat)?; + let imports = imports! { + "env" => { + "memory" => memory, + }, + }; + let instance = Instance::new(&module, &imports)?; + let set_at: NativeFunc<(i32, i32), ()> = instance.exports.get_native_function("set_at")?; + let get_at: NativeFunc = instance.exports.get_native_function("get_at")?; + set_at.call(200, 123)?; + assert_eq!(get_at.call(200)?, 123); + + Ok(()) +} From a7367ea7e2e24c48eb683355efa7d1c36a70d241 Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 00:42:43 -0700 Subject: [PATCH 06/10] Fixed lint --- lib/api/src/externals/function.rs | 2 +- lib/api/src/externals/global.rs | 5 +++-- lib/api/src/externals/memory.rs | 2 +- lib/api/src/externals/table.rs | 5 +++-- lib/api/src/module.rs | 8 +++++--- lib/engine/src/export.rs | 5 +---- lib/engine/src/lib.rs | 4 +--- tests/compilers/imports.rs | 1 - 8 files changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/api/src/externals/function.rs b/lib/api/src/externals/function.rs index d9c2ad55ab8..5654e12cd4a 100644 --- a/lib/api/src/externals/function.rs +++ b/lib/api/src/externals/function.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use wasmer_engine::{Export, ExportFunction, ExportFunctionMetadata}; use wasmer_vm::{ raise_user_trap, resume_panic, wasmer_call_trampoline, ImportInitializerFuncPtr, - VMCallerCheckedAnyfunc, VMDynamicFunctionContext, VMFunction, VMFuncRef, VMFunctionBody, + VMCallerCheckedAnyfunc, VMDynamicFunctionContext, VMFuncRef, VMFunction, VMFunctionBody, VMFunctionEnvironment, VMFunctionKind, VMTrampoline, }; diff --git a/lib/api/src/externals/global.rs b/lib/api/src/externals/global.rs index f33d2cf5233..1d03cc10a24 100644 --- a/lib/api/src/externals/global.rs +++ b/lib/api/src/externals/global.rs @@ -78,7 +78,7 @@ impl Global { vm_global: VMGlobal { from: Arc::new(global), instance_ref: None, - } + }, }) } @@ -178,7 +178,8 @@ impl Global { return Err(RuntimeError::new("cross-`Store` values are not supported")); } unsafe { - self.vm_global.from + self.vm_global + .from .set(val) .map_err(|e| RuntimeError::new(format!("{}", e)))?; } diff --git a/lib/api/src/externals/memory.rs b/lib/api/src/externals/memory.rs index 316f0e42971..a71653c6db7 100644 --- a/lib/api/src/externals/memory.rs +++ b/lib/api/src/externals/memory.rs @@ -55,7 +55,7 @@ impl Memory { from: memory, // We are creating it from the host, and therefore there is no // associated instance with this memory - instance_ref: None + instance_ref: None, }, }) } diff --git a/lib/api/src/externals/table.rs b/lib/api/src/externals/table.rs index df5dce8fb3c..d959212ba31 100644 --- a/lib/api/src/externals/table.rs +++ b/lib/api/src/externals/table.rs @@ -57,7 +57,7 @@ impl Table { vm_table: VMTable { from: table, instance_ref: None, - } + }, }) } @@ -99,7 +99,8 @@ impl Table { /// Returns an error if the `delta` is out of bounds for the table. pub fn grow(&self, delta: u32, init: Val) -> Result { let item = init.into_table_reference(&self.store)?; - self.vm_table.from + self.vm_table + .from .grow(delta, item) .ok_or_else(|| RuntimeError::new(format!("failed to grow table by `{}`", delta))) } diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index b4bda945789..8cb8fdd7939 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -264,9 +264,11 @@ impl Module { resolver: &dyn Resolver, ) -> Result { unsafe { - let instance_handle = - self.artifact - .instantiate(self.store.tunables(), resolver, Box::new((self.store.clone(), self.artifact.clone())))?; + let instance_handle = self.artifact.instantiate( + self.store.tunables(), + resolver, + Box::new((self.store.clone(), self.artifact.clone())), + )?; // After the instance handle is created, we need to initialize // the data, call the start function and so. However, if any diff --git a/lib/engine/src/export.rs b/lib/engine/src/export.rs index 080dcbbff99..46e03074c04 100644 --- a/lib/engine/src/export.rs +++ b/lib/engine/src/export.rs @@ -1,9 +1,6 @@ use loupe::MemoryUsage; use std::sync::Arc; -use wasmer_vm::{ - ImportInitializerFuncPtr, VMExport, VMFunction, VMGlobal, VMMemory, - VMTable, -}; +use wasmer_vm::{ImportInitializerFuncPtr, VMExport, VMFunction, VMGlobal, VMMemory, VMTable}; /// The value of an export passed from one instance to another. #[derive(Debug, Clone)] diff --git a/lib/engine/src/lib.rs b/lib/engine/src/lib.rs index 0d0b43ce38e..9cc5f1a68b9 100644 --- a/lib/engine/src/lib.rs +++ b/lib/engine/src/lib.rs @@ -33,9 +33,7 @@ pub use crate::engine::{Engine, EngineId}; pub use crate::error::{ DeserializeError, ImportError, InstantiationError, LinkError, SerializeError, }; -pub use crate::export::{ - Export, ExportFunction, ExportFunctionMetadata, -}; +pub use crate::export::{Export, ExportFunction, ExportFunctionMetadata}; pub use crate::resolver::{ resolve_imports, ChainableNamedResolver, NamedResolver, NamedResolverChain, NullResolver, Resolver, diff --git a/tests/compilers/imports.rs b/tests/compilers/imports.rs index 95131274eba..2b2c6dfac16 100644 --- a/tests/compilers/imports.rs +++ b/tests/compilers/imports.rs @@ -391,7 +391,6 @@ fn multi_use_host_fn_manages_memory_correctly() -> Result<()> { Ok(()) } - #[test] fn instance_local_memory_lifetime() -> Result<()> { let store = get_store(false); From 7e7b93033c51e8ba73776ce3b91327a673db5b36 Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 00:50:03 -0700 Subject: [PATCH 07/10] Fixed unallocated libraries --- lib/engine-native/src/artifact.rs | 7 +++++-- lib/engine-native/src/engine.rs | 11 ----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index c95e70e8e5f..11972f74c4e 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -49,6 +49,9 @@ pub struct NativeArtifact { finished_dynamic_function_trampolines: BoxedSlice, func_data_registry: Arc, signatures: BoxedSlice, + #[allow(dead_code)] + #[loupe(skip)] + library: Option, } fn to_compile_error(err: impl Error) -> CompileError { @@ -371,6 +374,7 @@ impl NativeArtifact { .into_boxed_slice(), func_data_registry: Arc::new(FuncDataRegistry::new()), signatures: signatures.into_boxed_slice(), + library: None, }) } @@ -463,11 +467,10 @@ impl NativeArtifact { .collect::>() }; - engine_inner.add_library(lib); - Ok(Self { sharedobject_path, metadata, + library: Some(lib), finished_functions: finished_functions.into_boxed_slice(), finished_function_call_trampolines: finished_function_call_trampolines .into_boxed_slice(), diff --git a/lib/engine-native/src/engine.rs b/lib/engine-native/src/engine.rs index 196f743a0d2..1e2b34dd962 100644 --- a/lib/engine-native/src/engine.rs +++ b/lib/engine-native/src/engine.rs @@ -1,7 +1,6 @@ //! Native Engine. use crate::NativeArtifact; -use libloading::Library; use loupe::MemoryUsage; use std::path::Path; use std::sync::Arc; @@ -42,7 +41,6 @@ impl NativeEngine { features, is_cross_compiling, linker, - libraries: vec![], })), target: Arc::new(target), engine_id: EngineId::default(), @@ -74,7 +72,6 @@ impl NativeEngine { prefixer: None, is_cross_compiling: false, linker: Linker::None, - libraries: vec![], })), target: Arc::new(Target::default()), engine_id: EngineId::default(), @@ -259,10 +256,6 @@ pub struct NativeEngineInner { /// The linker to use. linker: Linker, - - /// List of libraries loaded by this engine. - #[loupe(skip)] - libraries: Vec, } impl NativeEngineInner { @@ -323,8 +316,4 @@ impl NativeEngineInner { pub(crate) fn linker(&self) -> Linker { self.linker } - - pub(crate) fn add_library(&mut self, library: Library) { - self.libraries.push(library); - } } From 8fae8ae8dcc0e4ac6bb1a11c87e2da6ef6d0572f Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 01:23:32 -0700 Subject: [PATCH 08/10] Simplified api function --- lib/api/src/externals/function.rs | 72 ++--------- lib/api/src/native.rs | 190 +++++++++++++++--------------- 2 files changed, 105 insertions(+), 157 deletions(-) diff --git a/lib/api/src/externals/function.rs b/lib/api/src/externals/function.rs index 5654e12cd4a..d597d88b96a 100644 --- a/lib/api/src/externals/function.rs +++ b/lib/api/src/externals/function.rs @@ -22,30 +22,6 @@ use wasmer_vm::{ VMFunctionEnvironment, VMFunctionKind, VMTrampoline, }; -/// A function defined in the Wasm module -#[derive(Clone, PartialEq, MemoryUsage)] -pub struct WasmFunctionDefinition { - // Address of the trampoline to do the call. - #[loupe(skip)] - pub(crate) trampoline: VMTrampoline, -} - -/// A function defined in the Host -#[derive(Clone, PartialEq, MemoryUsage)] -pub struct HostFunctionDefinition { - /// If the host function has a custom environment attached - pub(crate) has_env: bool, -} - -/// The inner helper -#[derive(Clone, PartialEq, MemoryUsage)] -pub enum FunctionDefinition { - /// A function defined in the Wasm side - Wasm(WasmFunctionDefinition), - /// A function defined in the Host side - Host(HostFunctionDefinition), -} - /// A WebAssembly `function` instance. /// /// A function instance is the runtime representation of a function. @@ -66,7 +42,6 @@ pub enum FunctionDefinition { #[derive(Clone, PartialEq, MemoryUsage)] pub struct Function { pub(crate) store: Store, - pub(crate) definition: FunctionDefinition, pub(crate) exported: ExportFunction, } @@ -203,7 +178,6 @@ impl Function { Self { store: store.clone(), - definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: false }), exported: ExportFunction { metadata: Some(Arc::new( // # Safety @@ -308,7 +282,6 @@ impl Function { Self { store: store.clone(), - definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { metadata: Some(Arc::new(metadata)), vm_function: VMFunction { @@ -359,8 +332,6 @@ impl Function { Self { store: store.clone(), - definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: false }), - exported: ExportFunction { // TODO: figure out what's going on in this function: it takes an `Env` // param but also marks itself as not having an env @@ -421,7 +392,6 @@ impl Function { Self { store: store.clone(), - definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { metadata: Some(Arc::new(metadata)), vm_function: VMFunction { @@ -469,7 +439,6 @@ impl Function { Self { store: store.clone(), - definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { metadata: Some(Arc::new(metadata)), vm_function: VMFunction { @@ -512,7 +481,7 @@ impl Function { fn call_wasm( &self, - func: &WasmFunctionDefinition, + trampoline: VMTrampoline, params: &[Val], results: &mut [Val], ) -> Result<(), RuntimeError> { @@ -560,7 +529,7 @@ impl Function { if let Err(error) = unsafe { wasmer_call_trampoline( self.exported.vm_function.vmctx, - func.trampoline, + trampoline, self.exported.vm_function.address, values_vec.as_mut_ptr() as *mut u8, ) @@ -649,34 +618,19 @@ impl Function { /// assert_eq!(sum.call(&[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); /// ``` pub fn call(&self, params: &[Val]) -> Result, RuntimeError> { - let mut results = vec![Val::null(); self.result_arity()]; - - match &self.definition { - FunctionDefinition::Wasm(wasm) => { - self.call_wasm(&wasm, params, &mut results)?; - } - // TODO: we can trivially hit this, look into it - _ => unimplemented!("The function definition isn't supported for the moment"), + if let Some(trampoline) = self.exported.vm_function.call_trampoline { + let mut results = vec![Val::null(); self.result_arity()]; + self.call_wasm(trampoline, params, &mut results)?; + return Ok(results.into_boxed_slice()); } - Ok(results.into_boxed_slice()) + unimplemented!("The function definition isn't supported for the moment"); } pub(crate) fn from_vm_export(store: &Store, wasmer_export: ExportFunction) -> Self { - if let Some(trampoline) = wasmer_export.vm_function.call_trampoline { - Self { - store: store.clone(), - definition: FunctionDefinition::Wasm(WasmFunctionDefinition { trampoline }), - exported: wasmer_export, - } - } else { - Self { - store: store.clone(), - definition: FunctionDefinition::Host(HostFunctionDefinition { - has_env: !wasmer_export.vm_function.vmctx.is_null(), - }), - exported: wasmer_export, - } + Self { + store: store.clone(), + exported: wasmer_export, } } @@ -798,11 +752,7 @@ impl Function { } } - Ok(NativeFunc::new( - self.store.clone(), - self.exported.clone(), - self.definition.clone(), - )) + Ok(NativeFunc::new(self.store.clone(), self.exported.clone())) } #[track_caller] diff --git a/lib/api/src/native.rs b/lib/api/src/native.rs index fa9457c1393..41a421502bc 100644 --- a/lib/api/src/native.rs +++ b/lib/api/src/native.rs @@ -10,8 +10,7 @@ use std::marker::PhantomData; use crate::externals::function::{ - DynamicFunctionWithEnv, DynamicFunctionWithoutEnv, FunctionDefinition, HostFunctionDefinition, - VMDynamicFunction, WasmFunctionDefinition, + DynamicFunctionWithEnv, DynamicFunctionWithoutEnv, VMDynamicFunction, }; use crate::{FromToNativeWasmType, Function, RuntimeError, Store, WasmTypeList}; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -23,7 +22,6 @@ use wasmer_vm::{VMDynamicFunctionContext, VMFunctionBody, VMFunctionEnvironment, /// (using the Native ABI). #[derive(Clone)] pub struct NativeFunc { - definition: FunctionDefinition, store: Store, exported: ExportFunction, _phantom: PhantomData<(Args, Rets)>, @@ -36,19 +34,22 @@ where Args: WasmTypeList, Rets: WasmTypeList, { - pub(crate) fn new( - store: Store, - exported: ExportFunction, - definition: FunctionDefinition, - ) -> Self { + pub(crate) fn new(store: Store, exported: ExportFunction) -> Self { Self { - definition, store, exported, _phantom: PhantomData, } } + pub(crate) fn has_env(&self) -> bool { + !self.exported.vm_function.vmctx.is_null() + } + + pub(crate) fn is_host(&self) -> bool { + self.exported.vm_function.instance_ref.is_none() + } + pub(crate) fn vmctx(&self) -> VMFunctionEnvironment { self.exported.vm_function.vmctx } @@ -99,7 +100,6 @@ where fn from(other: NativeFunc) -> Self { Self { store: other.store, - definition: other.definition, exported: other.exported, } } @@ -115,98 +115,96 @@ macro_rules! impl_native_traits { { /// Call the typed func and return results. pub fn call(&self, $( $x: $x, )* ) -> Result { - match self.definition { - FunctionDefinition::Wasm(WasmFunctionDefinition { - trampoline - }) => { - // TODO: when `const fn` related features mature more, we can declare a single array - // of the correct size here. - let mut params_list = [ $( $x.to_native().to_binary() ),* ]; - let mut rets_list_array = Rets::empty_array(); - let rets_list = rets_list_array.as_mut(); - let using_rets_array; - let args_rets: &mut [i128] = if params_list.len() > rets_list.len() { - using_rets_array = false; - params_list.as_mut() - } else { - using_rets_array = true; - for (i, &arg) in params_list.iter().enumerate() { - rets_list[i] = arg; - } - rets_list.as_mut() - }; + if !self.is_host() { + // We assume the trampoline is always going to be present for + // Wasm functions + let trampoline = self.exported.vm_function.call_trampoline.expect("Call trampoline not found in wasm function"); + // TODO: when `const fn` related features mature more, we can declare a single array + // of the correct size here. + let mut params_list = [ $( $x.to_native().to_binary() ),* ]; + let mut rets_list_array = Rets::empty_array(); + let rets_list = rets_list_array.as_mut(); + let using_rets_array; + let args_rets: &mut [i128] = if params_list.len() > rets_list.len() { + using_rets_array = false; + params_list.as_mut() + } else { + using_rets_array = true; + for (i, &arg) in params_list.iter().enumerate() { + rets_list[i] = arg; + } + rets_list.as_mut() + }; + unsafe { + wasmer_vm::wasmer_call_trampoline( + self.vmctx(), + trampoline, + self.address(), + args_rets.as_mut_ptr() as *mut u8, + ) + }?; + let num_rets = rets_list.len(); + if !using_rets_array && num_rets > 0 { + let src_pointer = params_list.as_ptr(); + let rets_list = &mut rets_list_array.as_mut()[0] as *mut i128; unsafe { - wasmer_vm::wasmer_call_trampoline( - self.vmctx(), - trampoline, - self.address(), - args_rets.as_mut_ptr() as *mut u8, - ) - }?; - let num_rets = rets_list.len(); - if !using_rets_array && num_rets > 0 { - let src_pointer = params_list.as_ptr(); - let rets_list = &mut rets_list_array.as_mut()[0] as *mut i128; - unsafe { - // TODO: we can probably remove this copy by doing some clever `transmute`s. - // we know it's not overlapping because `using_rets_array` is false - std::ptr::copy_nonoverlapping(src_pointer, - rets_list, - num_rets); - } + // TODO: we can probably remove this copy by doing some clever `transmute`s. + // we know it's not overlapping because `using_rets_array` is false + std::ptr::copy_nonoverlapping(src_pointer, + rets_list, + num_rets); } - Ok(Rets::from_array(rets_list_array)) - // TODO: When the Host ABI and Wasm ABI are the same, we could do this instead: - // but we can't currently detect whether that's safe. - // - // let results = unsafe { - // wasmer_vm::catch_traps_with_result(self.vmctx, || { - // let f = std::mem::transmute::<_, unsafe extern "C" fn( *mut VMContext, $( $x, )*) -> Rets::CStruct>(self.address()); - // // We always pass the vmctx - // f( self.vmctx, $( $x, )* ) - // }).map_err(RuntimeError::from_trap)? - // }; - // Ok(Rets::from_c_struct(results)) - } - FunctionDefinition::Host(HostFunctionDefinition { - has_env - }) => { - match self.arg_kind() { - VMFunctionKind::Static => { - let results = catch_unwind(AssertUnwindSafe(|| unsafe { - let f = std::mem::transmute::<_, unsafe extern "C" fn( VMFunctionEnvironment, $( $x, )*) -> Rets::CStruct>(self.address()); - // We always pass the vmctx - f( self.vmctx(), $( $x, )* ) - })).map_err(|e| RuntimeError::new(format!("{:?}", e)))?; - Ok(Rets::from_c_struct(results)) - }, - VMFunctionKind::Dynamic => { - let params_list = [ $( $x.to_native().to_value() ),* ]; - let results = if !has_env { - type VMContextWithoutEnv = VMDynamicFunctionContext; - unsafe { - let ctx = self.vmctx().host_env as *mut VMContextWithoutEnv; - (*ctx).ctx.call(¶ms_list)? - } - } else { - type VMContextWithEnv = VMDynamicFunctionContext>; - unsafe { - let ctx = self.vmctx().host_env as *mut VMContextWithEnv; - (*ctx).ctx.call(¶ms_list)? - } - }; - let mut rets_list_array = Rets::empty_array(); - let mut_rets = rets_list_array.as_mut() as *mut [i128] as *mut i128; - for (i, ret) in results.iter().enumerate() { - unsafe { - ret.write_value_to(mut_rets.add(i)); - } + Ok(Rets::from_array(rets_list_array)) + // TODO: When the Host ABI and Wasm ABI are the same, we could do this instead: + // but we can't currently detect whether that's safe. + // + // let results = unsafe { + // wasmer_vm::catch_traps_with_result(self.vmctx, || { + // let f = std::mem::transmute::<_, unsafe extern "C" fn( *mut VMContext, $( $x, )*) -> Rets::CStruct>(self.address()); + // // We always pass the vmctx + // f( self.vmctx, $( $x, )* ) + // }).map_err(RuntimeError::from_trap)? + // }; + // Ok(Rets::from_c_struct(results)) + + } + else { + match self.arg_kind() { + VMFunctionKind::Static => { + let results = catch_unwind(AssertUnwindSafe(|| unsafe { + let f = std::mem::transmute::<_, unsafe extern "C" fn( VMFunctionEnvironment, $( $x, )*) -> Rets::CStruct>(self.address()); + // We always pass the vmctx + f( self.vmctx(), $( $x, )* ) + })).map_err(|e| RuntimeError::new(format!("{:?}", e)))?; + Ok(Rets::from_c_struct(results)) + }, + VMFunctionKind::Dynamic => { + let has_env = self.has_env(); + let params_list = [ $( $x.to_native().to_value() ),* ]; + let results = if !has_env { + type VMContextWithoutEnv = VMDynamicFunctionContext; + unsafe { + let ctx = self.vmctx().host_env as *mut VMContextWithoutEnv; + (*ctx).ctx.call(¶ms_list)? + } + } else { + type VMContextWithEnv = VMDynamicFunctionContext>; + unsafe { + let ctx = self.vmctx().host_env as *mut VMContextWithEnv; + (*ctx).ctx.call(¶ms_list)? + } + }; + let mut rets_list_array = Rets::empty_array(); + let mut_rets = rets_list_array.as_mut() as *mut [i128] as *mut i128; + for (i, ret) in results.iter().enumerate() { + unsafe { + ret.write_value_to(mut_rets.add(i)); } - Ok(Rets::from_array(rets_list_array)) } + Ok(Rets::from_array(rets_list_array)) } - }, + } } } From 1b3fa6100b5ab1e38f96f16f2703603f1237f623 Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 01:25:07 -0700 Subject: [PATCH 09/10] Revert "Fixed unallocated libraries" This reverts commit 7e7b93033c51e8ba73776ce3b91327a673db5b36. --- lib/engine-native/src/artifact.rs | 7 ++----- lib/engine-native/src/engine.rs | 11 +++++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 11972f74c4e..c95e70e8e5f 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -49,9 +49,6 @@ pub struct NativeArtifact { finished_dynamic_function_trampolines: BoxedSlice, func_data_registry: Arc, signatures: BoxedSlice, - #[allow(dead_code)] - #[loupe(skip)] - library: Option, } fn to_compile_error(err: impl Error) -> CompileError { @@ -374,7 +371,6 @@ impl NativeArtifact { .into_boxed_slice(), func_data_registry: Arc::new(FuncDataRegistry::new()), signatures: signatures.into_boxed_slice(), - library: None, }) } @@ -467,10 +463,11 @@ impl NativeArtifact { .collect::>() }; + engine_inner.add_library(lib); + Ok(Self { sharedobject_path, metadata, - library: Some(lib), finished_functions: finished_functions.into_boxed_slice(), finished_function_call_trampolines: finished_function_call_trampolines .into_boxed_slice(), diff --git a/lib/engine-native/src/engine.rs b/lib/engine-native/src/engine.rs index 1e2b34dd962..196f743a0d2 100644 --- a/lib/engine-native/src/engine.rs +++ b/lib/engine-native/src/engine.rs @@ -1,6 +1,7 @@ //! Native Engine. use crate::NativeArtifact; +use libloading::Library; use loupe::MemoryUsage; use std::path::Path; use std::sync::Arc; @@ -41,6 +42,7 @@ impl NativeEngine { features, is_cross_compiling, linker, + libraries: vec![], })), target: Arc::new(target), engine_id: EngineId::default(), @@ -72,6 +74,7 @@ impl NativeEngine { prefixer: None, is_cross_compiling: false, linker: Linker::None, + libraries: vec![], })), target: Arc::new(Target::default()), engine_id: EngineId::default(), @@ -256,6 +259,10 @@ pub struct NativeEngineInner { /// The linker to use. linker: Linker, + + /// List of libraries loaded by this engine. + #[loupe(skip)] + libraries: Vec, } impl NativeEngineInner { @@ -316,4 +323,8 @@ impl NativeEngineInner { pub(crate) fn linker(&self) -> Linker { self.linker } + + pub(crate) fn add_library(&mut self, library: Library) { + self.libraries.push(library); + } } From 9befaf64be6bba3595f24cfa8c783c0aec6250ff Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 1 May 2021 02:15:18 -0700 Subject: [PATCH 10/10] Simplified function environment --- lib/api/src/externals/function.rs | 92 +++++-------------------------- lib/api/src/native.rs | 19 +------ 2 files changed, 16 insertions(+), 95 deletions(-) diff --git a/lib/api/src/externals/function.rs b/lib/api/src/externals/function.rs index d597d88b96a..6963ded2d4a 100644 --- a/lib/api/src/externals/function.rs +++ b/lib/api/src/externals/function.rs @@ -110,6 +110,8 @@ where (env, metadata) } +impl WasmerEnv for WithoutEnv {} + impl Function { /// Creates a new host `Function` (dynamic) with the provided signature. /// @@ -149,59 +151,10 @@ impl Function { FT: Into, F: Fn(&[Val]) -> Result, RuntimeError> + 'static + Send + Sync, { - let ty: FunctionType = ty.into(); - let dynamic_ctx: VMDynamicFunctionContext = - VMDynamicFunctionContext::from_context(DynamicFunctionWithoutEnv { - func: Arc::new(func), - store: store.clone(), - function_type: ty.clone(), - }); - // We don't yet have the address with the Wasm ABI signature. - // The engine linker will replace the address with one pointing to a - // generated dynamic trampoline. - let address = std::ptr::null() as *const VMFunctionBody; - let host_env = Box::into_raw(Box::new(dynamic_ctx)) as *mut _; - let vmctx = VMFunctionEnvironment { host_env }; - let host_env_clone_fn: fn(*mut c_void) -> *mut c_void = |ptr| { - let duped_env: VMDynamicFunctionContext = unsafe { - let ptr: *mut VMDynamicFunctionContext = ptr as _; - let item: &VMDynamicFunctionContext = &*ptr; - item.clone() - }; - Box::into_raw(Box::new(duped_env)) as _ - }; - let host_env_drop_fn: fn(*mut c_void) = |ptr: *mut c_void| { - unsafe { - Box::from_raw(ptr as *mut VMDynamicFunctionContext) - }; + let new_func = move |_first: &WithoutEnv, args: &[Val]| -> Result, RuntimeError> { + func(args) }; - - Self { - store: store.clone(), - exported: ExportFunction { - metadata: Some(Arc::new( - // # Safety - // - All these functions work on all threads - // - The host env is `Send`. - unsafe { - ExportFunctionMetadata::new( - host_env, - None, - host_env_clone_fn, - host_env_drop_fn, - ) - }, - )), - vm_function: VMFunction { - address, - kind: VMFunctionKind::Dynamic, - vmctx, - signature: ty, - call_trampoline: None, - instance_ref: None, - }, - }, - } + Self::new_with_env(store, ty, WithoutEnv, new_func) } /// Creates a new host `Function` (dynamic) with the provided signature and environment. @@ -256,8 +209,8 @@ impl Function { Env: Sized + WasmerEnv + 'static, { let ty: FunctionType = ty.into(); - let dynamic_ctx: VMDynamicFunctionContext> = - VMDynamicFunctionContext::from_context(DynamicFunctionWithEnv { + let dynamic_ctx: VMDynamicFunctionContext> = + VMDynamicFunctionContext::from_context(DynamicFunction { env: Box::new(env), func: Arc::new(func), store: store.clone(), @@ -265,13 +218,13 @@ impl Function { }); let import_init_function_ptr: for<'a> fn(&'a mut _, &'a _) -> Result<(), _> = - |env: &mut VMDynamicFunctionContext>, + |env: &mut VMDynamicFunctionContext>, instance: &crate::Instance| { Env::init_with_instance(&mut *env.ctx.env, instance) }; let (host_env, metadata) = build_export_function_metadata::< - VMDynamicFunctionContext>, + VMDynamicFunctionContext>, >(dynamic_ctx, import_init_function_ptr); // We don't yet have the address with the Wasm ABI signature. @@ -790,27 +743,7 @@ pub(crate) trait VMDynamicFunction: Send + Sync { fn store(&self) -> &Store; } -#[derive(Clone)] -pub(crate) struct DynamicFunctionWithoutEnv { - #[allow(clippy::type_complexity)] - func: Arc Result, RuntimeError> + 'static + Send + Sync>, - function_type: FunctionType, - store: Store, -} - -impl VMDynamicFunction for DynamicFunctionWithoutEnv { - fn call(&self, args: &[Val]) -> Result, RuntimeError> { - (*self.func)(&args) - } - fn function_type(&self) -> &FunctionType { - &self.function_type - } - fn store(&self) -> &Store { - &self.store - } -} - -pub(crate) struct DynamicFunctionWithEnv +pub(crate) struct DynamicFunction where Env: Sized + 'static + Send + Sync, { @@ -821,7 +754,7 @@ where env: Box, } -impl Clone for DynamicFunctionWithEnv { +impl Clone for DynamicFunction { fn clone(&self) -> Self { Self { env: self.env.clone(), @@ -832,7 +765,7 @@ impl Clone for DynamicFunctionWithEn } } -impl VMDynamicFunction for DynamicFunctionWithEnv +impl VMDynamicFunction for DynamicFunction where Env: Sized + 'static + Send + Sync, { @@ -1235,6 +1168,7 @@ mod inner { /// An empty struct to help Rust typing to determine /// when a `HostFunction` does not have an environment. + #[derive(Clone)] pub struct WithoutEnv; impl HostFunctionKind for WithoutEnv {} diff --git a/lib/api/src/native.rs b/lib/api/src/native.rs index 41a421502bc..5f46254534c 100644 --- a/lib/api/src/native.rs +++ b/lib/api/src/native.rs @@ -9,9 +9,7 @@ //! ``` use std::marker::PhantomData; -use crate::externals::function::{ - DynamicFunctionWithEnv, DynamicFunctionWithoutEnv, VMDynamicFunction, -}; +use crate::externals::function::{DynamicFunction, VMDynamicFunction}; use crate::{FromToNativeWasmType, Function, RuntimeError, Store, WasmTypeList}; use std::panic::{catch_unwind, AssertUnwindSafe}; use wasmer_engine::ExportFunction; @@ -42,10 +40,6 @@ where } } - pub(crate) fn has_env(&self) -> bool { - !self.exported.vm_function.vmctx.is_null() - } - pub(crate) fn is_host(&self) -> bool { self.exported.vm_function.instance_ref.is_none() } @@ -180,16 +174,9 @@ macro_rules! impl_native_traits { Ok(Rets::from_c_struct(results)) }, VMFunctionKind::Dynamic => { - let has_env = self.has_env(); let params_list = [ $( $x.to_native().to_value() ),* ]; - let results = if !has_env { - type VMContextWithoutEnv = VMDynamicFunctionContext; - unsafe { - let ctx = self.vmctx().host_env as *mut VMContextWithoutEnv; - (*ctx).ctx.call(¶ms_list)? - } - } else { - type VMContextWithEnv = VMDynamicFunctionContext>; + let results = { + type VMContextWithEnv = VMDynamicFunctionContext>; unsafe { let ctx = self.vmctx().host_env as *mut VMContextWithEnv; (*ctx).ctx.call(¶ms_list)?