@@ -439,17 +439,19 @@ mod call_thread_state {
439439 #[ cfg( all( has_native_signals, unix) ) ]
440440 pub ( crate ) async_guard_range : Range < * mut u8 > ,
441441
442- // The values of `VMStoreContext::last_wasm_{exit_{pc,fp},entry_sp}` for
442+ // The values of
443+ // `VMStoreContext::{stack_limit,last_wasm_{exit_{pc,fp},entry_sp}}` for
443444 // the *previous* `CallThreadState` for this same store/limits. Our
444445 // *current* last wasm PC/FP/SP are saved in `self.vm_store_context`. We
445446 // save a copy of the old registers here because the `VMStoreContext`
446447 // typically doesn't change across nested calls into Wasm (i.e. they are
447448 // typically calls back into the same store and `self.vm_store_context
448449 // == self.prev.vm_store_context`) and we must to maintain the list of
449450 // contiguous-Wasm-frames stack regions for backtracing purposes.
450- old_last_wasm_exit_fp : Cell < usize > ,
451- old_last_wasm_exit_pc : Cell < usize > ,
452- old_last_wasm_entry_fp : Cell < usize > ,
451+ pub ( super ) old_stack_limit : Cell < usize > ,
452+ pub ( super ) old_last_wasm_exit_fp : Cell < usize > ,
453+ pub ( super ) old_last_wasm_exit_pc : Cell < usize > ,
454+ pub ( super ) old_last_wasm_entry_fp : Cell < usize > ,
453455 }
454456
455457 impl Drop for CallThreadState {
@@ -460,6 +462,7 @@ mod call_thread_state {
460462
461463 unsafe {
462464 let cx = self . vm_store_context . as_ref ( ) ;
465+ * cx. stack_limit . get ( ) = self . old_stack_limit . get ( ) ;
463466 * cx. last_wasm_exit_fp . get ( ) = self . old_last_wasm_exit_fp . get ( ) ;
464467 * cx. last_wasm_exit_pc . get ( ) = self . old_last_wasm_exit_pc . get ( ) ;
465468 * cx. last_wasm_entry_fp . get ( ) = self . old_last_wasm_entry_fp . get ( ) ;
@@ -500,6 +503,7 @@ mod call_thread_state {
500503 #[ cfg( all( has_native_signals, unix) ) ]
501504 async_guard_range,
502505 prev : Cell :: new ( ptr:: null ( ) ) ,
506+ old_stack_limit : Cell :: new ( unsafe { * vm_store_context. as_ref ( ) . stack_limit . get ( ) } ) ,
503507 old_last_wasm_exit_fp : Cell :: new ( unsafe {
504508 * vm_store_context. as_ref ( ) . last_wasm_exit_fp . get ( )
505509 } ) ,
@@ -825,6 +829,21 @@ pub(crate) mod tls {
825829
826830 pub use raw:: initialize as tls_eager_initialize;
827831
832+ #[ cfg( feature = "async" ) ]
833+ impl CallThreadState {
834+ unsafe fn swap ( & self ) {
835+ unsafe fn swap ( a : & core:: cell:: UnsafeCell < usize > , b : & core:: cell:: Cell < usize > ) {
836+ * a. get ( ) = b. replace ( * a. get ( ) ) ;
837+ }
838+
839+ let cx = self . vm_store_context . as_ref ( ) ;
840+ swap ( & cx. stack_limit , & self . old_stack_limit ) ;
841+ swap ( & cx. last_wasm_exit_fp , & self . old_last_wasm_exit_fp ) ;
842+ swap ( & cx. last_wasm_exit_pc , & self . old_last_wasm_exit_pc ) ;
843+ swap ( & cx. last_wasm_entry_fp , & self . old_last_wasm_entry_fp ) ;
844+ }
845+ }
846+
828847 /// Opaque state used to persist the state of the `CallThreadState`
829848 /// activations associated with a fiber stack that's used as part of an
830849 /// async wasm call.
@@ -873,6 +892,13 @@ pub(crate) mod tls {
873892 // list as stored in the state of this current thread.
874893 let ret = PreviousAsyncWasmCallState { state : raw:: get ( ) } ;
875894 let mut ptr = self . state ;
895+
896+ if let Some ( state) = ptr. as_ref ( ) {
897+ // Swap the current PC/FP/SP/etc. with those in the oldest
898+ // activation so we can restore them later in
899+ // `PreviousAsyncWasmCallState::restore`
900+ state. swap ( ) ;
901+ }
876902 while let Some ( state) = ptr. as_ref ( ) {
877903 ptr = state. prev . replace ( core:: ptr:: null_mut ( ) ) ;
878904 state. push ( ) ;
@@ -932,14 +958,22 @@ pub(crate) mod tls {
932958 // this loop is finished.
933959 let ptr = raw:: get ( ) ;
934960 if ptr == thread_head {
961+ if let Some ( state) = ret. state . as_ref ( ) {
962+ // Swap the current PC/FP/SP/etc. with those in the
963+ // oldest activation, which reverses what we did in
964+ // `AsyncWasmCallState::push`.
965+ state. swap ( ) ;
966+ }
967+
935968 break ret;
936969 }
937970
938971 // Pop this activation from the current thread's TLS state, and
939972 // then afterwards push it onto our own linked list within this
940- // `AsyncWasmCallState`. Note that the linked list in `AsyncWasmCallState` is stored
941- // in reverse order so a subsequent `push` later on pushes
942- // everything in the right order.
973+ // `AsyncWasmCallState`. Note that the linked list in
974+ // `AsyncWasmCallState` is stored in reverse order so a
975+ // subsequent `push` later on pushes everything in the right
976+ // order.
943977 ( * ptr) . pop ( ) ;
944978 if let Some ( state) = ret. state . as_ref ( ) {
945979 ( * ptr) . prev . set ( state) ;
0 commit comments