mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 22:58:18 +00:00
Reverse trampoline static generation now works! 🎉
This commit is contained in:
@@ -590,9 +590,7 @@ impl Function {
|
||||
ty: ty.clone(),
|
||||
func: Box::new(func),
|
||||
};
|
||||
let address = store
|
||||
.engine()
|
||||
.reverse_trampoline(&ty, func_wrapper as *const () as usize);
|
||||
let address = std::ptr::null() as *const () as *const VMFunctionBody;
|
||||
// let vmctx = std::ptr::null_mut() as *mut _ as *mut VMContext;
|
||||
let vmctx = Box::leak(Box::new(dynamic_ctx)) as *mut _ as *mut VMContext;
|
||||
let signature = store.engine().register_signature(&ty);
|
||||
|
||||
@@ -16,7 +16,8 @@ use cranelift_codegen::{binemit, isa, Context};
|
||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||
use wasm_common::entity::PrimaryMap;
|
||||
use wasm_common::{
|
||||
Features, FunctionType, LocalFunctionIndex, MemoryIndex, SignatureIndex, TableIndex,
|
||||
Features, FunctionIndex, FunctionType, LocalFunctionIndex, MemoryIndex, SignatureIndex,
|
||||
TableIndex,
|
||||
};
|
||||
use wasmer_compiler::CompileError;
|
||||
use wasmer_compiler::{
|
||||
@@ -169,18 +170,38 @@ impl Compiler for CraneliftCompiler {
|
||||
.collect::<Result<Vec<_>, CompileError>>()
|
||||
}
|
||||
|
||||
fn compile_wasm2host_trampoline(
|
||||
fn compile_wasm2host_trampolines(
|
||||
&self,
|
||||
signature: &FunctionType,
|
||||
callee_address: usize,
|
||||
) -> Result<FunctionBody, CompileError> {
|
||||
let mut cx = FunctionBuilderContext::new();
|
||||
make_wasm2host_trampoline(&*self.isa, &mut cx, signature, callee_address as _)
|
||||
// signatures
|
||||
// .par_iter()
|
||||
// .map_init(FunctionBuilderContext::new, |mut cx, sig| {
|
||||
// make_wasm2host_trampoline(&*self.isa, &mut cx, sig)
|
||||
// })
|
||||
// .collect::<Result<Vec<_>, CompileError>>()
|
||||
module: &Module,
|
||||
) -> Result<PrimaryMap<FunctionIndex, FunctionBody>, CompileError> {
|
||||
use wasmer_runtime::VMOffsets;
|
||||
let isa = self.isa();
|
||||
let frontend_config = isa.frontend_config();
|
||||
let offsets = VMOffsets::new(frontend_config.pointer_bytes(), module);
|
||||
Ok(module
|
||||
.functions
|
||||
.iter()
|
||||
.take(module.num_imported_funcs)
|
||||
.map(|(function_index, signature)| {
|
||||
let func_type = &module.signatures[*signature];
|
||||
(function_index, func_type)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.par_iter()
|
||||
.map_init(
|
||||
FunctionBuilderContext::new,
|
||||
|mut cx, (function_index, func_type)| {
|
||||
make_wasm2host_trampoline(
|
||||
&*self.isa,
|
||||
&offsets,
|
||||
&mut cx,
|
||||
&function_index,
|
||||
&func_type,
|
||||
)
|
||||
},
|
||||
)
|
||||
.collect::<Result<Vec<_>, CompileError>>()?
|
||||
.into_iter()
|
||||
.collect::<PrimaryMap<FunctionIndex, FunctionBody>>())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,31 +12,33 @@ use cranelift_codegen::print_errors::pretty_error;
|
||||
use cranelift_codegen::Context;
|
||||
use cranelift_codegen::{binemit, ir};
|
||||
use std::cmp;
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
|
||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||
use wasm_common::FunctionType;
|
||||
use wasm_common::{FunctionIndex, FunctionType};
|
||||
use wasmer_compiler::{CompileError, FunctionBody};
|
||||
use wasmer_runtime::VMFunctionBody;
|
||||
use wasmer_runtime::VMOffsets;
|
||||
|
||||
/// Create a trampoline for invoking a WebAssembly function.
|
||||
pub fn make_wasm2host_trampoline(
|
||||
isa: &dyn TargetIsa,
|
||||
offsets: &VMOffsets,
|
||||
fn_builder_ctx: &mut FunctionBuilderContext,
|
||||
callee_index: &FunctionIndex,
|
||||
func_type: &FunctionType,
|
||||
callee_address: *const VMFunctionBody,
|
||||
) -> Result<FunctionBody, CompileError> {
|
||||
let pointer_type = isa.pointer_type();
|
||||
let frontend_config = isa.frontend_config();
|
||||
let signature = signature_to_cranelift_ir(func_type, &frontend_config);
|
||||
let mut stub_sig = ir::Signature::new(frontend_config.default_call_conv);
|
||||
// Add the caller/callee `vmctx` parameters.
|
||||
// Add the caller `vmctx` parameter.
|
||||
stub_sig.params.push(ir::AbiParam::special(
|
||||
pointer_type,
|
||||
ir::ArgumentPurpose::VMContext,
|
||||
));
|
||||
|
||||
// Add the caller `vmctx` parameter.
|
||||
// Add the caller/callee `vmctx` parameter.
|
||||
stub_sig.params.push(ir::AbiParam::new(pointer_type));
|
||||
|
||||
// Add the `values_vec` parameter.
|
||||
@@ -87,15 +89,14 @@ pub fn make_wasm2host_trampoline(
|
||||
|
||||
let new_sig = builder.import_signature(stub_sig);
|
||||
|
||||
let callee_value = builder.ins().iconst(pointer_type, callee_address as i64);
|
||||
|
||||
// let vmctx = self.vmctx(&mut pos.func);
|
||||
// let base = builder.ins().global_value(pointer_type, vmctx);
|
||||
// let mem_flags = ir::MemFlags::trusted();
|
||||
// // Load the callee address.
|
||||
// let body_offset =
|
||||
// i32::try_from(self.offsets.vmctx_vmfunction_import_body(callee_index)).unwrap();
|
||||
// let callee_value = builder.ins().load(pointer_type, mem_flags, base, body_offset);
|
||||
let mem_flags = ir::MemFlags::trusted();
|
||||
// Load the callee address.
|
||||
let body_offset =
|
||||
i32::try_from(offsets.vmctx_vmfunction_import_dynamic_body(*callee_index)).unwrap();
|
||||
let callee_value =
|
||||
builder
|
||||
.ins()
|
||||
.load(pointer_type, mem_flags, caller_vmctx_ptr_val, body_offset);
|
||||
|
||||
builder
|
||||
.ins()
|
||||
@@ -116,6 +117,7 @@ pub fn make_wasm2host_trampoline(
|
||||
builder.finalize()
|
||||
}
|
||||
|
||||
// println!("{:?}", context.func);
|
||||
let mut code_buf = Vec::new();
|
||||
let mut reloc_sink = TrampolineRelocSink {};
|
||||
let mut trap_sink = binemit::NullTrapSink {};
|
||||
|
||||
@@ -9,7 +9,9 @@ use crate::target::Target;
|
||||
use crate::FunctionBodyData;
|
||||
use crate::ModuleTranslationState;
|
||||
use wasm_common::entity::PrimaryMap;
|
||||
use wasm_common::{Features, FunctionType, LocalFunctionIndex, MemoryIndex, TableIndex};
|
||||
use wasm_common::{
|
||||
Features, FunctionIndex, FunctionType, LocalFunctionIndex, MemoryIndex, TableIndex,
|
||||
};
|
||||
use wasmer_runtime::Module;
|
||||
use wasmer_runtime::{MemoryPlan, TablePlan};
|
||||
use wasmparser::{validate, OperatorValidatorConfig, ValidatingParserConfig};
|
||||
@@ -102,13 +104,8 @@ pub trait Compiler {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn compile_wasm2host_trampoline(
|
||||
fn compile_wasm2host_trampolines(
|
||||
&self,
|
||||
signature: &FunctionType,
|
||||
callee_address: usize,
|
||||
) -> Result<FunctionBody, CompileError>;
|
||||
// fn compile_wasm2host_trampolines(
|
||||
// &self,
|
||||
// signatures: &[FunctionType],
|
||||
// ) -> Result<Vec<FunctionBody>, CompileError>;
|
||||
module: &Module,
|
||||
) -> Result<PrimaryMap<FunctionIndex, FunctionBody>, CompileError>;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{CodeMemory, CompiledModule};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use wasm_common::entity::PrimaryMap;
|
||||
use wasm_common::{FunctionType, LocalFunctionIndex, SignatureIndex};
|
||||
use wasm_common::{FunctionIndex, FunctionType, LocalFunctionIndex, SignatureIndex};
|
||||
use wasmer_compiler::{CompileError, FunctionBody};
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_compiler::{Compiler, CompilerConfig};
|
||||
@@ -111,17 +111,6 @@ impl Engine for JITEngine {
|
||||
self.compiler().trampoline(sig)
|
||||
}
|
||||
|
||||
/// Retrieves the reverse trampoline
|
||||
fn reverse_trampoline(
|
||||
&self,
|
||||
func_type: &FunctionType,
|
||||
address: usize,
|
||||
) -> *const VMFunctionBody {
|
||||
self.compiler_mut()
|
||||
.reverse_trampoline(func_type, address)
|
||||
.expect("Can't construct trampoline")
|
||||
}
|
||||
|
||||
/// Validates a WebAssembly module
|
||||
fn validate(&self, binary: &[u8]) -> Result<(), CompileError> {
|
||||
self.compiler().validate(binary)
|
||||
@@ -223,7 +212,14 @@ impl JITEngineInner {
|
||||
module: &Module,
|
||||
functions: &PrimaryMap<LocalFunctionIndex, FunctionBody>,
|
||||
trampolines: &PrimaryMap<SignatureIndex, FunctionBody>,
|
||||
) -> Result<PrimaryMap<LocalFunctionIndex, *mut [VMFunctionBody]>, CompileError> {
|
||||
reverse_trampolines: &PrimaryMap<FunctionIndex, FunctionBody>,
|
||||
) -> Result<
|
||||
(
|
||||
PrimaryMap<LocalFunctionIndex, *mut [VMFunctionBody]>,
|
||||
PrimaryMap<FunctionIndex, *const VMFunctionBody>,
|
||||
),
|
||||
CompileError,
|
||||
> {
|
||||
// Allocate all of the compiled functions into executable memory,
|
||||
// copying over their contents.
|
||||
let allocated_functions =
|
||||
@@ -258,18 +254,10 @@ impl JITEngineInner {
|
||||
unsafe { std::mem::transmute::<*const VMFunctionBody, VMTrampoline>(ptr) };
|
||||
self.trampolines.insert(index, trampoline);
|
||||
}
|
||||
Ok(allocated_functions)
|
||||
}
|
||||
|
||||
/// Retrieves the reverse trampoline
|
||||
fn reverse_trampoline(
|
||||
&mut self,
|
||||
func_type: &FunctionType,
|
||||
address: usize,
|
||||
) -> Result<*const VMFunctionBody, CompileError> {
|
||||
let compiled_function = self
|
||||
.compiler()?
|
||||
.compile_wasm2host_trampoline(&func_type, address)?;
|
||||
let allocated_reverse_trampolines = reverse_trampolines
|
||||
.iter()
|
||||
.map(|(func_index, compiled_function)| {
|
||||
let ptr = self
|
||||
.code_memory
|
||||
.allocate_for_function(&compiled_function)
|
||||
@@ -280,8 +268,11 @@ impl JITEngineInner {
|
||||
))
|
||||
})?
|
||||
.as_ptr();
|
||||
self.code_memory.publish();
|
||||
Ok(ptr)
|
||||
})
|
||||
.collect::<Result<PrimaryMap<FunctionIndex, _>, CompileError>>()?;
|
||||
|
||||
Ok((allocated_functions, allocated_reverse_trampolines))
|
||||
}
|
||||
|
||||
/// Make memory containing compiled code executable.
|
||||
|
||||
@@ -8,8 +8,8 @@ use std::any::Any;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use wasm_common::entity::{BoxedSlice, PrimaryMap};
|
||||
use wasm_common::{
|
||||
DataInitializer, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, SignatureIndex,
|
||||
TableIndex,
|
||||
DataInitializer, FunctionIndex, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer,
|
||||
SignatureIndex, TableIndex,
|
||||
};
|
||||
use wasmer_compiler::CompileError;
|
||||
#[cfg(feature = "compiler")]
|
||||
@@ -30,6 +30,7 @@ pub struct CompiledModule {
|
||||
serializable: SerializableModule,
|
||||
|
||||
finished_functions: BoxedSlice<LocalFunctionIndex, *mut [VMFunctionBody]>,
|
||||
finished_reverse_trampolines: BoxedSlice<FunctionIndex, *const VMFunctionBody>,
|
||||
signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
|
||||
frame_info_registration: Mutex<Option<Option<GlobalFrameInfoRegistration>>>,
|
||||
}
|
||||
@@ -82,6 +83,8 @@ impl CompiledModule {
|
||||
.into_iter()
|
||||
.collect::<PrimaryMap<SignatureIndex, _>>();
|
||||
|
||||
let reverse_trampolines = compiler.compile_wasm2host_trampolines(&translation.module)?;
|
||||
|
||||
let data_initializers = translation
|
||||
.data_initializers
|
||||
.iter()
|
||||
@@ -101,6 +104,7 @@ impl CompiledModule {
|
||||
function_jt_offsets: compilation.get_jt_offsets(),
|
||||
function_frame_info: frame_infos,
|
||||
trampolines,
|
||||
reverse_trampolines,
|
||||
custom_sections: compilation.get_custom_sections(),
|
||||
};
|
||||
let serializable = SerializableModule {
|
||||
@@ -148,10 +152,11 @@ impl CompiledModule {
|
||||
jit_compiler: &mut JITEngineInner,
|
||||
serializable: SerializableModule,
|
||||
) -> Result<Self, CompileError> {
|
||||
let finished_functions = jit_compiler.allocate(
|
||||
let (finished_functions, finished_reverse_trampolines) = jit_compiler.allocate(
|
||||
&serializable.module,
|
||||
&serializable.compilation.function_bodies,
|
||||
&serializable.compilation.trampolines,
|
||||
&serializable.compilation.reverse_trampolines,
|
||||
)?;
|
||||
|
||||
link_module(
|
||||
@@ -179,6 +184,7 @@ impl CompiledModule {
|
||||
Ok(Self {
|
||||
serializable,
|
||||
finished_functions: finished_functions.into_boxed_slice(),
|
||||
finished_reverse_trampolines: finished_reverse_trampolines.into_boxed_slice(),
|
||||
signatures: signatures.into_boxed_slice(),
|
||||
frame_info_registration: Mutex::new(None),
|
||||
})
|
||||
@@ -210,6 +216,7 @@ impl CompiledModule {
|
||||
&self.module(),
|
||||
&sig_registry,
|
||||
resolver,
|
||||
&self.finished_reverse_trampolines,
|
||||
self.memory_plans(),
|
||||
self.table_plans(),
|
||||
)
|
||||
|
||||
@@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use wasm_common::entity::PrimaryMap;
|
||||
use wasm_common::{
|
||||
Features, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, SignatureIndex, TableIndex,
|
||||
Features, FunctionIndex, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, SignatureIndex,
|
||||
TableIndex,
|
||||
};
|
||||
use wasmer_compiler::{FunctionBody, JumpTableOffsets, Relocation, SectionBody, SectionIndex};
|
||||
use wasmer_engine::SerializableFunctionFrameInfo;
|
||||
@@ -20,6 +21,7 @@ pub struct SerializableCompilation {
|
||||
// format upon serialization.
|
||||
pub function_frame_info: PrimaryMap<LocalFunctionIndex, SerializableFunctionFrameInfo>,
|
||||
pub trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
|
||||
pub reverse_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
|
||||
pub custom_sections: PrimaryMap<SectionIndex, SectionBody>,
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,6 @@ pub trait Engine {
|
||||
/// Retrieves a trampoline given a signature
|
||||
fn trampoline(&self, sig: VMSharedSignatureIndex) -> Option<VMTrampoline>;
|
||||
|
||||
/// Retrieves the reverse trampoline
|
||||
fn reverse_trampoline(&self, func_type: &FunctionType, address: usize)
|
||||
-> *const VMFunctionBody;
|
||||
|
||||
/// Validates a WebAssembly module
|
||||
fn validate(&self, binary: &[u8]) -> Result<(), CompileError>;
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
use crate::error::{ImportError, LinkError};
|
||||
use more_asserts::assert_ge;
|
||||
use wasm_common::entity::PrimaryMap;
|
||||
use wasm_common::{ExternType, ImportIndex, MemoryIndex, TableIndex};
|
||||
use wasm_common::entity::{BoxedSlice, EntityRef, PrimaryMap};
|
||||
use wasm_common::{ExternType, FunctionIndex, ImportIndex, MemoryIndex, TableIndex};
|
||||
use wasmer_runtime::{
|
||||
Export, Imports, SignatureRegistry, VMFunctionImport, VMGlobalImport, VMMemoryImport,
|
||||
VMTableImport,
|
||||
Export, Imports, SignatureRegistry, VMFunctionBody, VMFunctionImport, VMGlobalImport,
|
||||
VMMemoryImport, VMTableImport,
|
||||
};
|
||||
|
||||
use wasmer_runtime::{MemoryPlan, TablePlan};
|
||||
@@ -91,6 +91,7 @@ pub fn resolve_imports(
|
||||
module: &Module,
|
||||
signatures: &SignatureRegistry,
|
||||
resolver: &dyn Resolver,
|
||||
finished_reverse_trampolines: &BoxedSlice<FunctionIndex, *const VMFunctionBody>,
|
||||
memory_plans: &PrimaryMap<MemoryIndex, MemoryPlan>,
|
||||
_table_plans: &PrimaryMap<TableIndex, TablePlan>,
|
||||
) -> Result<Imports, LinkError> {
|
||||
@@ -122,8 +123,17 @@ pub fn resolve_imports(
|
||||
}
|
||||
match resolved {
|
||||
Export::Function(ref f) => {
|
||||
let address = if f.dynamic_address.is_null() {
|
||||
f.address
|
||||
} else {
|
||||
// If this is a dynamic imported function,
|
||||
// the address of the funciton is the address of the
|
||||
// reverse trampoline.
|
||||
let index = FunctionIndex::new(function_imports.len());
|
||||
finished_reverse_trampolines[index]
|
||||
};
|
||||
function_imports.push(VMFunctionImport {
|
||||
body: f.address,
|
||||
body: address,
|
||||
dynamic_body: f.dynamic_address,
|
||||
vmctx: f.vmctx,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user