feat(deprecated) Port DynamicFunc.

This commit is contained in:
Ivan Enderlin
2020-06-29 15:25:41 +02:00
parent 210c3a2fdf
commit d95f92fbf1
5 changed files with 159 additions and 33 deletions

View File

@@ -2,22 +2,29 @@ use crate::{
error::ExportError, export::Exportable, import::LikeNamespace, module::Module, new, error::ExportError, export::Exportable, import::LikeNamespace, module::Module, new,
structures::TypedIndex, types::Value, vm, structures::TypedIndex, types::Value, vm,
}; };
use std::error::Error; use std::{
cell::{Ref, RefCell},
error::Error,
};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct PreInstance { pub(crate) struct PreInstance {
pub(crate) vmctx: vm::Ctx, pub(crate) vmctx: RefCell<vm::Ctx>,
} }
impl PreInstance { impl PreInstance {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
Self { Self {
vmctx: vm::Ctx::new(), vmctx: RefCell::new(vm::Ctx::new()),
} }
} }
pub(crate) fn vmctx(&self) -> RefCell<vm::Ctx> {
self.vmctx.clone()
}
pub(crate) fn vmctx_ptr(&self) -> *mut vm::Ctx { pub(crate) fn vmctx_ptr(&self) -> *mut vm::Ctx {
&self.vmctx as *const _ as *mut _ self.vmctx.as_ptr()
} }
} }
@@ -71,12 +78,12 @@ impl Instance {
Module::new(self.new_instance.module().clone()) Module::new(self.new_instance.module().clone())
} }
pub fn context(&self) -> &vm::Ctx { pub fn context(&self) -> Ref<vm::Ctx> {
&self.pre_instance.vmctx self.pre_instance.vmctx.borrow()
} }
pub fn context_mut(&mut self) -> &mut vm::Ctx { pub fn context_mut(&mut self) -> &mut vm::Ctx {
&mut self.pre_instance.vmctx self.pre_instance.vmctx.get_mut()
} }
} }

View File

@@ -38,7 +38,7 @@ pub use functional_api::{
pub mod prelude { pub mod prelude {
pub use crate::import::{namespace, ImportObject, Namespace}; pub use crate::import::{namespace, ImportObject, Namespace};
pub use crate::typed_func::Func; pub use crate::typed_func::{DynamicFunc, Func};
pub use crate::types::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, Type, Value}; pub use crate::types::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex, Type, Value};
} }

View File

@@ -1,12 +1,15 @@
use crate::{ use crate::{
cache::Artifact, cache::Artifact,
error::InstantiationError, error::{InstantiationError, RuntimeError},
import::{ImportObject, Namespace}, import::{ImportObject, Namespace},
instance::{Instance, PreInstance}, instance::{Instance, PreInstance},
new, vm, new,
types::{FuncSig, Value},
vm,
}; };
use new::wasmer_runtime::Export; use new::wasmer_runtime::Export;
use std::{ use std::{
cell::RefCell,
collections::HashMap, collections::HashMap,
convert::{AsRef, Infallible}, convert::{AsRef, Infallible},
ptr, ptr,
@@ -52,6 +55,10 @@ impl Module {
Export::Function(mut function) => { Export::Function(mut function) => {
// That's an ugly hack. Go your way :-]. // That's an ugly hack. Go your way :-].
{ {
// That's a static host function
// constructed with
// `new::wasmer::Function::new_env`.
if !function.address.is_null() {
// An empty `vm::Ctx` was created in // An empty `vm::Ctx` was created in
// `Func` as a host function // `Func` as a host function
// environment. The internals of // environment. The internals of
@@ -75,6 +82,48 @@ impl Module {
// environment hack. // environment hack.
function.vmctx = pre_instance.vmctx_ptr() as _; function.vmctx = pre_instance.vmctx_ptr() as _;
} }
// That's a dynamic host function
// constructed with
// `new::wasmer::Function::new_dynamic_env`.
else {
// `new::wasmer::VMDynamicFunctionWithEnv`
// is private to `new::wasmer`. Let's
// replicate it, and hope the layout
// is the same!
struct VMDynamicFunctionWithEnv<Env>
where
Env: Sized + 'static,
{
#[allow(unused)]
function_type: FuncSig,
#[allow(unused)]
func: Box<
dyn Fn(
&mut Env,
&[Value],
)
-> Result<Vec<Value>, RuntimeError>
+ 'static,
>,
env: RefCell<Env>,
}
// Get back the `vmctx` as it is
// stored by
// `new::wasmer::Function::new_dynamic_env`.
let vmctx: Box<
new::wasmer_runtime::VMDynamicFunctionContext<
VMDynamicFunctionWithEnv<vm::Ctx>,
>,
> = unsafe { Box::from_raw(function.vmctx as *mut _) };
// Replace the environment by ours.
vmctx.ctx.env.swap(&pre_instance.vmctx());
// … without anyone noticing…
function.vmctx = Box::into_raw(vmctx) as _;
}
}
( (
(namespace, name), (namespace, name),

View File

@@ -2,7 +2,7 @@ use crate::{
error::{ExportError, RuntimeError}, error::{ExportError, RuntimeError},
get_global_store, get_global_store,
new::{self, wasm_common::NativeWasmType}, new::{self, wasm_common::NativeWasmType},
types::{FuncDescriptor, Type, Value}, types::{FuncDescriptor, FuncSig, Type, Value},
vm, vm,
}; };
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -204,3 +204,73 @@ where
} }
} }
} }
#[derive(Clone)]
pub struct DynamicFunc {
new_function: new::wasmer::Function,
}
impl DynamicFunc {
pub fn new<F>(signature: &FuncSig, func: F) -> Self
where
F: Fn(&mut vm::Ctx, &[Value]) -> Result<Vec<Value>, RuntimeError> + 'static,
{
// Create an empty `vm::Ctx`, that is going to be overwritten by `Instance::new`.
let ctx = vm::Ctx::new();
Self {
new_function: new::wasmer::Function::new_dynamic_env(
get_global_store(),
signature,
ctx,
func,
),
}
}
pub fn signature(&self) -> &FuncDescriptor {
self.new_function.ty()
}
pub fn params(&self) -> &[Type] {
self.signature().params()
}
pub fn returns(&self) -> &[Type] {
self.signature().results()
}
pub fn dyn_call(&self, params: &[Value]) -> Result<Box<[Value]>, RuntimeError> {
self.new_function.call(params)
}
}
impl From<DynamicFunc> for new::wasmer::Extern {
fn from(dynamic_func: DynamicFunc) -> Self {
new::wasmer::Extern::Function(dynamic_func.new_function)
}
}
impl From<&new::wasmer::Function> for DynamicFunc {
fn from(new_function: &new::wasmer::Function) -> Self {
Self {
new_function: new_function.clone(),
}
}
}
impl<'a> new::wasmer::Exportable<'a> for DynamicFunc {
fn to_export(&self) -> new::wasmer_runtime::Export {
self.new_function.to_export()
}
fn get_self_from_extern(r#extern: &'a new::wasmer::Extern) -> Result<&'a Self, ExportError> {
match r#extern {
new::wasmer::Extern::Function(dynamic_func) => Ok(
// It's not ideal to call `Box::leak` here, but it would introduce too much changes in the `new::wasmer` API to support `Cow` or similar.
Box::leak(Box::<DynamicFunc>::new(dynamic_func.into())),
),
_ => Err(ExportError::IncompatibleType),
}
}
}

View File

@@ -8,7 +8,7 @@ pub use wasmer_runtime_core::memory::ptr::{Array, Item, WasmPtr};
pub use wasmer_runtime_core::memory::Memory; pub use wasmer_runtime_core::memory::Memory;
pub use wasmer_runtime_core::module::Module; pub use wasmer_runtime_core::module::Module;
pub use wasmer_runtime_core::table::Table; pub use wasmer_runtime_core::table::Table;
pub use wasmer_runtime_core::typed_func::Func; pub use wasmer_runtime_core::typed_func::{DynamicFunc, Func};
pub use wasmer_runtime_core::types; pub use wasmer_runtime_core::types;
pub use wasmer_runtime_core::vm::Ctx; pub use wasmer_runtime_core::vm::Ctx;
pub use wasmer_runtime_core::{ pub use wasmer_runtime_core::{