@@ -89,8 +89,6 @@ use crate::prelude::*;
8989use crate :: runtime:: vm:: GcRootsList ;
9090#[ cfg( feature = "stack-switching" ) ]
9191use crate :: runtime:: vm:: VMContRef ;
92- #[ cfg( feature = "gc" ) ]
93- use crate :: runtime:: vm:: VMExnRef ;
9492use crate :: runtime:: vm:: mpk:: ProtectionKey ;
9593use crate :: runtime:: vm:: {
9694 self , GcStore , Imports , InstanceAllocationRequest , InstanceAllocator , InstanceHandle ,
@@ -124,6 +122,8 @@ pub(crate) use token::StoreToken;
124122mod async_;
125123#[ cfg( all( feature = "async" , feature = "call-hook" ) ) ]
126124pub use self :: async_:: CallHookHandler ;
125+
126+ use super :: vm:: VMExnRef ;
127127#[ cfg( feature = "gc" ) ]
128128mod gc;
129129
@@ -357,6 +357,12 @@ pub struct StoreOpaque {
357357 // Types for which the embedder has created an allocator for.
358358 #[ cfg( feature = "gc" ) ]
359359 gc_host_alloc_types : crate :: hash_set:: HashSet < crate :: type_registry:: RegisteredType > ,
360+ /// Pending exception, if any. This is also a GC root, because it
361+ /// needs to be rooted somewhere between the time that a pending
362+ /// exception is set and the time that the Wasm-to-host entry
363+ /// trampoline starts the unwind (right before it would return).
364+ #[ cfg( feature = "gc" ) ]
365+ pending_exception : Option < VMGcRef > ,
360366
361367 // Numbers of resources instantiated in this store, and their limits
362368 instance_count : usize ,
@@ -575,6 +581,8 @@ impl<T> Store<T> {
575581 gc_roots_list : GcRootsList :: default ( ) ,
576582 #[ cfg( feature = "gc" ) ]
577583 gc_host_alloc_types : Default :: default ( ) ,
584+ #[ cfg( feature = "gc" ) ]
585+ pending_exception : None ,
578586 modules : ModuleRegistry :: default ( ) ,
579587 func_refs : FuncRefs :: default ( ) ,
580588 host_globals : PrimaryMap :: new ( ) ,
@@ -1659,6 +1667,7 @@ impl StoreOpaque {
16591667 self . trace_wasm_continuation_roots ( gc_roots_list) ;
16601668 self . trace_vmctx_roots ( gc_roots_list) ;
16611669 self . trace_user_roots ( gc_roots_list) ;
1670+ self . trace_pending_exception_roots ( gc_roots_list) ;
16621671
16631672 log:: trace!( "End trace GC roots" )
16641673 }
@@ -1780,6 +1789,17 @@ impl StoreOpaque {
17801789 log:: trace!( "End trace GC roots :: user" ) ;
17811790 }
17821791
1792+ #[ cfg( feature = "gc" ) ]
1793+ fn trace_pending_exception_roots ( & mut self , gc_roots_list : & mut GcRootsList ) {
1794+ log:: trace!( "Begin trace GC roots :: pending exception" ) ;
1795+ if let Some ( pending_exception) = self . pending_exception . as_mut ( ) {
1796+ unsafe {
1797+ gc_roots_list. add_root ( pending_exception. into ( ) , "Pending exception" ) ;
1798+ }
1799+ }
1800+ log:: trace!( "End trace GC roots :: pending exception" ) ;
1801+ }
1802+
17831803 /// Insert a host-allocated GC type into this store.
17841804 ///
17851805 /// This makes it suitable for the embedder to allocate instances of this
@@ -2144,18 +2164,6 @@ at https://bytecodealliance.org/security.
21442164 Ok ( ptr)
21452165 }
21462166
2147- /// Throws an exception.
2148- ///
2149- /// # Safety
2150- ///
2151- /// Must be invoked when Wasm code is on the stack.
2152- #[ cfg( feature = "gc" ) ]
2153- pub ( crate ) unsafe fn throw_ref ( & mut self , exnref : VMExnRef ) -> ! {
2154- let mut nogc = AutoAssertNoGc :: new ( self ) ;
2155- // SAFETY: this is invoked when Wasm is on the stack.
2156- unsafe { vm:: throw ( & mut nogc, exnref) }
2157- }
2158-
21592167 /// Constructs and executes an `InstanceAllocationRequest` and pushes the
21602168 /// returned instance into the store.
21612169 ///
@@ -2231,6 +2239,24 @@ at https://bytecodealliance.org/security.
22312239
22322240 Ok ( id)
22332241 }
2242+
2243+ /// Set a pending exception. The `exnref` is taken and held on
2244+ /// this store to be fetched later by an unwind. This method does
2245+ /// *not* set up an unwind request on the TLS call state; that
2246+ /// must be done separately.
2247+ #[ cfg( feature = "gc" ) ]
2248+ pub ( crate ) fn set_pending_exception ( & mut self , exnref : VMExnRef ) {
2249+ self . pending_exception = Some ( exnref. into ( ) ) ;
2250+ }
2251+
2252+ /// Take a pending exception.
2253+ #[ cfg( feature = "gc" ) ]
2254+ pub ( crate ) fn take_pending_exception ( & mut self ) -> VMExnRef {
2255+ self . pending_exception
2256+ . take ( )
2257+ . expect ( "No pending exception set" )
2258+ . into_exnref_unchecked ( )
2259+ }
22342260}
22352261
22362262/// Helper parameter to [`StoreOpaque::allocate_instance`].
0 commit comments