mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 05:08:19 +00:00
Make dynamic functions work again
This commit is contained in:
@@ -7,13 +7,11 @@ use crate::RuntimeError;
|
|||||||
use crate::{ExternType, FunctionType, GlobalType, MemoryType, TableType, ValType};
|
use crate::{ExternType, FunctionType, GlobalType, MemoryType, TableType, ValType};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use wasm_common::{
|
use wasm_common::{HostFunction, Pages, ValueType, WasmTypeList, WithEnv, WithoutEnv};
|
||||||
HostFunction, Pages, SignatureIndex, ValueType, WasmTypeList, WithEnv, WithoutEnv,
|
|
||||||
};
|
|
||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
wasmer_call_trampoline, Export, ExportFunction, ExportGlobal, ExportMemory, ExportTable,
|
wasmer_call_trampoline, Export, ExportFunction, ExportGlobal, ExportMemory, ExportTable,
|
||||||
InstanceHandle, LinearMemory, MemoryError, Table as RuntimeTable, VMCallerCheckedAnyfunc,
|
LinearMemory, MemoryError, Table as RuntimeTable, VMCallerCheckedAnyfunc, VMContext,
|
||||||
VMContext, VMDynamicFunctionImportContext, VMFunctionBody, VMFunctionKind, VMGlobalDefinition,
|
VMDynamicFunctionImportContext, VMFunctionBody, VMFunctionKind, VMGlobalDefinition,
|
||||||
VMMemoryDefinition, VMTrampoline,
|
VMMemoryDefinition, VMTrampoline,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -542,6 +540,7 @@ impl Function {
|
|||||||
let dynamic_ctx =
|
let dynamic_ctx =
|
||||||
VMDynamicFunctionImportContext::from_context(VMDynamicFunctionWithoutEnv {
|
VMDynamicFunctionImportContext::from_context(VMDynamicFunctionWithoutEnv {
|
||||||
func: Box::new(func),
|
func: Box::new(func),
|
||||||
|
function_type: ty.clone(),
|
||||||
});
|
});
|
||||||
let address = std::ptr::null() as *const VMFunctionBody;
|
let address = std::ptr::null() as *const VMFunctionBody;
|
||||||
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
|
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
|
||||||
@@ -568,6 +567,7 @@ impl Function {
|
|||||||
let dynamic_ctx = VMDynamicFunctionImportContext::from_context(VMDynamicFunctionWithEnv {
|
let dynamic_ctx = VMDynamicFunctionImportContext::from_context(VMDynamicFunctionWithEnv {
|
||||||
env,
|
env,
|
||||||
func: Box::new(func),
|
func: Box::new(func),
|
||||||
|
function_type: ty.clone(),
|
||||||
});
|
});
|
||||||
let address = std::ptr::null() as *const VMFunctionBody;
|
let address = std::ptr::null() as *const VMFunctionBody;
|
||||||
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
|
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
|
||||||
@@ -777,16 +777,21 @@ impl std::fmt::Debug for Function {
|
|||||||
/// This trait is one that all dynamic funcitons must fulfill.
|
/// This trait is one that all dynamic funcitons must fulfill.
|
||||||
trait VMDynamicFunction {
|
trait VMDynamicFunction {
|
||||||
fn call(&self, args: &[Val]) -> Result<Vec<Val>, RuntimeError>;
|
fn call(&self, args: &[Val]) -> Result<Vec<Val>, RuntimeError>;
|
||||||
|
fn function_type(&self) -> &FunctionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VMDynamicFunctionWithoutEnv {
|
struct VMDynamicFunctionWithoutEnv {
|
||||||
func: Box<dyn Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static>,
|
func: Box<dyn Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static>,
|
||||||
|
function_type: FunctionType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VMDynamicFunction for VMDynamicFunctionWithoutEnv {
|
impl VMDynamicFunction for VMDynamicFunctionWithoutEnv {
|
||||||
fn call(&self, args: &[Val]) -> Result<Vec<Val>, RuntimeError> {
|
fn call(&self, args: &[Val]) -> Result<Vec<Val>, RuntimeError> {
|
||||||
(*self.func)(&args)
|
(*self.func)(&args)
|
||||||
}
|
}
|
||||||
|
fn function_type(&self) -> &FunctionType {
|
||||||
|
&self.function_type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VMDynamicFunctionWithEnv<Env>
|
struct VMDynamicFunctionWithEnv<Env>
|
||||||
@@ -795,6 +800,7 @@ where
|
|||||||
{
|
{
|
||||||
func: Box<dyn Fn(&mut Env, &[Val]) -> Result<Vec<Val>, RuntimeError> + 'static>,
|
func: Box<dyn Fn(&mut Env, &[Val]) -> Result<Vec<Val>, RuntimeError> + 'static>,
|
||||||
env: *mut Env,
|
env: *mut Env,
|
||||||
|
function_type: FunctionType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Env> VMDynamicFunction for VMDynamicFunctionWithEnv<Env>
|
impl<Env> VMDynamicFunction for VMDynamicFunctionWithEnv<Env>
|
||||||
@@ -804,17 +810,15 @@ where
|
|||||||
fn call(&self, args: &[Val]) -> Result<Vec<Val>, RuntimeError> {
|
fn call(&self, args: &[Val]) -> Result<Vec<Val>, RuntimeError> {
|
||||||
unsafe { (*self.func)(&mut *self.env, &args) }
|
unsafe { (*self.func)(&mut *self.env, &args) }
|
||||||
}
|
}
|
||||||
|
fn function_type(&self) -> &FunctionType {
|
||||||
|
&self.function_type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait VMDynamicFunctionImportCall<T: VMDynamicFunction> {
|
trait VMDynamicFunctionImportCall<T: VMDynamicFunction> {
|
||||||
fn from_context(ctx: T) -> Self;
|
fn from_context(ctx: T) -> Self;
|
||||||
fn address_ptr() -> *const VMFunctionBody;
|
fn address_ptr() -> *const VMFunctionBody;
|
||||||
unsafe fn func_wrapper(
|
unsafe fn func_wrapper(&self, values_vec: *mut i128);
|
||||||
&self,
|
|
||||||
caller_vmctx: *mut VMContext,
|
|
||||||
sig_index: SignatureIndex,
|
|
||||||
values_vec: *mut i128,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: VMDynamicFunction> VMDynamicFunctionImportCall<T> for VMDynamicFunctionImportContext<T> {
|
impl<T: VMDynamicFunction> VMDynamicFunctionImportCall<T> for VMDynamicFunctionImportContext<T> {
|
||||||
@@ -835,25 +839,11 @@ impl<T: VMDynamicFunction> VMDynamicFunctionImportCall<T> for VMDynamicFunctionI
|
|||||||
// Note: we use the trick that the first param to this function is the `VMDynamicFunctionImportContext`
|
// Note: we use the trick that the first param to this function is the `VMDynamicFunctionImportContext`
|
||||||
// itself, so rather than doing `dynamic_ctx: &VMDynamicFunctionImportContext<T>`, we simplify it a bit
|
// itself, so rather than doing `dynamic_ctx: &VMDynamicFunctionImportContext<T>`, we simplify it a bit
|
||||||
&self,
|
&self,
|
||||||
caller_vmctx: *mut VMContext,
|
|
||||||
sig_index: SignatureIndex,
|
|
||||||
values_vec: *mut i128,
|
values_vec: *mut i128,
|
||||||
) {
|
) {
|
||||||
use std::panic::{self, AssertUnwindSafe};
|
use std::panic::{self, AssertUnwindSafe};
|
||||||
let result = panic::catch_unwind(AssertUnwindSafe(|| {
|
let result = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||||
// This is actually safe, since right now the function signature
|
let func_ty = self.ctx.function_type();
|
||||||
// receives two contexts:
|
|
||||||
// 1. `vmctx`: the context associated to where the function is defined.
|
|
||||||
// It will be `VMContext` in case is defined in Wasm, and a custom
|
|
||||||
// `Env` in case is host defined.
|
|
||||||
// 2. `caller_vmctx`: the context associated to whoever is calling that function.
|
|
||||||
//
|
|
||||||
// Because this code will only be reached when calling from wasm to host, we
|
|
||||||
// can assure the callee_vmctx is indeed a VMContext, and hence is completely
|
|
||||||
// safe to get a handle from it.
|
|
||||||
let handle = InstanceHandle::from_vmctx(caller_vmctx);
|
|
||||||
let module = handle.module_ref();
|
|
||||||
let func_ty = &module.signatures[sig_index];
|
|
||||||
let mut args = Vec::with_capacity(func_ty.params().len());
|
let mut args = Vec::with_capacity(func_ty.params().len());
|
||||||
for (i, ty) in func_ty.params().iter().enumerate() {
|
for (i, ty) in func_ty.params().iter().enumerate() {
|
||||||
args.push(Val::read_value_from(values_vec.add(i), *ty));
|
args.push(Val::read_value_from(values_vec.add(i), *ty));
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use super::binemit::TrampolineRelocSink;
|
use super::binemit::TrampolineRelocSink;
|
||||||
use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir};
|
use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir};
|
||||||
use cranelift_codegen::ir::{
|
use cranelift_codegen::ir::{
|
||||||
types, ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
|
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
|
||||||
};
|
};
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::TargetIsa;
|
||||||
use cranelift_codegen::print_errors::pretty_error;
|
use cranelift_codegen::print_errors::pretty_error;
|
||||||
@@ -13,7 +13,6 @@ use std::cmp;
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||||
use wasm_common::entity::EntityRef;
|
|
||||||
use wasm_common::SignatureIndex;
|
use wasm_common::SignatureIndex;
|
||||||
use wasmer_compiler::{CompileError, FunctionBody};
|
use wasmer_compiler::{CompileError, FunctionBody};
|
||||||
use wasmer_runtime::{ModuleInfo, VMOffsets};
|
use wasmer_runtime::{ModuleInfo, VMOffsets};
|
||||||
@@ -37,9 +36,6 @@ pub fn make_trampoline_dynamic_function(
|
|||||||
ir::ArgumentPurpose::VMContext,
|
ir::ArgumentPurpose::VMContext,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Add the `sig_index` parameter.
|
|
||||||
stub_sig.params.push(ir::AbiParam::new(types::I32));
|
|
||||||
|
|
||||||
// Add the `values_vec` parameter.
|
// Add the `values_vec` parameter.
|
||||||
stub_sig.params.push(ir::AbiParam::new(pointer_type));
|
stub_sig.params.push(ir::AbiParam::new(pointer_type));
|
||||||
|
|
||||||
@@ -80,10 +76,12 @@ pub fn make_trampoline_dynamic_function(
|
|||||||
let block_params = builder.func.dfg.block_params(block0);
|
let block_params = builder.func.dfg.block_params(block0);
|
||||||
let vmctx_ptr_val = block_params[0];
|
let vmctx_ptr_val = block_params[0];
|
||||||
|
|
||||||
|
// Note: not used at the moment, but keeping in case is useful
|
||||||
|
// for the future
|
||||||
// Get the signature index
|
// Get the signature index
|
||||||
let caller_sig_id = builder.ins().iconst(types::I32, sig_index.index() as i64);
|
// let caller_sig_id = builder.ins().iconst(types::I32, sig_index.index() as i64);
|
||||||
|
|
||||||
let callee_args = vec![vmctx_ptr_val, caller_sig_id, values_vec_ptr_val];
|
let callee_args = vec![vmctx_ptr_val, values_vec_ptr_val];
|
||||||
|
|
||||||
let new_sig = builder.import_signature(stub_sig);
|
let new_sig = builder.import_signature(stub_sig);
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ entity_impl!(MemoryIndex);
|
|||||||
/// Index type of a signature (imported or local) inside the WebAssembly module.
|
/// Index type of a signature (imported or local) inside the WebAssembly module.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct SignatureIndex(u32);
|
pub struct SignatureIndex(u32);
|
||||||
entity_impl!(SignatureIndex);
|
entity_impl!(SignatureIndex);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user