diff --git a/lib/api/src/externals/function.rs b/lib/api/src/externals/function.rs index ac0b5f26b..9a373c6b7 100644 --- a/lib/api/src/externals/function.rs +++ b/lib/api/src/externals/function.rs @@ -96,7 +96,7 @@ impl Function { address, kind: VMFunctionKind::Dynamic, vmctx, - function_ptr: 0, + function_ptr: None, signature: ty.clone(), }, } @@ -126,7 +126,7 @@ impl Function { pub fn new_with_env(store: &Store, ty: &FunctionType, env: Env, func: F) -> Self where F: Fn(&mut Env, &[Val]) -> Result, RuntimeError> + 'static, - Env: Sized + 'static, + Env: Sized + crate::WasmerPostInstantiate + 'static, { let dynamic_ctx = VMDynamicFunctionContext::from_context(VMDynamicFunctionWithEnv { env: RefCell::new(env), @@ -140,6 +140,9 @@ impl Function { let vmctx = FunctionExtraData { host_env: Box::into_raw(Box::new(dynamic_ctx)) as *mut _, }; + // TODO: look into removing transmute by changing API type signatures + let function_ptr = Some(unsafe { std::mem::transmute::(Env::finish) }); + //dbg!(function_ptr); Self { store: store.clone(), @@ -148,8 +151,7 @@ impl Function { address, kind: VMFunctionKind::Dynamic, vmctx, - // TODO: - function_ptr: 0, + function_ptr, signature: ty.clone(), }, } @@ -193,8 +195,9 @@ impl Function { address, vmctx, signature, - // TODO: - function_ptr: 0, + // TODO: figure out what's going on in this function: it takes an `Env` + // param but also marks itself as not having an env + function_ptr: None, kind: VMFunctionKind::Static, }, } @@ -241,8 +244,9 @@ impl Function { let vmctx = FunctionExtraData { host_env: Box::into_raw(box_env) as *mut _, }; - let function_ptr = Env::finish as usize; - dbg!(function_ptr); + // TODO: look into removing transmute by changing API type signatures + let function_ptr = Some(unsafe { std::mem::transmute::(Env::finish) }); + //dbg!(function_ptr as usize); let signature = function.ty(); Self { diff --git a/lib/api/src/instance.rs b/lib/api/src/instance.rs index 61f51a43a..c9dd1c621 100644 --- a/lib/api/src/instance.rs +++ b/lib/api/src/instance.rs @@ -73,7 +73,7 @@ impl Instance { pub fn new(module: &Module, resolver: &dyn Resolver) -> Result { let store = module.store(); - let (handle, thunks) = module.instantiate(resolver)?; + let handle = module.instantiate(resolver)?; let exports = module .exports() @@ -91,11 +91,10 @@ impl Instance { exports, }; - for (func, env) in thunks.iter() { - dbg!(func, env); - unsafe { - func(*env, (&instance) as *const _ as *const _); - } + unsafe { + instance + .handle + .initialize_host_envs(&instance as *const _ as *const _); } Ok(instance) diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index 74b361a8d..714991cba 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -261,18 +261,9 @@ impl Module { pub(crate) fn instantiate( &self, resolver: &dyn Resolver, - ) -> Result< - ( - InstanceHandle, - Vec<( - fn(*mut std::ffi::c_void, *const std::ffi::c_void), - *mut std::ffi::c_void, - )>, - ), - InstantiationError, - > { + ) -> Result { unsafe { - let (instance_handle, thunks) = + let instance_handle = self.artifact .instantiate(self.store.tunables(), resolver, Box::new(()))?; @@ -283,7 +274,7 @@ impl Module { // instance tables. self.artifact.finish_instantiation(&instance_handle)?; - Ok((instance_handle, thunks)) + Ok(instance_handle) } } diff --git a/lib/api/src/native.rs b/lib/api/src/native.rs index 9957e23bb..5a02ac8e3 100644 --- a/lib/api/src/native.rs +++ b/lib/api/src/native.rs @@ -70,7 +70,7 @@ where vmctx: other.vmctx, signature, // TODO: - function_ptr: 0, + function_ptr: None, kind: other.arg_kind, } } @@ -91,7 +91,7 @@ where vmctx: other.vmctx, signature, // TODO: - function_ptr: 0, + function_ptr: None, kind: other.arg_kind, }, } diff --git a/lib/api/src/types.rs b/lib/api/src/types.rs index cea1336d6..07b0ea1f7 100644 --- a/lib/api/src/types.rs +++ b/lib/api/src/types.rs @@ -77,7 +77,8 @@ impl ValFuncRef for Val { address: item.func_ptr, signature, // TODO: - function_ptr: 0, + // figure out if we ever need a value here: need testing with complicated import patterns + function_ptr: None, // All functions in tables are already Static (as dynamic functions // are converted to use the trampolines with static signatures). kind: wasmer_vm::VMFunctionKind::Static, diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index 5719fa6d2..215e8bc26 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -86,16 +86,7 @@ pub trait Artifact: Send + Sync + Upcastable { tunables: &dyn Tunables, resolver: &dyn Resolver, host_state: Box, - ) -> Result< - ( - InstanceHandle, - Vec<( - fn(*mut std::ffi::c_void, *const std::ffi::c_void), - *mut std::ffi::c_void, - )>, - ), - InstantiationError, - > { + ) -> Result { self.preinstantiate()?; let module = self.module(); @@ -110,13 +101,17 @@ pub trait Artifact: Send + Sync + Upcastable { let mut thunks = vec![]; // ------------ - for func in imports.functions.values() { - unsafe { - let finish: fn(*mut std::ffi::c_void, instance: *const std::ffi::c_void) = - std::mem::transmute(func.function_ptr); - dbg!(func.extra_data.host_env); - thunks.push((finish, func.extra_data.host_env)); - } + for (func_init, func) in imports + .host_function_env_initializers + .values() + .cloned() + .zip(imports.functions.values()) + { + let host_env = unsafe { + //dbg!(func.extra_data.host_env); + func.extra_data.host_env + }; + thunks.push((func_init, host_env)); } // ------------ @@ -144,9 +139,10 @@ pub trait Artifact: Send + Sync + Upcastable { imports, self.signatures().clone(), host_state, + thunks, ) .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?; - Ok((handle, thunks)) + Ok(handle) } /// Finishes the instantiation of a just created `InstanceHandle`. diff --git a/lib/engine/src/resolver.rs b/lib/engine/src/resolver.rs index 0e27426f6..6ef8650d7 100644 --- a/lib/engine/src/resolver.rs +++ b/lib/engine/src/resolver.rs @@ -125,6 +125,9 @@ pub fn resolve_imports( _table_styles: &PrimaryMap, ) -> Result { let mut function_imports = PrimaryMap::with_capacity(module.num_imported_functions); + // TODO: account for imported functions without env / from other Wasm instances + let mut host_function_env_initializers = + PrimaryMap::with_capacity(module.num_imported_functions); let mut table_imports = PrimaryMap::with_capacity(module.num_imported_tables); let mut memory_imports = PrimaryMap::with_capacity(module.num_imported_memories); let mut global_imports = PrimaryMap::with_capacity(module.num_imported_globals); @@ -168,9 +171,9 @@ pub fn resolve_imports( function_imports.push(VMFunctionImport { body: address, extra_data: f.vmctx, - // TODO: - function_ptr: f.function_ptr, }); + + host_function_env_initializers.push(f.function_ptr); } Export::Table(ref t) => { table_imports.push(VMTableImport { @@ -224,6 +227,7 @@ pub fn resolve_imports( Ok(Imports::new( function_imports, + host_function_env_initializers, table_imports, memory_imports, global_imports, diff --git a/lib/vm/src/export.rs b/lib/vm/src/export.rs index 23672aa8f..fde459e44 100644 --- a/lib/vm/src/export.rs +++ b/lib/vm/src/export.rs @@ -32,7 +32,7 @@ pub struct ExportFunction { /// Pointer to the containing `VMContext`. pub vmctx: crate::vmcontext::FunctionExtraData, /// temp code to set vmctx for host functions - pub function_ptr: usize, + pub function_ptr: Option, /// The function type, used for compatibility checking. pub signature: FunctionType, /// The function kind (it defines how it's the signature that provided `address` have) diff --git a/lib/vm/src/imports.rs b/lib/vm/src/imports.rs index fb5da5099..80c7ce19c 100644 --- a/lib/vm/src/imports.rs +++ b/lib/vm/src/imports.rs @@ -11,6 +11,12 @@ pub struct Imports { /// Resolved addresses for imported functions. pub functions: BoxedSlice, + /// Initializers for host function environments. This is split out from `functions` + /// because the generated code never needs to touch this and the extra wasted + /// space may affect Wasm runtime performance due to increased cache pressure. + pub host_function_env_initializers: + BoxedSlice>, + /// Resolved addresses for imported tables. pub tables: BoxedSlice, @@ -25,12 +31,17 @@ impl Imports { /// Construct a new `Imports` instance. pub fn new( function_imports: PrimaryMap, + host_function_env_initializers: PrimaryMap< + FunctionIndex, + Option, + >, table_imports: PrimaryMap, memory_imports: PrimaryMap, global_imports: PrimaryMap, ) -> Self { Self { functions: function_imports.into_boxed_slice(), + host_function_env_initializers: host_function_env_initializers.into_boxed_slice(), tables: table_imports.into_boxed_slice(), memories: memory_imports.into_boxed_slice(), globals: global_imports.into_boxed_slice(), @@ -41,6 +52,7 @@ impl Imports { pub fn none() -> Self { Self { functions: PrimaryMap::new().into_boxed_slice(), + host_function_env_initializers: PrimaryMap::new().into_boxed_slice(), tables: PrimaryMap::new().into_boxed_slice(), memories: PrimaryMap::new().into_boxed_slice(), globals: PrimaryMap::new().into_boxed_slice(), diff --git a/lib/vm/src/instance.rs b/lib/vm/src/instance.rs index 055d57e2c..b77a5b6df 100644 --- a/lib/vm/src/instance.rs +++ b/lib/vm/src/instance.rs @@ -100,6 +100,17 @@ pub(crate) struct Instance { /// Handler run when `SIGBUS`, `SIGFPE`, `SIGILL`, or `SIGSEGV` are caught by the instance thread. pub(crate) signal_handler: Cell>>, + /// TODO: document this + /// Functions to initialize the host environments in the imports. + /// Do we want to drain this? There's probably no reason to keep this memory + /// around once we've used it. + /// + /// Be sure to test with serialize/deserialize and imported functions from other Wasm modules. + import_initializers: Vec<( + Option, + *mut std::ffi::c_void, + )>, + /// Additional context used by compiled wasm code. This field is last, and /// represents a dynamically-sized array that extends beyond the nominal /// end of the struct (similar to a flexible array member). @@ -141,6 +152,14 @@ impl Instance { unsafe { &*self.imported_functions_ptr().add(index) } } + /// TODO: document this + fn imported_function_env_initializer( + &self, + index: FunctionIndex, + ) -> Option { + self.import_initializers[index.as_u32() as usize].0 + } + /// Return a pointer to the `VMFunctionImport`s. fn imported_functions_ptr(&self) -> *mut VMFunctionImport { unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_functions_begin()) } @@ -298,11 +317,12 @@ impl Instance { crate::vmcontext::FunctionExtraData { vmctx: self.vmctx_ptr(), }, - 0, + None, ) } else { let import = self.imported_function(*index); - (import.body, import.extra_data, import.function_ptr) + let initializer = self.imported_function_env_initializer(*index); + (import.body, import.extra_data, initializer) }; let signature = self.module.signatures[*sig_index].clone(); ExportFunction { @@ -815,6 +835,10 @@ impl InstanceHandle { imports: Imports, vmshared_signatures: BoxedSlice, host_state: Box, + import_initializers: Vec<( + Option, + *mut std::ffi::c_void, + )>, ) -> Result { // TODO: investigate `vmctx_tables` and `vmctx_memories`: both of these // appear to be dropped in this function which may cause memory problems @@ -859,6 +883,7 @@ impl InstanceHandle { passive_data, host_state, signal_handler: Cell::new(None), + import_initializers, vmctx: VMContext {}, }; let layout = instance.alloc_layout(); @@ -1076,6 +1101,17 @@ impl InstanceHandle { unsafe { &*(self.instance as *const Instance) } } + /// TODO: document this + /// Initializes the host environments. + pub unsafe fn initialize_host_envs(&self, instance_ptr: *const std::ffi::c_void) { + for (func, env) in self.instance().import_initializers.iter() { + if let Some(f) = func { + dbg!(f, env); + f(*env, instance_ptr); + } + } + } + /// Deallocates memory associated with this instance. /// /// # Safety diff --git a/lib/vm/src/vmcontext.rs b/lib/vm/src/vmcontext.rs index d1de6b311..49a75c598 100644 --- a/lib/vm/src/vmcontext.rs +++ b/lib/vm/src/vmcontext.rs @@ -47,10 +47,6 @@ pub struct VMFunctionImport { /// A pointer to the `VMContext` that owns the function or host data. pub extra_data: FunctionExtraData, - - /// temporary hack - /// Only used by host env - pub function_ptr: usize, } #[cfg(test)] diff --git a/lib/vm/src/vmoffsets.rs b/lib/vm/src/vmoffsets.rs index 66406d003..b18408165 100644 --- a/lib/vm/src/vmoffsets.rs +++ b/lib/vm/src/vmoffsets.rs @@ -109,7 +109,7 @@ impl VMOffsets { /// /// [`VMFunctionImport`]: crate::vmcontext::VMFunctionImport pub fn size_of_vmfunction_import(&self) -> u8 { - 3 * self.pointer_size + 2 * self.pointer_size } } diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index d0733055f..701977959 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -188,7 +188,6 @@ impl WasiEnv { /// Get a reference to the memory pub fn memory(&self) -> &Memory { - dbg!("Getting memory", &self.memory); unsafe { &*self.memory } }