mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-18 17:10:52 +00:00
!temp
This commit is contained in:
parent
0e27f2fa72
commit
2a041f898e
@ -12,33 +12,46 @@ fn imported_functions_forms() {
|
||||
(import "env" "memory" (memory 1 1))
|
||||
(import "env" "callback_fn" (func $callback_fn (type $type)))
|
||||
(import "env" "callback_closure" (func $callback_closure (type $type)))
|
||||
(import "env" "callback_closure_with_env" (func $callback_closure_with_env (type $type)))
|
||||
(import "env" "callback_fn_with_vmctx" (func $callback_fn_with_vmctx (type $type)))
|
||||
(import "env" "callback_closure_with_vmctx" (func $callback_closure_with_vmctx (type $type)))
|
||||
(import "env" "callback_fn_trap" (func $callback_fn_trap (type $type)))
|
||||
(import "env" "callback_closure_trap" (func $callback_closure_trap (type $type)))
|
||||
(import "env" "callback_fn_trap_with_vmctx" (func $callback_fn_trap_with_vmctx (type $type)))
|
||||
(import "env" "callback_closure_trap_with_vmctx" (func $callback_closure_trap_with_vmctx (type $type)))
|
||||
|
||||
(func (export "function_fn") (type $type)
|
||||
get_local 0
|
||||
call $callback_fn)
|
||||
|
||||
(func (export "function_closure") (type $type)
|
||||
get_local 0
|
||||
call $callback_closure)
|
||||
|
||||
(func (export "function_closure_with_env") (type $type)
|
||||
get_local 0
|
||||
call $callback_closure_with_env)
|
||||
|
||||
(func (export "function_fn_with_vmctx") (type $type)
|
||||
get_local 0
|
||||
call $callback_fn_with_vmctx)
|
||||
|
||||
(func (export "function_closure_with_vmctx") (type $type)
|
||||
get_local 0
|
||||
call $callback_closure_with_vmctx)
|
||||
|
||||
(func (export "function_fn_trap") (type $type)
|
||||
get_local 0
|
||||
call $callback_fn_trap)
|
||||
|
||||
(func (export "function_closure_trap") (type $type)
|
||||
get_local 0
|
||||
call $callback_closure_trap)
|
||||
|
||||
(func (export "function_fn_trap_with_vmctx") (type $type)
|
||||
get_local 0
|
||||
call $callback_fn_trap_with_vmctx)
|
||||
|
||||
(func (export "function_closure_trap_with_vmctx") (type $type)
|
||||
get_local 0
|
||||
call $callback_closure_trap_with_vmctx))
|
||||
@ -51,6 +64,7 @@ fn imported_functions_forms() {
|
||||
|
||||
const SHIFT: i32 = 10;
|
||||
memory.view()[0].set(SHIFT);
|
||||
let shift = 100;
|
||||
|
||||
let import_object = imports! {
|
||||
"env" => {
|
||||
@ -59,6 +73,9 @@ fn imported_functions_forms() {
|
||||
"callback_closure" => Func::new(|n: i32| -> Result<i32, ()> {
|
||||
Ok(n + 1)
|
||||
}),
|
||||
"callback_closure_with_env" => Func::new(move |n: i32| -> Result<i32, ()> {
|
||||
Ok(shift + n + 1)
|
||||
}),
|
||||
"callback_fn_with_vmctx" => Func::new(callback_fn_with_vmctx),
|
||||
"callback_closure_with_vmctx" => Func::new(|vmctx: &mut vm::Ctx, n: i32| -> Result<i32, ()> {
|
||||
let memory = vmctx.memory(0);
|
||||
@ -134,6 +151,7 @@ fn imported_functions_forms() {
|
||||
|
||||
call_and_assert!(function_fn, Ok(2));
|
||||
call_and_assert!(function_closure, Ok(2));
|
||||
call_and_assert!(function_closure_with_env, Ok(2 + shift));
|
||||
call_and_assert!(function_fn_with_vmctx, Ok(2 + SHIFT));
|
||||
call_and_assert!(function_closure_with_vmctx, Ok(2 + SHIFT));
|
||||
call_and_assert!(
|
||||
|
@ -586,18 +586,18 @@ fn import_functions(
|
||||
if *expected_sig == *signature {
|
||||
functions.push(vm::ImportedFunc {
|
||||
func: func.inner(),
|
||||
func_ctx: {
|
||||
let _ = match ctx {
|
||||
Context::External(ctx) => ctx,
|
||||
Context::Internal => vmctx,
|
||||
};
|
||||
|
||||
NonNull::new(Box::into_raw(Box::new(vm::FuncCtx {
|
||||
vmctx: NonNull::new(vmctx).expect("`vmctx` must not be null."),
|
||||
func_env: ptr::null_mut(),
|
||||
})))
|
||||
.unwrap()
|
||||
},
|
||||
func_ctx: NonNull::new(Box::into_raw(Box::new(vm::FuncCtx {
|
||||
vmctx: NonNull::new(vmctx).expect("`vmctx` must not be null."),
|
||||
func_env: match ctx {
|
||||
Context::External(ctx) => {
|
||||
NonNull::new(ctx).map(|pointer| {
|
||||
pointer.cast() // `*mut vm::FuncEnv` was casted to `*mut vm::Ctx` to fit in `Context::External`. Cast it back.
|
||||
})
|
||||
}
|
||||
Context::Internal => None,
|
||||
},
|
||||
})))
|
||||
.unwrap(),
|
||||
});
|
||||
} else {
|
||||
link_errors.push(LinkError::IncorrectImportSignature {
|
||||
|
@ -175,7 +175,7 @@ where
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
fn to_raw(&self) -> NonNull<vm::Func>;
|
||||
fn to_raw(self) -> (NonNull<vm::Func>, Option<NonNull<vm::FuncEnv>>);
|
||||
}
|
||||
|
||||
pub trait TrapEarly<Rets>
|
||||
@ -208,10 +208,12 @@ where
|
||||
}
|
||||
|
||||
/// Represents a function that can be used by WebAssembly.
|
||||
#[allow(dead_code)]
|
||||
pub struct Func<'a, Args = (), Rets = (), Inner: Kind = Wasm> {
|
||||
inner: Inner,
|
||||
f: NonNull<vm::Func>,
|
||||
ctx: *mut vm::Ctx,
|
||||
func: NonNull<vm::Func>,
|
||||
func_env: Option<NonNull<vm::FuncEnv>>,
|
||||
vmctx: *mut vm::Ctx,
|
||||
_phantom: PhantomData<(&'a (), Args, Rets)>,
|
||||
}
|
||||
|
||||
@ -225,19 +227,20 @@ where
|
||||
{
|
||||
pub(crate) unsafe fn from_raw_parts(
|
||||
inner: Wasm,
|
||||
f: NonNull<vm::Func>,
|
||||
ctx: *mut vm::Ctx,
|
||||
func: NonNull<vm::Func>,
|
||||
vmctx: *mut vm::Ctx,
|
||||
) -> Func<'a, Args, Rets, Wasm> {
|
||||
Func {
|
||||
inner,
|
||||
f,
|
||||
ctx,
|
||||
func,
|
||||
func_env: None,
|
||||
vmctx,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_vm_func(&self) -> NonNull<vm::Func> {
|
||||
self.f
|
||||
self.func
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,15 +249,18 @@ where
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
pub fn new<F, Kind>(f: F) -> Func<'a, Args, Rets, Host>
|
||||
pub fn new<F, Kind>(func: F) -> Func<'a, Args, Rets, Host>
|
||||
where
|
||||
Kind: ExternalFunctionKind,
|
||||
F: ExternalFunction<Kind, Args, Rets>,
|
||||
{
|
||||
let (func, func_env) = func.to_raw();
|
||||
|
||||
Func {
|
||||
inner: Host(()),
|
||||
f: f.to_raw(),
|
||||
ctx: ptr::null_mut(),
|
||||
func,
|
||||
func_env,
|
||||
vmctx: ptr::null_mut(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -391,7 +397,7 @@ where
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
pub fn call(&self, a: A) -> Result<Rets, RuntimeError> {
|
||||
unsafe { <A as WasmTypeList>::call(a, self.f, self.inner, self.ctx) }
|
||||
unsafe { <A as WasmTypeList>::call(a, self.func, self.inner, self.vmctx) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -482,57 +488,75 @@ macro_rules! impl_traits {
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn(&mut vm::Ctx $( , $x )*) -> Trap,
|
||||
FN: Fn(&mut vm::Ctx $( , $x )*) -> Trap + 'static,
|
||||
{
|
||||
#[allow(non_snake_case)]
|
||||
fn to_raw(&self) -> NonNull<vm::Func> {
|
||||
if mem::size_of::<Self>() == 0 {
|
||||
/// This is required for the llvm backend to be able to unwind through this function.
|
||||
#[cfg_attr(nightly, unwind(allowed))]
|
||||
extern fn wrap<$( $x, )* Rets, Trap, FN>(
|
||||
func_ctx: &mut vm::FuncCtx $( , $x: <$x as WasmExternType>::Native )*
|
||||
) -> Rets::CStruct
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn(&mut vm::Ctx, $( $x, )*) -> Trap,
|
||||
{
|
||||
let vmctx = unsafe { func_ctx.vmctx.as_mut() };
|
||||
let f: FN = unsafe { mem::transmute_copy(&()) };
|
||||
fn to_raw(self) -> (NonNull<vm::Func>, Option<NonNull<vm::FuncEnv>>) {
|
||||
/// This is required for the llvm backend to be able to unwind through this function.
|
||||
#[cfg_attr(nightly, unwind(allowed))]
|
||||
extern fn wrap<$( $x, )* Rets, Trap, FN>(
|
||||
func_ctx: &mut vm::FuncCtx $( , $x: <$x as WasmExternType>::Native )*
|
||||
) -> Rets::CStruct
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn(&mut vm::Ctx, $( $x, )*) -> Trap,
|
||||
{
|
||||
dbg!(func_ctx.vmctx.as_ptr());
|
||||
|
||||
let err = match panic::catch_unwind(
|
||||
panic::AssertUnwindSafe(
|
||||
|| {
|
||||
f(vmctx $( , WasmExternType::from_native($x) )* ).report()
|
||||
}
|
||||
)
|
||||
) {
|
||||
Ok(Ok(returns)) => return returns.into_c_struct(),
|
||||
Ok(Err(err)) => {
|
||||
let b: Box<_> = err.into();
|
||||
b as Box<dyn Any>
|
||||
},
|
||||
Err(err) => err,
|
||||
};
|
||||
let vmctx = unsafe { func_ctx.vmctx.as_mut() };
|
||||
let func_env = func_ctx.func_env;
|
||||
|
||||
unsafe {
|
||||
(&*vmctx.module).runnable_module.do_early_trap(err)
|
||||
}
|
||||
dbg!(func_env);
|
||||
|
||||
let func: &FN = match func_env {
|
||||
Some(func_env) => unsafe {
|
||||
let func: NonNull<FN> = func_env.cast();
|
||||
|
||||
&*func.as_ptr()
|
||||
},
|
||||
None => unsafe { mem::transmute_copy(&()) }
|
||||
};
|
||||
|
||||
let err = match panic::catch_unwind(
|
||||
panic::AssertUnwindSafe(
|
||||
|| {
|
||||
func(vmctx $( , WasmExternType::from_native($x) )* ).report()
|
||||
}
|
||||
)
|
||||
) {
|
||||
Ok(Ok(returns)) => return returns.into_c_struct(),
|
||||
Ok(Err(err)) => {
|
||||
let b: Box<_> = err.into();
|
||||
b as Box<dyn Any>
|
||||
},
|
||||
Err(err) => err,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
(&*vmctx.module).runnable_module.do_early_trap(err)
|
||||
}
|
||||
|
||||
NonNull::new(wrap::<$( $x, )* Rets, Trap, Self> as *mut vm::Func).unwrap()
|
||||
} else {
|
||||
assert_eq!(
|
||||
mem::size_of::<Self>(),
|
||||
mem::size_of::<usize>(),
|
||||
"you cannot use a closure that captures state for `Func`."
|
||||
);
|
||||
|
||||
NonNull::new(unsafe {
|
||||
mem::transmute_copy::<_, *mut vm::Func>(self)
|
||||
}).unwrap()
|
||||
}
|
||||
|
||||
let func_env: Option<NonNull<vm::FuncEnv>> =
|
||||
// `FN` is a function pointer, or a closure
|
||||
// _without_ a captured environment.
|
||||
if mem::size_of::<Self>() == 0 {
|
||||
None
|
||||
}
|
||||
// `FN` is a closure _with_ a captured
|
||||
// environment. Grab it.
|
||||
else {
|
||||
NonNull::new(Box::into_raw(Box::new(self))).map(NonNull::cast)
|
||||
};
|
||||
|
||||
dbg!(func_env);
|
||||
|
||||
(
|
||||
NonNull::new(wrap::<$( $x, )* Rets, Trap, Self> as *mut vm::Func).unwrap(),
|
||||
func_env
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,57 +565,75 @@ macro_rules! impl_traits {
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn($( $x, )*) -> Trap,
|
||||
FN: Fn($( $x, )*) -> Trap + 'static,
|
||||
{
|
||||
#[allow(non_snake_case)]
|
||||
fn to_raw(&self) -> NonNull<vm::Func> {
|
||||
if mem::size_of::<Self>() == 0 {
|
||||
/// This is required for the llvm backend to be able to unwind through this function.
|
||||
#[cfg_attr(nightly, unwind(allowed))]
|
||||
extern fn wrap<$( $x, )* Rets, Trap, FN>(
|
||||
func_ctx: &mut vm::FuncCtx $( , $x: <$x as WasmExternType>::Native )*
|
||||
) -> Rets::CStruct
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn($( $x, )*) -> Trap,
|
||||
{
|
||||
let vmctx = unsafe { func_ctx.vmctx.as_mut() };
|
||||
let f: FN = unsafe { mem::transmute_copy(&()) };
|
||||
fn to_raw(self) -> (NonNull<vm::Func>, Option<NonNull<vm::FuncEnv>>) {
|
||||
/// This is required for the llvm backend to be able to unwind through this function.
|
||||
#[cfg_attr(nightly, unwind(allowed))]
|
||||
extern fn wrap<$( $x, )* Rets, Trap, FN>(
|
||||
func_ctx: &mut vm::FuncCtx $( , $x: <$x as WasmExternType>::Native )*
|
||||
) -> Rets::CStruct
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn($( $x, )*) -> Trap,
|
||||
{
|
||||
dbg!(func_ctx.vmctx.as_ptr());
|
||||
|
||||
let err = match panic::catch_unwind(
|
||||
panic::AssertUnwindSafe(
|
||||
|| {
|
||||
f($( WasmExternType::from_native($x), )* ).report()
|
||||
}
|
||||
)
|
||||
) {
|
||||
Ok(Ok(returns)) => return returns.into_c_struct(),
|
||||
Ok(Err(err)) => {
|
||||
let b: Box<_> = err.into();
|
||||
b as Box<dyn Any>
|
||||
},
|
||||
Err(err) => err,
|
||||
};
|
||||
let vmctx = unsafe { func_ctx.vmctx.as_mut() };
|
||||
let func_env = func_ctx.func_env;
|
||||
|
||||
unsafe {
|
||||
(&*vmctx.module).runnable_module.do_early_trap(err)
|
||||
}
|
||||
dbg!(func_env);
|
||||
|
||||
let func: &FN = match func_env {
|
||||
Some(func_env) => unsafe {
|
||||
let func: NonNull<FN> = func_env.cast();
|
||||
|
||||
&*func.as_ptr()
|
||||
},
|
||||
None => unsafe { mem::transmute_copy(&()) }
|
||||
};
|
||||
|
||||
let err = match panic::catch_unwind(
|
||||
panic::AssertUnwindSafe(
|
||||
|| {
|
||||
func($( WasmExternType::from_native($x), )* ).report()
|
||||
}
|
||||
)
|
||||
) {
|
||||
Ok(Ok(returns)) => return returns.into_c_struct(),
|
||||
Ok(Err(err)) => {
|
||||
let b: Box<_> = err.into();
|
||||
b as Box<dyn Any>
|
||||
},
|
||||
Err(err) => err,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
(&*vmctx.module).runnable_module.do_early_trap(err)
|
||||
}
|
||||
|
||||
NonNull::new(wrap::<$( $x, )* Rets, Trap, Self> as *mut vm::Func).unwrap()
|
||||
} else {
|
||||
assert_eq!(
|
||||
mem::size_of::<Self>(),
|
||||
mem::size_of::<usize>(),
|
||||
"you cannot use a closure that captures state for `Func`."
|
||||
);
|
||||
|
||||
NonNull::new(unsafe {
|
||||
mem::transmute_copy::<_, *mut vm::Func>(self)
|
||||
}).unwrap()
|
||||
}
|
||||
|
||||
let func_env: Option<NonNull<vm::FuncEnv>> =
|
||||
// `FN` is a function pointer, or a closure
|
||||
// _without_ a captured environment.
|
||||
if mem::size_of::<Self>() == 0 {
|
||||
None
|
||||
}
|
||||
// `FN` is a closure _with_ a captured
|
||||
// environment. Grab it.
|
||||
else {
|
||||
NonNull::new(Box::into_raw(Box::new(self))).map(NonNull::cast)
|
||||
};
|
||||
|
||||
dbg!(func_env);
|
||||
|
||||
(
|
||||
NonNull::new(wrap::<$( $x, )* Rets, Trap, Self> as *mut vm::Func).unwrap(),
|
||||
func_env
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,9 +648,9 @@ macro_rules! impl_traits {
|
||||
unsafe {
|
||||
<( $( $x ),* ) as WasmTypeList>::call(
|
||||
( $( $x ),* ),
|
||||
self.f,
|
||||
self.func,
|
||||
self.inner,
|
||||
self.ctx
|
||||
self.vmctx
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -646,8 +688,11 @@ where
|
||||
Inner: Kind,
|
||||
{
|
||||
fn to_export(&self) -> Export {
|
||||
let func = unsafe { FuncPointer::new(self.f.as_ptr()) };
|
||||
let ctx = Context::Internal;
|
||||
let func = unsafe { FuncPointer::new(self.func.as_ptr()) };
|
||||
let ctx = match self.func_env {
|
||||
Some(func_env) => Context::External(func_env.cast().as_ptr()),
|
||||
None => Context::Internal,
|
||||
};
|
||||
let signature = Arc::new(FuncSig::new(Args::types(), Rets::types()));
|
||||
|
||||
Export::Function {
|
||||
|
@ -512,16 +512,16 @@ pub struct FuncEnv {
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct FuncCtx {
|
||||
pub vmctx: NonNull<Ctx>,
|
||||
pub func_env: *mut FuncEnv,
|
||||
pub(crate) vmctx: NonNull<Ctx>,
|
||||
pub(crate) func_env: Option<NonNull<FuncEnv>>,
|
||||
}
|
||||
|
||||
/// An imported function, which contains the vmctx that owns this function.
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct ImportedFunc {
|
||||
pub func: *const Func,
|
||||
pub func_ctx: NonNull<FuncCtx>,
|
||||
pub(crate) func: *const Func,
|
||||
pub(crate) func_ctx: NonNull<FuncCtx>,
|
||||
}
|
||||
|
||||
// manually implemented because ImportedFunc contains raw pointers
|
||||
|
Loading…
x
Reference in New Issue
Block a user