Skip to content

Commit

Permalink
Try #1739:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] authored Oct 20, 2020
2 parents a3ffc9e + b78447f commit d473ef9
Show file tree
Hide file tree
Showing 20 changed files with 316 additions and 73 deletions.
3 changes: 0 additions & 3 deletions examples/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let import_object = wasi_env.import_object(&module)?;
let instance = Instance::new(&module, &import_object)?;

// WASI requires to explicitly set the memory for the `WasiEnv`
wasi_env.set_memory(instance.exports.get_memory("memory")?.clone());

println!("Call WASI `_start` function...");
// And we just call the `_start` function!
let start = instance.exports.get_function("_start")?;
Expand Down
38 changes: 29 additions & 9 deletions lib/api/src/externals/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use std::cmp::max;
use std::fmt;
use wasmer_vm::{
raise_user_trap, resume_panic, wasmer_call_trampoline, Export, ExportFunction,
VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMFunctionBody, VMFunctionKind,
VMTrampoline,
FunctionExtraData, VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMFunctionBody,
VMFunctionKind, VMTrampoline,
};

/// A function defined in the Wasm module
Expand Down Expand Up @@ -85,7 +85,9 @@ impl Function {
// The engine linker will replace the address with one pointing to a
// generated dynamic trampoline.
let address = std::ptr::null() as *const VMFunctionBody;
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
let vmctx = FunctionExtraData {
host_env: Box::into_raw(Box::new(dynamic_ctx)) as *mut _,
};

Self {
store: store.clone(),
Expand All @@ -94,6 +96,7 @@ impl Function {
address,
kind: VMFunctionKind::Dynamic,
vmctx,
function_ptr: None,
signature: ty.clone(),
call_trampoline: None,
},
Expand Down Expand Up @@ -124,7 +127,7 @@ impl Function {
pub fn new_with_env<F, Env>(store: &Store, ty: &FunctionType, env: Env, func: F) -> Self
where
F: Fn(&mut Env, &[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
Env: Sized + 'static,
Env: Sized + crate::WasmerEnv + 'static,
{
let dynamic_ctx = VMDynamicFunctionContext::from_context(VMDynamicFunctionWithEnv {
env: RefCell::new(env),
Expand All @@ -135,7 +138,12 @@ impl Function {
// The engine linker will replace the address with one pointing to a
// generated dynamic trampoline.
let address = std::ptr::null() as *const VMFunctionBody;
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
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::<fn(_, _), fn(_, _)>(Env::finish) });
//dbg!(function_ptr);

Self {
store: store.clone(),
Expand All @@ -144,6 +152,7 @@ impl Function {
address,
kind: VMFunctionKind::Dynamic,
vmctx,
function_ptr,
signature: ty.clone(),
call_trampoline: None,
},
Expand Down Expand Up @@ -176,7 +185,9 @@ impl Function {
{
let function = inner::Function::<Args, Rets>::new(func);
let address = function.address() as *const VMFunctionBody;
let vmctx = std::ptr::null_mut() as *mut _ as *mut VMContext;
let vmctx = FunctionExtraData {
host_env: std::ptr::null_mut() as *mut _,
};
let signature = function.ty();

Self {
Expand All @@ -186,6 +197,9 @@ impl Function {
address,
vmctx,
signature,
// 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,
call_trampoline: None,
},
Expand Down Expand Up @@ -219,7 +233,7 @@ impl Function {
F: HostFunction<Args, Rets, WithEnv, Env>,
Args: WasmTypeList,
Rets: WasmTypeList,
Env: Sized + 'static,
Env: Sized + crate::WasmerEnv + 'static,
{
let function = inner::Function::<Args, Rets>::new(func);
let address = function.address();
Expand All @@ -230,7 +244,12 @@ impl Function {
// In the case of Host-defined functions `VMContext` is whatever environment
// the user want to attach to the function.
let box_env = Box::new(env);
let vmctx = Box::into_raw(box_env) as *mut _ as *mut VMContext;
let vmctx = FunctionExtraData {
host_env: Box::into_raw(box_env) as *mut _,
};
// TODO: look into removing transmute by changing API type signatures
let function_ptr = Some(unsafe { std::mem::transmute::<fn(_, _), fn(_, _)>(Env::finish) });
//dbg!(function_ptr as usize);
let signature = function.ty();

Self {
Expand All @@ -240,6 +259,7 @@ impl Function {
address,
kind: VMFunctionKind::Static,
vmctx,
function_ptr,
signature,
call_trampoline: None,
},
Expand Down Expand Up @@ -365,7 +385,7 @@ impl Function {
Self {
store: store.clone(),
definition: FunctionDefinition::Host(HostFunctionDefinition {
has_env: !wasmer_export.vmctx.is_null(),
has_env: !unsafe { wasmer_export.vmctx.host_env.is_null() },
}),
exported: wasmer_export,
}
Expand Down
12 changes: 10 additions & 2 deletions lib/api/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,19 @@ impl Instance {
})
.collect::<Exports>();

Ok(Self {
let instance = Self {
handle,
module: module.clone(),
exports,
})
};

unsafe {
instance
.handle
.initialize_host_envs(&instance as *const _ as *const _);
}

Ok(instance)
}

/// Gets the [`Module`] associated with this instance.
Expand Down
14 changes: 14 additions & 0 deletions lib/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,17 @@ pub use wasmer_engine_native::{Native, NativeArtifact, NativeEngine};

/// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

// --------------------------------------------------------------
// TODO: put this in a proper location, just prototyping for now:
// TODO: rename everything, all names are throw-away names

/// Prototype trait for finishing envs.
pub trait WasmerEnv {
/// The function that Wasmer will call on your type to let it finish
/// instantiating.
fn finish(&mut self, instance: &Instance);

/// Frees memory written to `self` so it can be dropped without any memory leaks.
fn free(&mut self);
}
25 changes: 17 additions & 8 deletions lib/api/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ use crate::{FromToNativeWasmType, Function, FunctionType, RuntimeError, Store, W
use std::panic::{catch_unwind, AssertUnwindSafe};
use wasmer_types::NativeWasmType;
use wasmer_vm::{
ExportFunction, VMContext, VMDynamicFunctionContext, VMFunctionBody, VMFunctionKind,
ExportFunction, FunctionExtraData, VMContext, VMDynamicFunctionContext, VMFunctionBody,
VMFunctionKind,
};

/// A WebAssembly function that can be called natively
Expand All @@ -26,7 +27,7 @@ pub struct NativeFunc<'a, Args = (), Rets = ()> {
definition: FunctionDefinition,
store: Store,
address: *const VMFunctionBody,
vmctx: *mut VMContext,
vmctx: FunctionExtraData,
arg_kind: VMFunctionKind,
// exported: ExportFunction,
_phantom: PhantomData<(&'a (), Args, Rets)>,
Expand All @@ -42,7 +43,7 @@ where
pub(crate) fn new(
store: Store,
address: *const VMFunctionBody,
vmctx: *mut VMContext,
vmctx: FunctionExtraData,
arg_kind: VMFunctionKind,
definition: FunctionDefinition,
) -> Self {
Expand All @@ -68,6 +69,8 @@ where
address: other.address,
vmctx: other.vmctx,
signature,
// TODO:
function_ptr: None,
kind: other.arg_kind,
call_trampoline: None,
}
Expand All @@ -88,6 +91,8 @@ where
address: other.address,
vmctx: other.vmctx,
signature,
// TODO:
function_ptr: None,
kind: other.arg_kind,
call_trampoline: None,
},
Expand Down Expand Up @@ -165,7 +170,7 @@ macro_rules! impl_native_traits {
match self.arg_kind {
VMFunctionKind::Static => {
let results = catch_unwind(AssertUnwindSafe(|| unsafe {
let f = std::mem::transmute::<_, unsafe extern "C" fn( *mut VMContext, $( $x, )*) -> Rets::CStruct>(self.address);
let f = std::mem::transmute::<_, unsafe extern "C" fn( FunctionExtraData, $( $x, )*) -> Rets::CStruct>(self.address);
// We always pass the vmctx
f( self.vmctx, $( $x, )* )
})).map_err(|e| RuntimeError::new(format!("{:?}", e)))?;
Expand All @@ -175,12 +180,16 @@ macro_rules! impl_native_traits {
let params_list = [ $( $x.to_native().to_value() ),* ];
let results = if !has_env {
type VMContextWithoutEnv = VMDynamicFunctionContext<VMDynamicFunctionWithoutEnv>;
let ctx = self.vmctx as *mut VMContextWithoutEnv;
unsafe { (*ctx).ctx.call(&params_list)? }
unsafe {
let ctx = self.vmctx.host_env as *mut VMContextWithoutEnv;
(*ctx).ctx.call(&params_list)?
}
} else {
type VMContextWithEnv = VMDynamicFunctionContext<VMDynamicFunctionWithEnv<std::ffi::c_void>>;
let ctx = self.vmctx as *mut VMContextWithEnv;
unsafe { (*ctx).ctx.call(&params_list)? }
unsafe {
let ctx = self.vmctx.host_env as *mut VMContextWithEnv;
(*ctx).ctx.call(&params_list)?
}
};
let mut rets_list_array = Rets::empty_array();
let mut_rets = rets_list_array.as_mut() as *mut [i128] as *mut i128;
Expand Down
7 changes: 6 additions & 1 deletion lib/api/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ impl ValFuncRef for Val {
Self::ExternRef(ExternRef::Null) => wasmer_vm::VMCallerCheckedAnyfunc {
func_ptr: ptr::null(),
type_index: wasmer_vm::VMSharedSignatureIndex::default(),
vmctx: ptr::null_mut(),
vmctx: wasmer_vm::FunctionExtraData {
host_env: ptr::null_mut(),
},
},
Self::FuncRef(f) => f.checked_anyfunc(),
_ => return Err(RuntimeError::new("val is not funcref")),
Expand All @@ -74,6 +76,9 @@ impl ValFuncRef for Val {
let export = wasmer_vm::ExportFunction {
address: item.func_ptr,
signature,
// TODO:
// 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,
Expand Down
2 changes: 1 addition & 1 deletion lib/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ default = [
"object-file",
"cache",
"wasi",
"emscripten",
# "emscripten",
]
engine = []
jit = [
Expand Down
2 changes: 1 addition & 1 deletion lib/cli/src/commands/run/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl Wasi {
let import_object = wasi_env.import_object(&module)?;
let instance = Instance::new(&module, &import_object)?;

wasi_env.set_memory(instance.exports.get_memory("memory")?.clone());
//wasi_env.set_memory(instance.exports.get_memory("memory")?.clone());

let start = instance.exports.get_function("_start")?;
let result = start.call(&[]);
Expand Down
23 changes: 21 additions & 2 deletions lib/engine/src/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,23 @@ pub trait Artifact: Send + Sync + Upcastable {
self.table_styles(),
)
.map_err(InstantiationError::Link)?;

let mut thunks = vec![];
// ------------
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));
}
// ------------

let finished_memories = tunables
.create_memories(&module, self.memory_styles())
.map_err(InstantiationError::Link)?
Expand All @@ -118,7 +135,7 @@ pub trait Artifact: Send + Sync + Upcastable {

self.register_frame_info();

InstanceHandle::new(
let handle = InstanceHandle::new(
module,
self.finished_functions().clone(),
self.finished_function_call_trampolines().clone(),
Expand All @@ -128,8 +145,10 @@ pub trait Artifact: Send + Sync + Upcastable {
imports,
self.signatures().clone(),
host_state,
thunks,
)
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?;
Ok(handle)
}

/// Finishes the instantiation of a just created `InstanceHandle`.
Expand Down
8 changes: 7 additions & 1 deletion lib/engine/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ pub fn resolve_imports(
_table_styles: &PrimaryMap<TableIndex, TableStyle>,
) -> Result<Imports, LinkError> {
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);
Expand Down Expand Up @@ -167,8 +170,10 @@ pub fn resolve_imports(
};
function_imports.push(VMFunctionImport {
body: address,
vmctx: f.vmctx,
extra_data: f.vmctx,
});

host_function_env_initializers.push(f.function_ptr);
}
Export::Table(ref t) => {
table_imports.push(VMTableImport {
Expand Down Expand Up @@ -222,6 +227,7 @@ pub fn resolve_imports(

Ok(Imports::new(
function_imports,
host_function_env_initializers,
table_imports,
memory_imports,
global_imports,
Expand Down
4 changes: 3 additions & 1 deletion lib/vm/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ pub struct ExportFunction {
/// The address of the native-code function.
pub address: *const VMFunctionBody,
/// Pointer to the containing `VMContext`.
pub vmctx: *mut VMContext,
pub vmctx: crate::vmcontext::FunctionExtraData,
/// temp code to set vmctx for host functions
pub function_ptr: Option<fn(*mut std::ffi::c_void, *const std::ffi::c_void)>,
/// The function type, used for compatibility checking.
pub signature: FunctionType,
/// The function kind (it defines how it's the signature that provided `address` have)
Expand Down
Loading

0 comments on commit d473ef9

Please sign in to comment.