mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 13:18:20 +00:00
Fix memory leak in host function envs
This commit is contained in:
77
lib/api/src/externals/function.rs
vendored
77
lib/api/src/externals/function.rs
vendored
@@ -12,6 +12,7 @@ pub use inner::{UnsafeMutableEnv, WithUnsafeMutableEnv};
|
|||||||
|
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::sync::Arc;
|
||||||
use wasmer_engine::{Export, ExportFunction};
|
use wasmer_engine::{Export, ExportFunction};
|
||||||
use wasmer_vm::{
|
use wasmer_vm::{
|
||||||
raise_user_trap, resume_panic, wasmer_call_trampoline, VMCallerCheckedAnyfunc,
|
raise_user_trap, resume_panic, wasmer_call_trampoline, VMCallerCheckedAnyfunc,
|
||||||
@@ -87,10 +88,11 @@ impl Function {
|
|||||||
where
|
where
|
||||||
F: Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
|
F: Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
|
||||||
{
|
{
|
||||||
let dynamic_ctx = VMDynamicFunctionContext::from_context(VMDynamicFunctionWithoutEnv {
|
let dynamic_ctx: VMDynamicFunctionContext<VMDynamicFunctionWithoutEnv> =
|
||||||
func: Box::new(func),
|
VMDynamicFunctionContext::from_context(VMDynamicFunctionWithoutEnv {
|
||||||
function_type: ty.clone(),
|
func: Box::new(func),
|
||||||
});
|
function_type: ty.clone(),
|
||||||
|
});
|
||||||
// We don't yet have the address with the Wasm ABI signature.
|
// We don't yet have the address with the Wasm ABI signature.
|
||||||
// The engine linker will replace the address with one pointing to a
|
// The engine linker will replace the address with one pointing to a
|
||||||
// generated dynamic trampoline.
|
// generated dynamic trampoline.
|
||||||
@@ -98,20 +100,27 @@ impl Function {
|
|||||||
let vmctx = VMFunctionEnvironment {
|
let vmctx = VMFunctionEnvironment {
|
||||||
host_env: Box::into_raw(Box::new(dynamic_ctx)) as *mut _,
|
host_env: Box::into_raw(Box::new(dynamic_ctx)) as *mut _,
|
||||||
};
|
};
|
||||||
|
let host_env_drop_fn: Option<fn(*mut std::ffi::c_void)> =
|
||||||
|
Some(|ptr: *mut std::ffi::c_void| {
|
||||||
|
unsafe {
|
||||||
|
Box::from_raw(ptr as *mut VMDynamicFunctionContext<VMDynamicFunctionWithoutEnv>)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: false }),
|
definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: false }),
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
import_init_function_ptr: None,
|
import_init_function_ptr: None,
|
||||||
vm_function: VMExportFunction {
|
host_env_drop_fn,
|
||||||
|
vm_function: Arc::new(VMExportFunction {
|
||||||
address,
|
address,
|
||||||
kind: VMFunctionKind::Dynamic,
|
kind: VMFunctionKind::Dynamic,
|
||||||
vmctx,
|
vmctx,
|
||||||
signature: ty.clone(),
|
signature: ty.clone(),
|
||||||
call_trampoline: None,
|
call_trampoline: None,
|
||||||
instance_allocator: None,
|
instance_allocator: None,
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,11 +152,12 @@ impl Function {
|
|||||||
F: Fn(&Env, &[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
|
F: Fn(&Env, &[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
|
||||||
Env: Sized + WasmerEnv + 'static,
|
Env: Sized + WasmerEnv + 'static,
|
||||||
{
|
{
|
||||||
let dynamic_ctx = VMDynamicFunctionContext::from_context(VMDynamicFunctionWithEnv {
|
let dynamic_ctx: VMDynamicFunctionContext<VMDynamicFunctionWithEnv<Env>> =
|
||||||
env: Box::new(env),
|
VMDynamicFunctionContext::from_context(VMDynamicFunctionWithEnv {
|
||||||
func: Box::new(func),
|
env: Box::new(env),
|
||||||
function_type: ty.clone(),
|
func: Box::new(func),
|
||||||
});
|
function_type: ty.clone(),
|
||||||
|
});
|
||||||
// We don't yet have the address with the Wasm ABI signature.
|
// We don't yet have the address with the Wasm ABI signature.
|
||||||
// The engine linker will replace the address with one pointing to a
|
// The engine linker will replace the address with one pointing to a
|
||||||
// generated dynamic trampoline.
|
// generated dynamic trampoline.
|
||||||
@@ -155,26 +165,44 @@ impl Function {
|
|||||||
let vmctx = VMFunctionEnvironment {
|
let vmctx = VMFunctionEnvironment {
|
||||||
host_env: Box::into_raw(Box::new(dynamic_ctx)) as *mut _,
|
host_env: Box::into_raw(Box::new(dynamic_ctx)) as *mut _,
|
||||||
};
|
};
|
||||||
// TODO: look into removing transmute by changing API type signatures
|
let import_init_function_ptr: fn(_, _) -> Result<(), _> =
|
||||||
|
|ptr: *mut std::ffi::c_void, instance: *const std::ffi::c_void| {
|
||||||
|
let ptr = ptr as *mut VMDynamicFunctionContext<VMDynamicFunctionWithEnv<Env>>;
|
||||||
|
unsafe {
|
||||||
|
let env = &mut *ptr;
|
||||||
|
let env: &mut Env = &mut *env.ctx.env;
|
||||||
|
let instance = &*(instance as *const crate::Instance);
|
||||||
|
Env::init_with_instance(env, instance)
|
||||||
|
}
|
||||||
|
};
|
||||||
let import_init_function_ptr = Some(unsafe {
|
let import_init_function_ptr = Some(unsafe {
|
||||||
std::mem::transmute::<fn(_, _) -> Result<(), _>, fn(_, _) -> Result<(), _>>(
|
std::mem::transmute::<fn(_, _) -> Result<(), _>, fn(_, _) -> Result<(), _>>(
|
||||||
Env::init_with_instance,
|
import_init_function_ptr,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
let host_env_drop_fn: Option<fn(*mut std::ffi::c_void)> =
|
||||||
|
Some(|ptr: *mut std::ffi::c_void| {
|
||||||
|
unsafe {
|
||||||
|
Box::from_raw(
|
||||||
|
ptr as *mut VMDynamicFunctionContext<VMDynamicFunctionWithEnv<Env>>,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }),
|
definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }),
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
import_init_function_ptr,
|
import_init_function_ptr,
|
||||||
vm_function: VMExportFunction {
|
host_env_drop_fn,
|
||||||
|
vm_function: Arc::new(VMExportFunction {
|
||||||
address,
|
address,
|
||||||
kind: VMFunctionKind::Dynamic,
|
kind: VMFunctionKind::Dynamic,
|
||||||
vmctx,
|
vmctx,
|
||||||
signature: ty.clone(),
|
signature: ty.clone(),
|
||||||
call_trampoline: None,
|
call_trampoline: None,
|
||||||
instance_allocator: None,
|
instance_allocator: None,
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,14 +249,15 @@ impl Function {
|
|||||||
// TODO: figure out what's going on in this function: it takes an `Env`
|
// TODO: figure out what's going on in this function: it takes an `Env`
|
||||||
// param but also marks itself as not having an env
|
// param but also marks itself as not having an env
|
||||||
import_init_function_ptr: None,
|
import_init_function_ptr: None,
|
||||||
vm_function: VMExportFunction {
|
host_env_drop_fn: None,
|
||||||
|
vm_function: Arc::new(VMExportFunction {
|
||||||
address,
|
address,
|
||||||
vmctx,
|
vmctx,
|
||||||
signature,
|
signature,
|
||||||
kind: VMFunctionKind::Static,
|
kind: VMFunctionKind::Static,
|
||||||
call_trampoline: None,
|
call_trampoline: None,
|
||||||
instance_allocator: None,
|
instance_allocator: None,
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,6 +307,11 @@ impl Function {
|
|||||||
let vmctx = VMFunctionEnvironment {
|
let vmctx = VMFunctionEnvironment {
|
||||||
host_env: Box::into_raw(box_env) as *mut _,
|
host_env: Box::into_raw(box_env) as *mut _,
|
||||||
};
|
};
|
||||||
|
let host_env_drop_fn: Option<fn(*mut std::ffi::c_void)> =
|
||||||
|
Some(|ptr: *mut std::ffi::c_void| {
|
||||||
|
unsafe { Box::from_raw(ptr as *mut Env) };
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: look into removing transmute by changing API type signatures
|
// TODO: look into removing transmute by changing API type signatures
|
||||||
let import_init_function_ptr = Some(unsafe {
|
let import_init_function_ptr = Some(unsafe {
|
||||||
std::mem::transmute::<fn(_, _) -> Result<(), _>, fn(_, _) -> Result<(), _>>(
|
std::mem::transmute::<fn(_, _) -> Result<(), _>, fn(_, _) -> Result<(), _>>(
|
||||||
@@ -291,14 +325,15 @@ impl Function {
|
|||||||
definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }),
|
definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }),
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
import_init_function_ptr,
|
import_init_function_ptr,
|
||||||
vm_function: VMExportFunction {
|
host_env_drop_fn,
|
||||||
|
vm_function: Arc::new(VMExportFunction {
|
||||||
address,
|
address,
|
||||||
kind: VMFunctionKind::Static,
|
kind: VMFunctionKind::Static,
|
||||||
vmctx,
|
vmctx,
|
||||||
signature,
|
signature,
|
||||||
call_trampoline: None,
|
call_trampoline: None,
|
||||||
instance_allocator: None,
|
instance_allocator: None,
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,14 +379,14 @@ impl Function {
|
|||||||
definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }),
|
definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }),
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
import_init_function_ptr,
|
import_init_function_ptr,
|
||||||
vm_function: VMExportFunction {
|
vm_function: Arc::new(VMExportFunction {
|
||||||
address,
|
address,
|
||||||
kind: VMFunctionKind::Static,
|
kind: VMFunctionKind::Static,
|
||||||
vmctx,
|
vmctx,
|
||||||
signature,
|
signature,
|
||||||
call_trampoline: None,
|
call_trampoline: None,
|
||||||
instance_allocator: None,
|
instance_allocator: None,
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use crate::externals::function::{
|
|||||||
};
|
};
|
||||||
use crate::{FromToNativeWasmType, Function, FunctionType, RuntimeError, Store, WasmTypeList};
|
use crate::{FromToNativeWasmType, Function, FunctionType, RuntimeError, Store, WasmTypeList};
|
||||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||||
|
use std::sync::Arc;
|
||||||
use wasmer_engine::ExportFunction;
|
use wasmer_engine::ExportFunction;
|
||||||
use wasmer_types::NativeWasmType;
|
use wasmer_types::NativeWasmType;
|
||||||
use wasmer_vm::{
|
use wasmer_vm::{
|
||||||
@@ -88,14 +89,15 @@ where
|
|||||||
Self {
|
Self {
|
||||||
// TODO:
|
// TODO:
|
||||||
import_init_function_ptr: None,
|
import_init_function_ptr: None,
|
||||||
vm_function: VMExportFunction {
|
host_env_drop_fn: None,
|
||||||
|
vm_function: Arc::new(VMExportFunction {
|
||||||
address: other.address,
|
address: other.address,
|
||||||
vmctx: other.vmctx,
|
vmctx: other.vmctx,
|
||||||
signature,
|
signature,
|
||||||
kind: other.arg_kind,
|
kind: other.arg_kind,
|
||||||
call_trampoline: None,
|
call_trampoline: None,
|
||||||
instance_allocator: None,
|
instance_allocator: None,
|
||||||
},
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,14 +115,15 @@ where
|
|||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
// TODO:
|
// TODO:
|
||||||
import_init_function_ptr: None,
|
import_init_function_ptr: None,
|
||||||
vm_function: VMExportFunction {
|
host_env_drop_fn: None,
|
||||||
|
vm_function: Arc::new(VMExportFunction {
|
||||||
address: other.address,
|
address: other.address,
|
||||||
vmctx: other.vmctx,
|
vmctx: other.vmctx,
|
||||||
signature,
|
signature,
|
||||||
kind: other.arg_kind,
|
kind: other.arg_kind,
|
||||||
call_trampoline: None,
|
call_trampoline: None,
|
||||||
instance_allocator: None,
|
instance_allocator: None,
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ impl ValFuncRef for Val {
|
|||||||
// TODO:
|
// TODO:
|
||||||
// figure out if we ever need a value here: need testing with complicated import patterns
|
// figure out if we ever need a value here: need testing with complicated import patterns
|
||||||
import_init_function_ptr: None,
|
import_init_function_ptr: None,
|
||||||
vm_function: wasmer_vm::VMExportFunction {
|
host_env_drop_fn: None,
|
||||||
|
vm_function: std::sync::Arc::new(wasmer_vm::VMExportFunction {
|
||||||
address: item.func_ptr,
|
address: item.func_ptr,
|
||||||
signature,
|
signature,
|
||||||
// All functions in tables are already Static (as dynamic functions
|
// All functions in tables are already Static (as dynamic functions
|
||||||
@@ -86,7 +87,7 @@ impl ValFuncRef for Val {
|
|||||||
vmctx: item.vmctx,
|
vmctx: item.vmctx,
|
||||||
call_trampoline: None,
|
call_trampoline: None,
|
||||||
instance_allocator: None,
|
instance_allocator: None,
|
||||||
},
|
}),
|
||||||
};
|
};
|
||||||
let f = Function::from_vm_export(store, export);
|
let f = Function::from_vm_export(store, export);
|
||||||
Self::FuncRef(f)
|
Self::FuncRef(f)
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ pub trait Artifact: Send + Sync + Upcastable {
|
|||||||
|
|
||||||
let module = self.module();
|
let module = self.module();
|
||||||
let (instance_ptr, offsets) = InstanceHandle::allocate_instance(&module);
|
let (instance_ptr, offsets) = InstanceHandle::allocate_instance(&module);
|
||||||
let (imports, import_initializers) = {
|
let (imports, import_envs) = {
|
||||||
let mut imports = resolve_imports(
|
let mut imports = resolve_imports(
|
||||||
&module,
|
&module,
|
||||||
resolver,
|
resolver,
|
||||||
@@ -108,9 +108,9 @@ pub trait Artifact: Send + Sync + Upcastable {
|
|||||||
|
|
||||||
// Get the `WasmerEnv::init_with_instance` function pointers and the pointers
|
// Get the `WasmerEnv::init_with_instance` function pointers and the pointers
|
||||||
// to the envs to call it on.
|
// to the envs to call it on.
|
||||||
let import_initializers: Vec<(_, _)> = imports.get_import_initializers();
|
let import_envs = imports.get_import_initializers();
|
||||||
|
|
||||||
(imports, import_initializers)
|
(imports, import_envs)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get pointers to where metadata about local memories should live in VM memory.
|
// Get pointers to where metadata about local memories should live in VM memory.
|
||||||
@@ -146,7 +146,7 @@ pub trait Artifact: Send + Sync + Upcastable {
|
|||||||
imports,
|
imports,
|
||||||
self.signatures().clone(),
|
self.signatures().clone(),
|
||||||
host_state,
|
host_state,
|
||||||
import_initializers,
|
import_envs,
|
||||||
)
|
)
|
||||||
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?;
|
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?;
|
||||||
Ok(handle)
|
Ok(handle)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ use wasmer_vm::{
|
|||||||
VMExportTable,
|
VMExportTable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// The value of an export passed from one instance to another.
|
/// The value of an export passed from one instance to another.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Export {
|
pub enum Export {
|
||||||
@@ -36,6 +38,7 @@ impl From<VMExport> for Export {
|
|||||||
VMExport::Function(vm_function) => Export::Function(ExportFunction {
|
VMExport::Function(vm_function) => Export::Function(ExportFunction {
|
||||||
vm_function,
|
vm_function,
|
||||||
import_init_function_ptr: None,
|
import_init_function_ptr: None,
|
||||||
|
host_env_drop_fn: None,
|
||||||
}),
|
}),
|
||||||
VMExport::Memory(vm_memory) => Export::Memory(ExportMemory { vm_memory }),
|
VMExport::Memory(vm_memory) => Export::Memory(ExportMemory { vm_memory }),
|
||||||
VMExport::Table(vm_table) => Export::Table(ExportTable { vm_table }),
|
VMExport::Table(vm_table) => Export::Table(ExportTable { vm_table }),
|
||||||
@@ -49,12 +52,14 @@ impl From<VMExport> for Export {
|
|||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ExportFunction {
|
pub struct ExportFunction {
|
||||||
/// The VM function, containing most of the data.
|
/// The VM function, containing most of the data.
|
||||||
pub vm_function: VMExportFunction,
|
pub vm_function: Arc<VMExportFunction>,
|
||||||
/// Function pointer to `WasmerEnv::init_with_instance(&mut self, instance: &Instance)`.
|
/// Function pointer to `WasmerEnv::init_with_instance(&mut self, instance: &Instance)`.
|
||||||
///
|
///
|
||||||
/// This function is called to finish setting up the environment after
|
/// This function is called to finish setting up the environment after
|
||||||
/// we create the `api::Instance`.
|
/// we create the `api::Instance`.
|
||||||
pub import_init_function_ptr: Option<ImportInitializerFuncPtr>,
|
pub import_init_function_ptr: Option<ImportInitializerFuncPtr>,
|
||||||
|
/// The destructor to free the host environment.
|
||||||
|
pub host_env_drop_fn: Option<fn(*mut std::ffi::c_void)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ExportFunction> for Export {
|
impl From<ExportFunction> for Export {
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
|
|
||||||
use crate::{Export, ImportError, LinkError};
|
use crate::{Export, ImportError, LinkError};
|
||||||
use more_asserts::assert_ge;
|
use more_asserts::assert_ge;
|
||||||
|
use std::sync::Arc;
|
||||||
use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap};
|
use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap};
|
||||||
use wasmer_types::{ExternType, FunctionIndex, ImportIndex, MemoryIndex, TableIndex};
|
use wasmer_types::{ExternType, FunctionIndex, ImportIndex, MemoryIndex, TableIndex};
|
||||||
|
|
||||||
use wasmer_vm::{
|
use wasmer_vm::{
|
||||||
FunctionBodyPtr, Imports, MemoryStyle, ModuleInfo, TableStyle, VMDynamicFunctionContext,
|
FunctionBodyPtr, ImportEnv, Imports, MemoryStyle, ModuleInfo, TableStyle,
|
||||||
VMFunctionBody, VMFunctionImport, VMFunctionKind, VMGlobalImport, VMMemoryImport,
|
VMDynamicFunctionContext, VMFunctionBody, VMFunctionImport, VMFunctionKind, VMGlobalImport,
|
||||||
VMTableImport,
|
VMMemoryImport, VMTableImport,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Import resolver connects imports with available exported values.
|
/// Import resolver connects imports with available exported values.
|
||||||
@@ -155,36 +156,13 @@ pub fn resolve_imports(
|
|||||||
}
|
}
|
||||||
match resolved {
|
match resolved {
|
||||||
Export::Function(ref f) => {
|
Export::Function(ref f) => {
|
||||||
let (address, env_ptr) = match f.vm_function.kind {
|
let address = match f.vm_function.kind {
|
||||||
VMFunctionKind::Dynamic => {
|
VMFunctionKind::Dynamic => {
|
||||||
// If this is a dynamic imported function,
|
// If this is a dynamic imported function,
|
||||||
// the address of the function is the address of the
|
// the address of the function is the address of the
|
||||||
// reverse trampoline.
|
// reverse trampoline.
|
||||||
let index = FunctionIndex::new(function_imports.len());
|
let index = FunctionIndex::new(function_imports.len());
|
||||||
let address = finished_dynamic_function_trampolines[index].0
|
finished_dynamic_function_trampolines[index].0 as *mut VMFunctionBody as _
|
||||||
as *mut VMFunctionBody as _;
|
|
||||||
let env_ptr = if f.import_init_function_ptr.is_some() {
|
|
||||||
// Our function env looks like:
|
|
||||||
// Box<VMDynamicFunctionContext<VMDynamicFunctionWithEnv<Env>>>
|
|
||||||
// Which we can interpret as `*const <field offset> *const Env` (due to
|
|
||||||
// the precise layout of these types via `repr(C)`)
|
|
||||||
// We extract the `*const Env`:
|
|
||||||
unsafe {
|
|
||||||
// Box<VMDynamicFunctionContext<...>>
|
|
||||||
let dyn_func_ctx_ptr = f.vm_function.vmctx.host_env
|
|
||||||
as *mut VMDynamicFunctionContext<*mut std::ffi::c_void>;
|
|
||||||
// maybe report error here if it's null?
|
|
||||||
// invariants of these types are not enforced.
|
|
||||||
|
|
||||||
// &VMDynamicFunctionContext<...>
|
|
||||||
let dyn_func_ctx = &*dyn_func_ctx_ptr;
|
|
||||||
dyn_func_ctx.ctx
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::ptr::null_mut()
|
|
||||||
};
|
|
||||||
|
|
||||||
(address, env_ptr)
|
|
||||||
|
|
||||||
// TODO: We should check that the f.vmctx actually matches
|
// TODO: We should check that the f.vmctx actually matches
|
||||||
// the shape of `VMDynamicFunctionImportContext`
|
// the shape of `VMDynamicFunctionImportContext`
|
||||||
@@ -198,9 +176,7 @@ pub fn resolve_imports(
|
|||||||
assert!(num_params < 9, "Only native functions with less than 9 arguments are allowed in Apple Silicon (for now). Received {} in the import {}.{}", num_params, module_name, field);
|
assert!(num_params < 9, "Only native functions with less than 9 arguments are allowed in Apple Silicon (for now). Received {} in the import {}.{}", num_params, module_name, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
(f.vm_function.address, unsafe {
|
f.vm_function.address
|
||||||
f.vm_function.vmctx.host_env
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function_imports.push(VMFunctionImport {
|
function_imports.push(VMFunctionImport {
|
||||||
@@ -208,7 +184,11 @@ pub fn resolve_imports(
|
|||||||
environment: f.vm_function.vmctx,
|
environment: f.vm_function.vmctx,
|
||||||
});
|
});
|
||||||
|
|
||||||
host_function_env_initializers.push((f.import_init_function_ptr, env_ptr));
|
host_function_env_initializers.push(Arc::new(ImportEnv {
|
||||||
|
env: unsafe { f.vm_function.vmctx.host_env },
|
||||||
|
initializer: f.import_init_function_ptr,
|
||||||
|
destructor: f.host_env_drop_fn,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
Export::Table(ref t) => {
|
Export::Table(ref t) => {
|
||||||
table_imports.push(VMTableImport {
|
table_imports.push(VMTableImport {
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ use std::sync::Arc;
|
|||||||
use wasmer_types::{FunctionType, MemoryType, TableType};
|
use wasmer_types::{FunctionType, MemoryType, TableType};
|
||||||
|
|
||||||
/// The value of an export passed from one instance to another.
|
/// The value of an export passed from one instance to another.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub enum VMExport {
|
pub enum VMExport {
|
||||||
/// A function export value.
|
/// A function export value.
|
||||||
Function(VMExportFunction),
|
Function(Arc<VMExportFunction>),
|
||||||
|
|
||||||
/// A table export value.
|
/// A table export value.
|
||||||
Table(VMExportTable),
|
Table(VMExportTable),
|
||||||
@@ -26,7 +26,7 @@ pub enum VMExport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A function export value.
|
/// A function export value.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct VMExportFunction {
|
pub struct VMExportFunction {
|
||||||
/// The address of the native-code function.
|
/// The address of the native-code function.
|
||||||
pub address: *const VMFunctionBody,
|
pub address: *const VMFunctionBody,
|
||||||
@@ -63,7 +63,7 @@ unsafe impl Sync for VMExportFunction {}
|
|||||||
|
|
||||||
impl From<VMExportFunction> for VMExport {
|
impl From<VMExportFunction> for VMExport {
|
||||||
fn from(func: VMExportFunction) -> Self {
|
fn from(func: VMExportFunction) -> Self {
|
||||||
Self::Function(func)
|
Self::Function(Arc::new(func))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// This file contains code from external sources.
|
// This file contains code from external sources.
|
||||||
// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
|
// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
|
||||||
|
|
||||||
use crate::instance::{ImportInitializerFuncPtr, ImportInitializerThunks};
|
use crate::instance::ImportEnv;
|
||||||
use crate::vmcontext::{VMFunctionImport, VMGlobalImport, VMMemoryImport, VMTableImport};
|
use crate::vmcontext::{VMFunctionImport, VMGlobalImport, VMMemoryImport, VMTableImport};
|
||||||
|
use std::sync::Arc;
|
||||||
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
||||||
use wasmer_types::{FunctionIndex, GlobalIndex, MemoryIndex, TableIndex};
|
use wasmer_types::{FunctionIndex, GlobalIndex, MemoryIndex, TableIndex};
|
||||||
|
|
||||||
@@ -17,9 +18,7 @@ pub struct Imports {
|
|||||||
/// space may affect Wasm runtime performance due to increased cache pressure.
|
/// space may affect Wasm runtime performance due to increased cache pressure.
|
||||||
///
|
///
|
||||||
/// We make it optional so that we can free the data after use.
|
/// We make it optional so that we can free the data after use.
|
||||||
pub host_function_env_initializers: Option<
|
pub host_function_env_initializers: Option<BoxedSlice<FunctionIndex, Arc<ImportEnv>>>,
|
||||||
BoxedSlice<FunctionIndex, (Option<ImportInitializerFuncPtr>, *mut std::ffi::c_void)>,
|
|
||||||
>,
|
|
||||||
|
|
||||||
/// Resolved addresses for imported tables.
|
/// Resolved addresses for imported tables.
|
||||||
pub tables: BoxedSlice<TableIndex, VMTableImport>,
|
pub tables: BoxedSlice<TableIndex, VMTableImport>,
|
||||||
@@ -35,10 +34,7 @@ impl Imports {
|
|||||||
/// Construct a new `Imports` instance.
|
/// Construct a new `Imports` instance.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
function_imports: PrimaryMap<FunctionIndex, VMFunctionImport>,
|
function_imports: PrimaryMap<FunctionIndex, VMFunctionImport>,
|
||||||
host_function_env_initializers: PrimaryMap<
|
host_function_env_initializers: PrimaryMap<FunctionIndex, Arc<ImportEnv>>,
|
||||||
FunctionIndex,
|
|
||||||
(Option<ImportInitializerFuncPtr>, *mut std::ffi::c_void),
|
|
||||||
>,
|
|
||||||
table_imports: PrimaryMap<TableIndex, VMTableImport>,
|
table_imports: PrimaryMap<TableIndex, VMTableImport>,
|
||||||
memory_imports: PrimaryMap<MemoryIndex, VMMemoryImport>,
|
memory_imports: PrimaryMap<MemoryIndex, VMMemoryImport>,
|
||||||
global_imports: PrimaryMap<GlobalIndex, VMGlobalImport>,
|
global_imports: PrimaryMap<GlobalIndex, VMGlobalImport>,
|
||||||
@@ -56,7 +52,7 @@ impl Imports {
|
|||||||
pub fn none() -> Self {
|
pub fn none() -> Self {
|
||||||
Self {
|
Self {
|
||||||
functions: PrimaryMap::new().into_boxed_slice(),
|
functions: PrimaryMap::new().into_boxed_slice(),
|
||||||
host_function_env_initializers: Some(PrimaryMap::new().into_boxed_slice()),
|
host_function_env_initializers: None,
|
||||||
tables: PrimaryMap::new().into_boxed_slice(),
|
tables: PrimaryMap::new().into_boxed_slice(),
|
||||||
memories: PrimaryMap::new().into_boxed_slice(),
|
memories: PrimaryMap::new().into_boxed_slice(),
|
||||||
globals: PrimaryMap::new().into_boxed_slice(),
|
globals: PrimaryMap::new().into_boxed_slice(),
|
||||||
@@ -68,25 +64,9 @@ impl Imports {
|
|||||||
///
|
///
|
||||||
/// This function can only be called once, it deletes the data it returns after
|
/// This function can only be called once, it deletes the data it returns after
|
||||||
/// returning it to ensure that it's not called more than once.
|
/// returning it to ensure that it's not called more than once.
|
||||||
pub fn get_import_initializers(&mut self) -> ImportInitializerThunks {
|
pub fn get_import_initializers(&mut self) -> BoxedSlice<FunctionIndex, Arc<ImportEnv>> {
|
||||||
let result = if let Some(inner) = &self.host_function_env_initializers {
|
self.host_function_env_initializers
|
||||||
inner
|
.take()
|
||||||
.values()
|
.unwrap_or_else(|| PrimaryMap::new().into_boxed_slice())
|
||||||
.cloned()
|
|
||||||
.map(|(func_init, env_ptr)| {
|
|
||||||
let host_env = if func_init.is_some() {
|
|
||||||
env_ptr
|
|
||||||
} else {
|
|
||||||
std::ptr::null_mut()
|
|
||||||
};
|
|
||||||
(func_init, host_env)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
};
|
|
||||||
// ensure we only call these functions once and free this now useless memory.
|
|
||||||
self.host_function_env_initializers = None;
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ pub(crate) struct Instance {
|
|||||||
///
|
///
|
||||||
/// TODO: Be sure to test with serialize/deserialize and imported
|
/// TODO: Be sure to test with serialize/deserialize and imported
|
||||||
/// functions from other Wasm modules.
|
/// functions from other Wasm modules.
|
||||||
import_initializers: ImportInitializerThunks,
|
/// TODO: update this comment
|
||||||
|
import_envs: BoxedSlice<FunctionIndex, Arc<ImportEnv>>,
|
||||||
|
|
||||||
/// Additional context used by compiled WebAssembly code. This
|
/// Additional context used by compiled WebAssembly code. This
|
||||||
/// field is last, and represents a dynamically-sized array that
|
/// field is last, and represents a dynamically-sized array that
|
||||||
@@ -109,6 +110,27 @@ pub(crate) struct Instance {
|
|||||||
vmctx: VMContext,
|
vmctx: VMContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: figure out what to do with Clone here
|
||||||
|
/// We can probably remove the Arc... just need to figure that out.
|
||||||
|
/// TODO:
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ImportEnv {
|
||||||
|
/// TODO:
|
||||||
|
pub env: *mut std::ffi::c_void,
|
||||||
|
/// TODO:
|
||||||
|
pub initializer: Option<ImportInitializerFuncPtr>,
|
||||||
|
/// TODO:
|
||||||
|
pub destructor: Option<fn(*mut std::ffi::c_void)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ImportEnv {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(destructor) = self.destructor {
|
||||||
|
(destructor)(self.env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Instance {
|
impl fmt::Debug for Instance {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter.debug_struct("Instance").finish()
|
formatter.debug_struct("Instance").finish()
|
||||||
@@ -155,7 +177,7 @@ impl Instance {
|
|||||||
&self,
|
&self,
|
||||||
index: FunctionIndex,
|
index: FunctionIndex,
|
||||||
) -> Option<ImportInitializerFuncPtr> {
|
) -> Option<ImportInitializerFuncPtr> {
|
||||||
self.import_initializers[index.as_u32() as usize].0
|
self.import_envs[index].initializer
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a pointer to the `VMFunctionImport`s.
|
/// Return a pointer to the `VMFunctionImport`s.
|
||||||
@@ -1007,7 +1029,7 @@ impl InstanceHandle {
|
|||||||
imports: Imports,
|
imports: Imports,
|
||||||
vmshared_signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
|
vmshared_signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
|
||||||
host_state: Box<dyn Any>,
|
host_state: Box<dyn Any>,
|
||||||
import_initializers: ImportInitializerThunks,
|
import_envs: BoxedSlice<FunctionIndex, Arc<ImportEnv>>,
|
||||||
) -> Result<Self, Trap> {
|
) -> Result<Self, Trap> {
|
||||||
// `NonNull<u8>` here actually means `NonNull<Instance>`. See
|
// `NonNull<u8>` here actually means `NonNull<Instance>`. See
|
||||||
// `Self::allocate_instance` to understand why.
|
// `Self::allocate_instance` to understand why.
|
||||||
@@ -1035,7 +1057,7 @@ impl InstanceHandle {
|
|||||||
passive_data,
|
passive_data,
|
||||||
host_state,
|
host_state,
|
||||||
signal_handler: Cell::new(None),
|
signal_handler: Cell::new(None),
|
||||||
import_initializers,
|
import_envs,
|
||||||
vmctx: VMContext {},
|
vmctx: VMContext {},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1411,18 +1433,20 @@ impl InstanceHandle {
|
|||||||
) -> Result<(), Err> {
|
) -> Result<(), Err> {
|
||||||
let instance_ref = self.instance.as_mut();
|
let instance_ref = self.instance.as_mut();
|
||||||
|
|
||||||
for (func, env) in instance_ref.import_initializers.drain(..) {
|
for ImportEnv {
|
||||||
if let Some(ref f) = func {
|
env, initializer, ..
|
||||||
|
} in instance_ref.import_envs.values().map(|v| &**v)
|
||||||
|
{
|
||||||
|
if let Some(ref f) = initializer {
|
||||||
// transmute our function pointer into one with the correct error type
|
// transmute our function pointer into one with the correct error type
|
||||||
let f = mem::transmute::<
|
let f = mem::transmute::<
|
||||||
&ImportInitializerFuncPtr,
|
&ImportInitializerFuncPtr,
|
||||||
&fn(*mut ffi::c_void, *const ffi::c_void) -> Result<(), Err>,
|
&fn(*mut ffi::c_void, *const ffi::c_void) -> Result<(), Err>,
|
||||||
>(f);
|
>(f);
|
||||||
f(env, instance_ptr)?;
|
f(*env, instance_ptr)?;
|
||||||
|
//*initializer = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// free memory now that it's empty.
|
|
||||||
instance_ref.import_initializers.shrink_to_fit();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ pub mod libcalls;
|
|||||||
pub use crate::export::*;
|
pub use crate::export::*;
|
||||||
pub use crate::global::*;
|
pub use crate::global::*;
|
||||||
pub use crate::imports::Imports;
|
pub use crate::imports::Imports;
|
||||||
pub use crate::instance::{ImportInitializerFuncPtr, InstanceHandle};
|
pub use crate::instance::{ImportEnv, ImportInitializerFuncPtr, InstanceHandle};
|
||||||
pub use crate::memory::{LinearMemory, Memory, MemoryError, MemoryStyle};
|
pub use crate::memory::{LinearMemory, Memory, MemoryError, MemoryStyle};
|
||||||
pub use crate::mmap::Mmap;
|
pub use crate::mmap::Mmap;
|
||||||
pub use crate::module::{ExportsIterator, ImportsIterator, ModuleInfo};
|
pub use crate::module::{ExportsIterator, ImportsIterator, ModuleInfo};
|
||||||
|
|||||||
Reference in New Issue
Block a user