mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-24 14:11:32 +00:00
Swap code lazily when tiering up from singlepass to LLVM.
Does not handle long-running functions, but should work at least.
This commit is contained in:
@ -151,6 +151,10 @@ pub trait RunnableModule: Send + Sync {
|
||||
None
|
||||
}
|
||||
|
||||
unsafe fn patch_local_function(&self, _idx: usize, _target_address: usize) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// A wasm trampoline contains the necessary data to dynamically call an exported wasm function.
|
||||
/// Given a particular signature index, we are returned a trampoline that is matched with that
|
||||
/// signature and an invoke function that can call the trampoline.
|
||||
@ -167,6 +171,11 @@ pub trait RunnableModule: Send + Sync {
|
||||
fn get_offsets(&self) -> Option<Vec<usize>> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns the beginning offsets of all local functions.
|
||||
fn get_local_function_offsets(&self) -> Option<Vec<usize>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CacheGen: Send + Sync {
|
||||
|
@ -17,7 +17,7 @@ use nix::sys::signal::{
|
||||
SIGSEGV, SIGTRAP,
|
||||
};
|
||||
use std::any::Any;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::ffi::c_void;
|
||||
use std::process;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@ -41,6 +41,7 @@ struct UnwindInfo {
|
||||
thread_local! {
|
||||
static UNWIND: UnsafeCell<Option<UnwindInfo>> = UnsafeCell::new(None);
|
||||
static CURRENT_CTX: UnsafeCell<*mut vm::Ctx> = UnsafeCell::new(::std::ptr::null_mut());
|
||||
static WAS_SIGINT_TRIGGERED: Cell<bool> = Cell::new(false);
|
||||
}
|
||||
|
||||
struct InterruptSignalMem(*mut u8);
|
||||
@ -69,6 +70,10 @@ lazy_static! {
|
||||
}
|
||||
static INTERRUPT_SIGNAL_DELIVERED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub fn was_sigint_triggered_fault() -> bool {
|
||||
WAS_SIGINT_TRIGGERED.with(|x| x.get())
|
||||
}
|
||||
|
||||
pub unsafe fn with_ctx<R, F: FnOnce() -> R>(ctx: *mut vm::Ctx, cb: F) -> R {
|
||||
let addr = CURRENT_CTX.with(|x| x.get());
|
||||
let old = *addr;
|
||||
@ -82,6 +87,17 @@ pub unsafe fn get_wasm_interrupt_signal_mem() -> *mut u8 {
|
||||
INTERRUPT_SIGNAL_MEM.0
|
||||
}
|
||||
|
||||
pub unsafe fn set_wasm_interrupt_on_ctx(ctx: *mut vm::Ctx) {
|
||||
if mprotect(
|
||||
(&*ctx).internal.interrupt_signal_mem as _,
|
||||
INTERRUPT_SIGNAL_MEM_SIZE,
|
||||
PROT_NONE,
|
||||
) < 0
|
||||
{
|
||||
panic!("cannot set PROT_NONE on signal mem");
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn set_wasm_interrupt() {
|
||||
let mem: *mut u8 = INTERRUPT_SIGNAL_MEM.0;
|
||||
if mprotect(mem as _, INTERRUPT_SIGNAL_MEM_SIZE, PROT_NONE) < 0 {
|
||||
@ -188,7 +204,7 @@ extern "C" fn signal_trap_handler(
|
||||
let should_unwind = allocate_and_run(TRAP_STACK_SIZE, || {
|
||||
let mut is_suspend_signal = false;
|
||||
|
||||
println!("SIGNAL: {:?} {:?}", Signal::from_c_int(signum), fault.faulting_addr);
|
||||
WAS_SIGINT_TRIGGERED.with(|x| x.set(false));
|
||||
|
||||
match Signal::from_c_int(signum) {
|
||||
Ok(SIGTRAP) => {
|
||||
@ -215,7 +231,9 @@ extern "C" fn signal_trap_handler(
|
||||
if fault.faulting_addr as usize == get_wasm_interrupt_signal_mem() as usize {
|
||||
is_suspend_signal = true;
|
||||
clear_wasm_interrupt();
|
||||
INTERRUPT_SIGNAL_DELIVERED.store(false, Ordering::SeqCst);
|
||||
if INTERRUPT_SIGNAL_DELIVERED.swap(false, Ordering::SeqCst) {
|
||||
WAS_SIGINT_TRIGGERED.with(|x| x.set(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -102,13 +102,20 @@ pub struct CodeMemory {
|
||||
size: usize,
|
||||
}
|
||||
|
||||
unsafe impl Send for CodeMemory {}
|
||||
unsafe impl Sync for CodeMemory {}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
impl CodeMemory {
|
||||
pub fn new(_size: usize) -> CodeMemory {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub fn make_executable(&mut self) {
|
||||
pub fn make_executable(&self) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub fn make_writable(&self) {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
@ -139,11 +146,17 @@ impl CodeMemory {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_executable(&mut self) {
|
||||
pub fn make_executable(&self) {
|
||||
if unsafe { mprotect(self.ptr as _, self.size, PROT_READ | PROT_EXEC) } != 0 {
|
||||
panic!("cannot set code memory to executable");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_writable(&self) {
|
||||
if unsafe { mprotect(self.ptr as _, self.size, PROT_READ | PROT_WRITE) } != 0 {
|
||||
panic!("cannot set code memory to writable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
|
@ -493,21 +493,21 @@ pub mod x64 {
|
||||
stack[stack_offset] |= v;
|
||||
}
|
||||
},
|
||||
MachineValue::WasmLocal(x) => {
|
||||
match fsm.locals[x] {
|
||||
WasmAbstractValue::Const(x) => {
|
||||
assert!(x <= ::std::u32::MAX as u64);
|
||||
stack[stack_offset] |= x;
|
||||
}
|
||||
WasmAbstractValue::Runtime => {
|
||||
let v = f.locals[x].unwrap();
|
||||
assert!(v <= ::std::u32::MAX as u64);
|
||||
stack[stack_offset] |= v;
|
||||
}
|
||||
MachineValue::WasmLocal(x) => match fsm.locals[x] {
|
||||
WasmAbstractValue::Const(x) => {
|
||||
assert!(x <= ::std::u32::MAX as u64);
|
||||
stack[stack_offset] |= x;
|
||||
}
|
||||
}
|
||||
WasmAbstractValue::Runtime => {
|
||||
let v = f.locals[x].unwrap();
|
||||
assert!(v <= ::std::u32::MAX as u64);
|
||||
stack[stack_offset] |= v;
|
||||
}
|
||||
},
|
||||
MachineValue::VmctxDeref(ref seq) => {
|
||||
stack[stack_offset] |= compute_vmctx_deref(vmctx as *const Ctx, seq) & (::std::u32::MAX as u64);
|
||||
stack[stack_offset] |=
|
||||
compute_vmctx_deref(vmctx as *const Ctx, seq)
|
||||
& (::std::u32::MAX as u64);
|
||||
}
|
||||
MachineValue::Undefined => {}
|
||||
_ => unimplemented!("TwoHalves.0"),
|
||||
@ -524,21 +524,22 @@ pub mod x64 {
|
||||
stack[stack_offset] |= v << 32;
|
||||
}
|
||||
},
|
||||
MachineValue::WasmLocal(x) => {
|
||||
match fsm.locals[x] {
|
||||
WasmAbstractValue::Const(x) => {
|
||||
assert!(x <= ::std::u32::MAX as u64);
|
||||
stack[stack_offset] |= x << 32;
|
||||
}
|
||||
WasmAbstractValue::Runtime => {
|
||||
let v = f.locals[x].unwrap();
|
||||
assert!(v <= ::std::u32::MAX as u64);
|
||||
stack[stack_offset] |= v << 32;
|
||||
}
|
||||
MachineValue::WasmLocal(x) => match fsm.locals[x] {
|
||||
WasmAbstractValue::Const(x) => {
|
||||
assert!(x <= ::std::u32::MAX as u64);
|
||||
stack[stack_offset] |= x << 32;
|
||||
}
|
||||
}
|
||||
WasmAbstractValue::Runtime => {
|
||||
let v = f.locals[x].unwrap();
|
||||
assert!(v <= ::std::u32::MAX as u64);
|
||||
stack[stack_offset] |= v << 32;
|
||||
}
|
||||
},
|
||||
MachineValue::VmctxDeref(ref seq) => {
|
||||
stack[stack_offset] |= (compute_vmctx_deref(vmctx as *const Ctx, seq) & (::std::u32::MAX as u64)) << 32;
|
||||
stack[stack_offset] |=
|
||||
(compute_vmctx_deref(vmctx as *const Ctx, seq)
|
||||
& (::std::u32::MAX as u64))
|
||||
<< 32;
|
||||
}
|
||||
MachineValue::Undefined => {}
|
||||
_ => unimplemented!("TwoHalves.1"),
|
||||
@ -583,7 +584,6 @@ pub mod x64 {
|
||||
|
||||
stack_offset -= 1;
|
||||
stack[stack_offset] = (code_base + activate_offset) as u64; // return address
|
||||
println!("activating at {:?}", (code_base + activate_offset) as *const u8);
|
||||
}
|
||||
|
||||
stack_offset -= 1;
|
||||
@ -694,7 +694,6 @@ pub mod x64 {
|
||||
|
||||
catch_unsafe_unwind(
|
||||
|| {
|
||||
::std::intrinsics::breakpoint();
|
||||
run_on_alternative_stack(
|
||||
stack.as_mut_ptr().offset(stack.len() as isize),
|
||||
stack.as_mut_ptr().offset(stack_offset as isize),
|
||||
|
Reference in New Issue
Block a user