wrap vm::Ctx (with more std::memory::transmute calls)

This commit is contained in:
Valery Antopol 2022-03-02 20:42:32 +03:00
parent daaa626c02
commit 4bd99589b0
6 changed files with 255 additions and 122 deletions

View File

@ -5,7 +5,7 @@
use std::path::PathBuf;
use thiserror::Error;
use wasmer_core::types::FuncSig;
use it_memory_traits::{SequentialMemoryView, SequentialReader, SequentialWriter};
use it_memory_traits::{SequentialMemoryView};
pub struct Value {}
@ -24,13 +24,14 @@ pub trait WasmBackend: Clone + 'static {
type WITMemory: Memory<Self> + it_memory_traits::Memory<Self::WITMemoryView> + Clone + 'static;
//type SR: SequentialReader;
//type SW: SequentialWriter;
type DynamicFunc: DynamicFunc<'static>;
type DynamicFunc: DynamicFunc<'static, Self>;
type WITMemoryView: for<'a> SequentialMemoryView<'a /* SR = Self::SR, SW = Self::SW*/> + 'static;
type FunctionExport: FunctionExport;
type M: Module<Self>;
type I: Instance<Self>;
type Wasi: WasiImplementation<Self>;
type Namespace: Namespace<Self>;
type ExportContext: ExportContext<Self>;
fn compile(wasm: &[u8]) -> WasmBackendResult<Self::M>;
}
@ -56,10 +57,7 @@ pub trait Instance<WB: WasmBackend> {
>;
fn exports(&self) -> &<WB as WasmBackend>::Exports;
fn import_object(&self) -> &<WB as WasmBackend>::IO;
// maybe hide them inside impl
fn context(&self) -> &wasmer_core::vm::Ctx;
fn context_mut(&mut self) -> &mut wasmer_core::vm::Ctx;
fn memory(&self, memory_index: u32) -> <WB as WasmBackend>::WITMemory;
}
pub trait Exports<WB: WasmBackend> {
@ -97,11 +95,6 @@ pub trait ImportObject<WB: WasmBackend>:
fn get_memory_env(
&self,
) -> Option<Export<<WB as WasmBackend>::MemoryExport, <WB as WasmBackend>::FunctionExport>>;
/*
fn maybe_with_namespace<Func, InnerRet>(&self, namespace: &str, f: Func) -> Option<InnerRet>
where
Func: FnOnce(&(dyn wasmer_runtime::LikeNamespace + Send)) -> Option<InnerRet>,
InnerRet: Sized;*/
}
pub trait WasiImplementation<WB: WasmBackend> {
@ -112,6 +105,8 @@ pub trait WasiImplementation<WB: WasmBackend> {
preopened_files: Vec<PathBuf>,
mapped_dirs: Vec<(String, PathBuf)>,
) -> Result<<WB as WasmBackend>::IO, String>;
fn get_wasi_state(instance: &mut <WB as WasmBackend>::I) -> &wasmer_wasi::state::WasiState;
}
pub trait MemoryExport {}
@ -120,17 +115,15 @@ pub trait FunctionExport {}
pub trait Memory<WB: WasmBackend> {
fn new(export: <WB as WasmBackend>::MemoryExport) -> Self;
fn view_from_ctx(
ctx: &wasmer_runtime::Ctx,
memory_index: u32,
) -> <WB as WasmBackend>::WITMemoryView;
fn size(&self) -> usize;
}
pub trait DynamicFunc<'a> {
fn new<F>(sig: std::sync::Arc<FuncSig>, func: F) -> Self
pub trait DynamicFunc<'a, WB: WasmBackend> {
fn new<'c, F>(sig: std::sync::Arc<FuncSig>, func: F) -> Self
where
F: Fn(
&mut wasmer_core::vm::Ctx,
&mut <WB as WasmBackend>::ExportContext,
&[wasmer_core::types::Value],
) -> Vec<wasmer_core::types::Value>
+ 'static;
@ -143,3 +136,15 @@ pub trait Namespace<WB: WasmBackend>: LikeNamespace<WB> {
}
pub trait LikeNamespace<WB: WasmBackend> {}
pub trait ExportContext<WB: WasmBackend> {
fn memory(&self, memory_index: u32) -> <WB as WasmBackend>::WITMemory;
unsafe fn get_export_func_by_name<'a, Args, Rets>(
&mut self,
name: &str,
) -> Result<wasmer_runtime::Func<'a, Args, Rets>, wasmer_runtime::error::ResolveError>
where
Args: wasmer_core::typed_func::WasmTypeList,
Rets: wasmer_core::typed_func::WasmTypeList;
}

View File

@ -1,6 +1,6 @@
use std::marker::PhantomData;
//use std::marker::PhantomData;
use marine_wasm_backend_traits::{
DynamicFunc, Export, LikeNamespace, Memory, Namespace, Value, WasmBackend,
DynamicFunc, Export, ExportContext, LikeNamespace, Memory, Namespace, Value, WasmBackend,
};
use marine_wasm_backend_traits::WasmBackendResult;
use marine_wasm_backend_traits::WasmBackendError;
@ -15,9 +15,14 @@ use marine_wasm_backend_traits::WasiImplementation;
use std::path::PathBuf;
use std::slice::Windows;
use std::sync::Arc;
use wasmer_core::backend::SigRegistry;
use wasmer_core::error::ResolveError;
use wasmer_core::fault::raw::longjmp;
use wasmer_core::prelude::vm::Ctx;
use wasmer_core::types::FuncSig;
use wasmer_core::Func;
use wasmer_core::module::ExportIndex;
//use wasmer_core::prelude::vm::Ctx;
use wasmer_core::types::{FuncSig, LocalOrImport};
use wasmer_wasi::state::WasiState;
mod memory_access;
mod memory;
@ -32,7 +37,7 @@ pub struct WasmerBackend /*<'a>*/ {
// _data: &'a PhantomData<i32>,
}
impl<'b> WasmBackend for WasmerBackend /*<'b>*/ {
impl WasmBackend for WasmerBackend /*<'b>*/ {
type Exports = WasmerInstance;
type MemoryExport = WasmerMemoryExport;
type FunctionExport = WasmerFunctionExport;
@ -46,6 +51,7 @@ impl<'b> WasmBackend for WasmerBackend /*<'b>*/ {
type Wasi = WasmerWasiImplementation;
type DynamicFunc = WasmerDynamicFunc;
type Namespace = WasmerNamespace;
type ExportContext = WasmerExportContext<'static>;
fn compile(wasm: &[u8]) -> WasmBackendResult<WasmerModule> {
wasmer_runtime::compile(wasm)
@ -96,11 +102,8 @@ impl Instance<WasmerBackend> for WasmerInstance {
&self.import_object
}
fn context(&self) -> &wasmer_core::vm::Ctx {
self.instance.context()
}
fn context_mut(&mut self) -> &mut wasmer_core::vm::Ctx {
self.instance.context_mut()
fn memory(&self, memory_index: u32) -> <WasmerBackend as WasmBackend>::WITMemory {
WITMemory(self.instance.context().memory(memory_index).clone())
}
}
@ -220,6 +223,10 @@ impl WasiImplementation<WasmerBackend> for WasmerWasiImplementation {
)
.map(|import_object| WasmerImportObject { import_object })
}
fn get_wasi_state(instance: &mut <WasmerBackend as WasmBackend>::I) -> &WasiState {
unsafe { wasmer_wasi::state::get_wasi_state(instance.instance.context_mut()) }
}
}
impl Exports<WasmerBackend> for WasmerInstance {
@ -272,7 +279,7 @@ impl Memory<WasmerBackend> for WITMemory {
fn new(export: WasmerMemoryExport) -> Self {
WITMemory(export.memory)
}
/*
fn view_from_ctx(ctx: &Ctx, memory_index: u32) -> WITMemoryView<'static> {
let memory = unsafe {
std::mem::transmute::<&'_ wasmer_runtime::Memory, &'static wasmer_runtime::Memory>(
@ -281,6 +288,9 @@ impl Memory<WasmerBackend> for WITMemory {
};
WITMemoryView(memory.view::<u8>())
}*/
fn size(&self) -> usize {
self.0.size().bytes().0
}
}
@ -288,13 +298,29 @@ pub struct WasmerDynamicFunc {
func: wasmer_core::typed_func::DynamicFunc<'static>,
}
impl<'a> DynamicFunc<'a> for WasmerDynamicFunc {
impl<'a> DynamicFunc<'a, WasmerBackend> for WasmerDynamicFunc {
fn new<F>(sig: Arc<FuncSig>, func: F) -> Self
where
F: Fn(&mut Ctx, &[wasmer_core::prelude::Value]) -> Vec<wasmer_core::prelude::Value>
F: Fn(
&mut WasmerExportContext<'static>,
&[wasmer_core::prelude::Value],
) -> Vec<wasmer_core::prelude::Value>
+ 'static,
{
let func = wasmer_core::typed_func::DynamicFunc::new(sig, func);
let func = wasmer_core::typed_func::DynamicFunc::new(
sig,
move |ctx: &mut wasmer_core::vm::Ctx, args: &[wasmer_core::prelude::Value]| unsafe {
let mut ctx = WasmerExportContext {
ctx: std::mem::transmute::<
&'_ mut wasmer_core::vm::Ctx,
&'static mut wasmer_core::vm::Ctx,
>(ctx),
};
func(&mut ctx, args)
},
);
Self { func }
}
}
@ -322,3 +348,83 @@ struct WasmerLikeNamespace {
}
impl LikeNamespace<WasmerBackend> for WasmerLikeNamespace {}
pub struct WasmerExportContext<'c> {
ctx: &'c mut wasmer_core::vm::Ctx,
}
impl<'c> ExportContext<WasmerBackend> for WasmerExportContext<'c> {
fn memory(&self, memory_index: u32) -> <WasmerBackend as WasmBackend>::WITMemory {
WITMemory(self.ctx.memory(memory_index).clone())
}
unsafe fn get_export_func_by_name<'a, Args, Rets>(
&mut self,
name: &str,
) -> Result<Func<'a, Args, Rets>, ResolveError>
where
Args: wasmer_core::typed_func::WasmTypeList,
Rets: wasmer_core::typed_func::WasmTypeList,
{
let ctx = &mut self.ctx;
let module_inner = &(*ctx.module);
let export_index =
module_inner
.info
.exports
.get(name)
.ok_or_else(|| ResolveError::ExportNotFound {
name: name.to_string(),
})?;
let export_func_index = match export_index {
ExportIndex::Func(func_index) => func_index,
_ => {
return Err(ResolveError::ExportWrongType {
name: name.to_string(),
})
}
};
let export_func_signature_idx = *module_inner
.info
.func_assoc
.get(*export_func_index)
.expect("broken invariant, incorrect func index");
let export_func_signature = &module_inner.info.signatures[export_func_signature_idx];
let export_func_signature_ref = SigRegistry.lookup_signature_ref(export_func_signature);
if export_func_signature_ref.params() != Args::types()
|| export_func_signature_ref.returns() != Rets::types()
{
return Err(ResolveError::Signature {
expected: (*export_func_signature).clone(),
found: Args::types().to_vec(),
});
}
let func_wasm_inner = module_inner
.runnable_module
.get_trampoline(&module_inner.info, export_func_signature_idx)
.unwrap();
let export_func_ptr = match export_func_index.local_or_import(&module_inner.info) {
LocalOrImport::Local(local_func_index) => module_inner
.runnable_module
.get_func(&module_inner.info, local_func_index)
.unwrap(),
_ => {
return Err(ResolveError::ExportNotFound {
name: name.to_string(),
})
}
};
let typed_func: Func<'_, Args, Rets, wasmer_core::typed_func::Wasm> =
Func::from_raw_parts(func_wasm_inner, export_func_ptr, None, (*ctx) as _);
Ok(typed_func)
}
}

View File

@ -23,7 +23,7 @@ use marine_wasm_backend_traits::ImportObject;
use wasmer_wasi::WasiVersion;
//use wasmer_runtime::ImportObject;
use wasmer_core::vm::Ctx;
//use wasmer_core::vm::Ctx;
use std::path::PathBuf;
use std::collections::HashMap;
@ -32,11 +32,12 @@ use std::collections::HashSet;
// 65536*1600 ~ 100 Mb (Wasm page size is 64 Kb)
const DEFAULT_HEAP_PAGES_COUNT: u32 = 1600;
pub type HostExportedFunc = Box<dyn Fn(&mut Ctx, Vec<IValue>) -> Option<IValue> + 'static>;
pub type HostExportedFunc<WB> =
Box<dyn Fn(&mut <WB as WasmBackend>::ExportContext, Vec<IValue>) -> Option<IValue> + 'static>;
pub struct HostImportDescriptor {
pub struct HostImportDescriptor<WB: WasmBackend> {
/// This closure will be invoked for corresponding import.
pub host_exported_func: HostExportedFunc,
pub host_exported_func: HostExportedFunc<WB>,
/// Type of the closure arguments.
pub argument_types: Vec<IType>,
@ -58,7 +59,7 @@ pub struct MModuleConfig<WB: WasmBackend> {
pub raw_imports: <WB as WasmBackend>::IO,
/// Imports from the host side that will be used in module instantiation process.
pub host_imports: HashMap<String, HostImportDescriptor>,
pub host_imports: HashMap<String, HostImportDescriptor<WB>>,
/// Desired WASI version.
pub wasi_version: WasiVersion,

View File

@ -29,22 +29,23 @@ use crate::HostImportDescriptor;
//use crate::module::wit_prelude::WITMemoryView;
//use wasmer_core::Func;
use wasmer_core::vm::Ctx;
//use wasmer_core::vm::Ctx;
//use wasmer_core::typed_func::DynamicFunc;
use wasmer_core::types::Value as WValue;
use wasmer_core::types::FuncSig;
use it_lilo::lifter::ILifter;
use it_lilo::lowerer::ILowerer;
use it_memory_traits::Memory as ITMemory;
use std::cell::RefCell;
use std::rc::Rc;
use marine_wasm_backend_traits::WasmBackend;
use marine_wasm_backend_traits::Memory;
use marine_wasm_backend_traits::DynamicFunc;
use marine_wasm_backend_traits::ExportContext;
pub(crate) fn create_host_import_func<WB: WasmBackend>(
descriptor: HostImportDescriptor,
descriptor: HostImportDescriptor<WB>,
record_types: Rc<MRecordTypes>,
) -> <WB as WasmBackend>::DynamicFunc {
let allocate_func: AllocateFunc = Box::new(RefCell::new(None));
@ -66,12 +67,11 @@ pub(crate) fn create_host_import_func<WB: WasmBackend>(
let raw_args = itypes_args_to_wtypes(&argument_types);
let raw_output = itypes_output_to_wtypes(&output_type_to_types(output_type));
let func = move |ctx: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
let func =
move |ctx: &mut <WB as WasmBackend>::ExportContext, inputs: &[WValue]| -> Vec<WValue> {
let result = {
let memory_index = 0;
//let memory = ctx.memory(memory_index);
//let memory_view = WITMemoryView(memory.view::<u8>());
let memory_view = <WB as WasmBackend>::WITMemory::view_from_ctx(ctx, memory_index);
let memory_view = ctx.memory(memory_index).view();
let li_helper = LiHelper::new(record_types.clone());
let lifter = ILifter::new(memory_view, &li_helper);
@ -86,12 +86,29 @@ pub(crate) fn create_host_import_func<WB: WasmBackend>(
}
};
let ctx = ctx;
init_wasm_func_once!(allocate_func, ctx, (i32, i32), i32, ALLOCATE_FUNC_NAME, 2);
/*if allocate_func.borrow().is_none() {
let raw_func = match unsafe {
ctx.get_export_func_by_name::<(i32, i32), i32>(ALLOCATE_FUNC_NAME)
} {
Ok(func) => func,
Err(_) => return vec![WValue::I32(2)],
};
unsafe {
// assumed that this function will be used only in the context of closure
// linked to a corresponding Wasm import, so it is safe to make is static
// because all Wasm imports live in the Wasmer instances, which
// is itself static (i.e., lives until the end of the program)
let raw_func = std::mem::transmute::<Func<'_, _, _>, Func<'static, _, _>>(raw_func);
*allocate_func.borrow_mut() = Some(raw_func);
}
}*/
let memory_index = 0;
//let memory = ctx.memory(memory_index);
//let memory_view = WITMemoryView(memory.view::<u8>());
let memory_view = <WB as WasmBackend>::WITMemory::view_from_ctx(ctx, memory_index);
let memory_view = ctx.memory(memory_index).view();
let lo_helper = LoHelper::new(&allocate_func);
let t = ILowerer::new(memory_view, &lo_helper)
.map_err(HostImportError::LowererError)

View File

@ -17,6 +17,7 @@
use super::WType;
use crate::IType;
/*
use wasmer_core::backend::SigRegistry;
use wasmer_core::module::ExportIndex;
use wasmer_core::vm::Ctx;
@ -24,7 +25,9 @@ use wasmer_core::typed_func::WasmTypeList;
use wasmer_runtime::Func;
use wasmer_runtime::error::ResolveError;
use wasmer_runtime::types::LocalOrImport;
*/
/*
// based on Wasmer: https://github.com/wasmerio/wasmer/blob/081f6250e69b98b9f95a8f62ad6d8386534f3279/lib/runtime-core/src/instance.rs#L863
/// Extract export function from Wasmer instance by name.
pub(super) unsafe fn get_export_func_by_name<'a, Args, Rets>(
@ -95,7 +98,7 @@ where
Ok(typed_func)
}
*/
pub(super) fn itypes_args_to_wtypes(itypes: &[IType]) -> Vec<WType> {
itypes
.iter()
@ -127,9 +130,8 @@ pub(super) fn itypes_output_to_wtypes(itypes: &[IType]) -> Vec<WType> {
macro_rules! init_wasm_func_once {
($func:ident, $ctx:ident, $args:ty, $rets:ty, $func_name:ident, $ret_error_code: expr) => {
if $func.borrow().is_none() {
let raw_func = match unsafe {
super::utils::get_export_func_by_name::<$args, $rets>($ctx, $func_name)
} {
let raw_func = match unsafe { $ctx.get_export_func_by_name::<$args, $rets>($func_name) }
{
Ok(func) => func,
Err(_) => return vec![WValue::I32($ret_error_code)],
};

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
use std::borrow::BorrowMut;
use super::wit_prelude::*;
use super::MFunctionSignature;
use super::MRecordTypes;
@ -29,6 +30,7 @@ use marine_wasm_backend_traits::WasiImplementation;
use marine_wasm_backend_traits::Exports;
use marine_wasm_backend_traits::Namespace;
use marine_wasm_backend_traits::DynamicFunc;
use marine_wasm_backend_traits::Memory;
use marine_it_interfaces::MITInterfaces;
use marine_it_parser::extract_it_from_module;
@ -196,7 +198,7 @@ impl<WB: WasmBackend> MModule<WB> {
}
pub(crate) fn get_wasi_state(&mut self) -> &wasmer_wasi::state::WasiState {
unsafe { wasmer_wasi::state::get_wasi_state(self.wasmer_instance.context_mut()) }
<WB as WasmBackend>::Wasi::get_wasi_state(self.wasmer_instance.borrow_mut())
}
/// Returns heap size that this module consumes in bytes.
@ -204,8 +206,7 @@ impl<WB: WasmBackend> MModule<WB> {
// Wasmer 0.17.1 supports only one memory
const MEMORY_INDEX: u32 = 0;
let pages = self.wasmer_instance.context().memory(MEMORY_INDEX).size();
pages.bytes().0
self.wasmer_instance.memory(MEMORY_INDEX).size()
}
// TODO: change the cloning Callable behaviour after changes of Wasmer API
@ -311,7 +312,7 @@ impl<WB: WasmBackend> MModule<WB> {
) -> MResult<<WB as WasmBackend>::IO> {
use marine_it_interfaces::ITAstType;
//use wasmer_core::typed_func::DynamicFunc;
use wasmer_core::vm::Ctx;
//use wasmer_core::vm::Ctx;
// returns function that will be called from imports of Wasmer module
fn dyn_func_from_raw_import<'a, 'b, F, WB, I1, I2>(
@ -320,7 +321,7 @@ impl<WB: WasmBackend> MModule<WB> {
raw_import: F,
) -> <WB as WasmBackend>::DynamicFunc
where
F: Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static,
F: Fn(&mut <WB as WasmBackend>::ExportContext, &[WValue]) -> Vec<WValue> + 'static,
WB: WasmBackend,
I1: Iterator<Item = &'a IType>,
I2: Iterator<Item = &'b IType>,
@ -342,8 +343,9 @@ impl<WB: WasmBackend> MModule<WB> {
interpreter: ITInterpreter<WB>,
import_namespace: String,
import_name: String,
) -> impl Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static {
move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
) -> impl Fn(&mut <WB as WasmBackend>::ExportContext, &[WValue]) -> Vec<WValue> + 'static
{
move |_: &mut <WB as WasmBackend>::ExportContext, inputs: &[WValue]| -> Vec<WValue> {
use wasmer_it::interpreter::stack::Stackable;
use super::type_converters::wval_to_ival;