Skip to content

Commit ea49772

Browse files
committed
WIP.
1 parent 88d0cb2 commit ea49772

File tree

7 files changed

+136
-111
lines changed

7 files changed

+136
-111
lines changed

crates/wasmtime/src/runtime/func.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,9 +2410,11 @@ impl HostContext {
24102410
//
24112411
// SAFETY: this is an entrypoint of wasm which requires correct type
24122412
// ascription of `T` itself, meaning that this should be safe to call.
2413-
crate::runtime::vm::catch_unwind_and_record_trap(move || unsafe {
2414-
Caller::with(caller_vmctx, run)
2415-
})
2413+
crate::runtime::vm::catch_unwind_and_record_trap(
2414+
caller_vmctx,
2415+
|caller| unsafe { Caller::with(caller_vmctx, run) },
2416+
|caller| unsafe { Caller::with(caller_vmctx, |caller| AutoAssertNoGc::new(caller)) },
2417+
)
24162418
}
24172419
}
24182420

crates/wasmtime/src/runtime/gc/enabled/exnref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ impl ExnRef {
557557
Ok(store.require_gc_store()?.header(gc_ref))
558558
}
559559

560-
fn exnref<'a>(&self, store: &'a AutoAssertNoGc<'_>) -> Result<&'a VMExnRef> {
560+
pub(crate) fn exnref<'a>(&self, store: &'a AutoAssertNoGc<'_>) -> Result<&'a VMExnRef> {
561561
assert!(self.comes_from_same_store(&store));
562562
let gc_ref = self.inner.try_gc_ref(store)?;
563563
debug_assert!(self.header(store)?.kind().matches(VMGcKind::ExnRef));

crates/wasmtime/src/runtime/store.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ pub(crate) use token::StoreToken;
122122
mod async_;
123123
#[cfg(all(feature = "async", feature = "call-hook"))]
124124
pub use self::async_::CallHookHandler;
125+
126+
use super::ExnRef;
127+
use super::vm::VMExnRef;
125128
#[cfg(feature = "gc")]
126129
mod gc;
127130

@@ -355,6 +358,12 @@ pub struct StoreOpaque {
355358
// Types for which the embedder has created an allocator for.
356359
#[cfg(feature = "gc")]
357360
gc_host_alloc_types: crate::hash_set::HashSet<crate::type_registry::RegisteredType>,
361+
/// Pending exception, if any. This is also a GC root, because it
362+
/// needs to be rooted somewhere between the time that a pending
363+
/// exception is set and the time that the Wasm-to-host entry
364+
/// trampoline starts the unwind (right before it would return).
365+
#[cfg(feature = "gc")]
366+
pending_exception: Option<VMGcRef>,
358367

359368
// Numbers of resources instantiated in this store, and their limits
360369
instance_count: usize,
@@ -573,6 +582,8 @@ impl<T> Store<T> {
573582
gc_roots_list: GcRootsList::default(),
574583
#[cfg(feature = "gc")]
575584
gc_host_alloc_types: Default::default(),
585+
#[cfg(feature = "gc")]
586+
pending_exception: None,
576587
modules: ModuleRegistry::default(),
577588
func_refs: FuncRefs::default(),
578589
host_globals: PrimaryMap::new(),
@@ -1657,6 +1668,7 @@ impl StoreOpaque {
16571668
self.trace_wasm_continuation_roots(gc_roots_list);
16581669
self.trace_vmctx_roots(gc_roots_list);
16591670
self.trace_user_roots(gc_roots_list);
1671+
self.trace_pending_exception_roots(gc_roots_list);
16601672

16611673
log::trace!("End trace GC roots")
16621674
}
@@ -1778,6 +1790,13 @@ impl StoreOpaque {
17781790
log::trace!("End trace GC roots :: user");
17791791
}
17801792

1793+
#[cfg(feature = "gc")]
1794+
fn trace_pending_exception_roots(&mut self, gc_roots_list: &mut GcRootsList) {
1795+
log::trace!("Begin trace GC roots :: pending exception");
1796+
gc_roots_list.add_root(self.pending_exception.as_mut().into(), "Pending exception");
1797+
log::trace!("End trace GC roots :: pending exception");
1798+
}
1799+
17811800
/// Insert a host-allocated GC type into this store.
17821801
///
17831802
/// This makes it suitable for the embedder to allocate instances of this
@@ -2217,6 +2236,24 @@ at https://bytecodealliance.org/security.
22172236

22182237
Ok(id)
22192238
}
2239+
2240+
/// Set a pending exception. The `exnref` is taken and held on
2241+
/// this store to be fetched later by an unwind. This method does
2242+
/// *not* set up an unwind request on the TLS call state; that
2243+
/// must be done separately.
2244+
#[cfg(feature = "gc")]
2245+
pub(crate) fn set_pending_exception(&mut self, exnref: VMExnRef) {
2246+
self.pending_exception = Some(exnref.into());
2247+
}
2248+
2249+
/// Take a pending exception.
2250+
#[cfg(feature = "gc")]
2251+
pub(crate) fn take_pending_exception(&mut self) -> VMExnRef {
2252+
self.pending_exception
2253+
.take()
2254+
.expect("No pending exception set")
2255+
.into_exnref_unchecked()
2256+
}
22202257
}
22212258

22222259
/// Helper parameter to [`StoreOpaque::allocate_instance`].

crates/wasmtime/src/runtime/store/async_.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ impl StoreOpaque {
230230
self.trace_vmctx_roots(gc_roots_list);
231231
Yield::new().await;
232232
self.trace_user_roots(gc_roots_list);
233+
Yield::new().await;
234+
self.trace_pending_exception_roots(gc_roots_list);
233235

234236
log::trace!("End trace GC roots")
235237
}

crates/wasmtime/src/runtime/vm/libcalls.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,15 +1571,17 @@ unsafe fn get_instance_id(_store: &mut dyn VMStore, instance: Pin<&mut Instance>
15711571

15721572
#[cfg(feature = "gc")]
15731573
unsafe fn throw_ref(
1574-
store: &mut dyn VMStore,
1574+
mut store: &mut dyn VMStore,
15751575
_instance: Pin<&mut Instance>,
15761576
exnref: u32,
1577-
) -> Result<()> {
1578-
use super::TrapOrException;
1577+
) -> Result<(), TrapReason> {
1578+
use crate::AsStoreOpaqueMut;
15791579

15801580
let exnref = VMGcRef::from_raw_u32(exnref).ok_or_else(|| Trap::NullReference)?;
1581+
let exnref = store.unwrap_gc_store_mut().clone_gc_ref(&exnref);
15811582
let exnref = exnref
15821583
.into_exnref(&*store.unwrap_gc_store().gc_heap)
15831584
.expect("gc ref should be an exception object");
1584-
Err(TrapOrException::Exception(exnref))
1585+
store.as_store_opaque_mut().set_pending_exception(exnref);
1586+
Err(TrapReason::Exception)
15851587
}

crates/wasmtime/src/runtime/vm/throw.rs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
//! Exception-throw logic for Wasm exceptions.
22
3-
use core::ptr::NonNull;
4-
53
use wasmtime_environ::TagIndex;
64
use wasmtime_unwinder::{Frame, ThrowAction};
75

8-
use super::{UnwindReason, UnwindState, VMContext, VMExnRef};
6+
use super::{VMContext, VMExnRef};
97
use crate::store::AutoAssertNoGc;
108

119
/// Implementation of exception throw.
@@ -14,7 +12,7 @@ use crate::store::AutoAssertNoGc;
1412
///
1513
/// Must be invoked when Wasm is in the stack and control has
1614
/// re-entered the runtime.
17-
pub unsafe fn compute_throw(nogc: &mut AutoAssertNoGc, exnref: VMExnRef) -> UnwindState {
15+
pub unsafe fn compute_throw(nogc: &mut AutoAssertNoGc, exnref: &VMExnRef) -> ThrowAction {
1816
// Get the tag identity relative to the store.
1917
let (throwing_tag_instance_id, throwing_tag_defined_tag_index) =
2018
exnref.tag(nogc).expect("cannot read tag");
@@ -110,20 +108,5 @@ pub unsafe fn compute_throw(nogc: &mut AutoAssertNoGc, exnref: VMExnRef) -> Unwi
110108
};
111109

112110
log::trace!("throw action: {action:?}");
113-
114-
match action {
115-
ThrowAction::Handler { pc, sp, fp } => UnwindState::UnwindIntoWasm {
116-
pc,
117-
sp,
118-
fp,
119-
payload1: usize::try_from(exnref.as_gc_ref().as_raw_u32())
120-
.expect("gcref does not fit in usize"),
121-
payload2: 0,
122-
},
123-
ThrowAction::None => UnwindState::UnwindPastWasm {
124-
reason: UnwindReason::Exception(exnref),
125-
backtrace: None,
126-
coredump_stack: None,
127-
},
128-
}
111+
action
129112
}

0 commit comments

Comments
 (0)