Remove global state for trap registration (#909)
* Remove global state for trap registration There's a number of changes brought about in this commit, motivated by a few things. One motivation was to remove an instance of using `lazy_static!` in an effort to remove global state and encapsulate it wherever possible. A second motivation came when investigating a slowly-compiling wasm module (a bit too slowly) where a good chunk of time was spent in managing trap registrations. The specific change made here is that `TrapRegistry` is now stored inside of a `Compiler` instead of inside a global. Additionally traps are "bulk registered" for a module rather than one-by-one. This form of bulk-registration allows optimizing the locks used here, where a lock is only held for a module at-a-time instead of once-per-function. With these changes the "unregister" logic has also been tweaked a bit here and there to continue to work. As a nice side effect the `Compiler` type now has one fewer field that requires actual mutability and has been updated for multi-threaded compilation, nudging us closer to a world where we can support multi-threaded compilation. Yay! In terms of performance improvements, a local wasm test file that previously took 3 seconds to compile is now 10% faster to compile, taking ~2.7 seconds now. * Perform trap resolution after unwinding This avoids taking locks in signal handlers which feels a bit iffy... * Remove `TrapRegistration::dummy()` Avoid an case where you're trying to lookup trap information from a dummy module for something that happened in a different module. * Tweak some comments
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
//! signalhandling mechanisms.
|
||||
|
||||
use crate::instance::{InstanceHandle, SignalHandler};
|
||||
use crate::trap_registry::get_trap_registry;
|
||||
use crate::trap_registry::TrapDescription;
|
||||
use crate::vmcontext::{VMContext, VMFunctionBody};
|
||||
use backtrace::Backtrace;
|
||||
@@ -78,8 +77,7 @@ cfg_if::cfg_if! {
|
||||
/// Only safe to call when wasm code is on the stack, aka `wasmtime_call` or
|
||||
/// `wasmtime_call_trampoline` must have been previously called.
|
||||
pub unsafe fn raise_user_trap(data: Box<dyn Error + Send + Sync>) -> ! {
|
||||
let trap = Trap::User(data);
|
||||
tls::with(|info| info.unwrap().unwind_with(UnwindReason::Trap(trap)))
|
||||
tls::with(|info| info.unwrap().unwind_with(UnwindReason::UserTrap(data)))
|
||||
}
|
||||
|
||||
/// Carries a Rust panic across wasm code and resumes the panic on the other
|
||||
@@ -187,7 +185,8 @@ pub struct CallThreadState {
|
||||
enum UnwindReason {
|
||||
None,
|
||||
Panic(Box<dyn Any + Send>),
|
||||
Trap(Trap),
|
||||
UserTrap(Box<dyn Error + Send + Sync>),
|
||||
Trap { backtrace: Backtrace, pc: usize },
|
||||
}
|
||||
|
||||
impl CallThreadState {
|
||||
@@ -210,9 +209,25 @@ impl CallThreadState {
|
||||
debug_assert_eq!(ret, 1);
|
||||
Ok(())
|
||||
}
|
||||
UnwindReason::Trap(trap) => {
|
||||
UnwindReason::UserTrap(data) => {
|
||||
debug_assert_eq!(ret, 0);
|
||||
Err(trap)
|
||||
Err(Trap::User(data))
|
||||
}
|
||||
UnwindReason::Trap { backtrace, pc } => {
|
||||
debug_assert_eq!(ret, 0);
|
||||
let instance = unsafe { InstanceHandle::from_vmctx(self.vmctx) };
|
||||
|
||||
Err(Trap::Wasm {
|
||||
desc: instance
|
||||
.instance()
|
||||
.trap_registration
|
||||
.get_trap(pc)
|
||||
.unwrap_or_else(|| TrapDescription {
|
||||
source_loc: ir::SourceLoc::default(),
|
||||
trap_code: ir::TrapCode::StackOverflow,
|
||||
}),
|
||||
backtrace,
|
||||
})
|
||||
}
|
||||
UnwindReason::Panic(panic) => {
|
||||
debug_assert_eq!(ret, 0);
|
||||
@@ -289,20 +304,12 @@ impl CallThreadState {
|
||||
if self.jmp_buf.get().is_null() {
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
let registry = get_trap_registry();
|
||||
let trap = Trap::Wasm {
|
||||
desc: registry
|
||||
.get_trap(pc as usize)
|
||||
.unwrap_or_else(|| TrapDescription {
|
||||
source_loc: ir::SourceLoc::default(),
|
||||
trap_code: ir::TrapCode::StackOverflow,
|
||||
}),
|
||||
backtrace: Backtrace::new_unresolved(),
|
||||
};
|
||||
|
||||
let backtrace = Backtrace::new_unresolved();
|
||||
self.reset_guard_page.set(reset_guard_page);
|
||||
self.unwind.replace(UnwindReason::Trap(trap));
|
||||
self.unwind.replace(UnwindReason::Trap {
|
||||
backtrace,
|
||||
pc: pc as usize,
|
||||
});
|
||||
self.jmp_buf.get()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user