@@ -122,6 +122,9 @@ pub(crate) use token::StoreToken;
122122mod async_;
123123#[ cfg( all( feature = "async" , feature = "call-hook" ) ) ]
124124pub use self :: async_:: CallHookHandler ;
125+
126+ use super :: ExnRef ;
127+ use super :: vm:: VMExnRef ;
125128#[ cfg( feature = "gc" ) ]
126129mod 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`].
0 commit comments