11use crate :: prelude:: * ;
22use crate :: store:: { Executor , StoreId , StoreInner , StoreOpaque } ;
33use crate :: vm:: mpk:: { self , ProtectionMask } ;
4- use crate :: vm:: { AsyncWasmCallState , VMStore } ;
4+ use crate :: vm:: { AlwaysMut , AsyncWasmCallState , VMStore } ;
55use crate :: { Engine , StoreContextMut } ;
66use anyhow:: { Result , anyhow} ;
77use core:: mem;
88use core:: ops:: Range ;
99use core:: pin:: Pin ;
1010use core:: ptr:: { self , NonNull } ;
1111use core:: task:: { Context , Poll } ;
12- use wasmtime_fiber:: { Fiber , Suspend } ;
12+ use wasmtime_fiber:: { Fiber , FiberStack , Suspend } ;
1313
1414type WasmtimeResume = Result < NonNull < Context < ' static > > > ;
1515type WasmtimeYield = StoreFiberYield ;
1616type WasmtimeComplete = Result < ( ) > ;
1717type WasmtimeSuspend = Suspend < WasmtimeResume , WasmtimeYield , WasmtimeComplete > ;
18+ type WasmtimeFiber < ' a > = Fiber < ' a , WasmtimeResume , WasmtimeYield , WasmtimeComplete > ;
1819
1920/// State related to asynchronous computations stored within a `Store<T>`.
2021///
@@ -434,9 +435,9 @@ pub(crate) struct StoreFiber<'a> {
434435 ///
435436 /// Note also that every `StoreFiber` is implicitly granted exclusive access
436437 /// to the store when it is resumed.
437- fiber : Option < Fiber < ' a , WasmtimeResume , WasmtimeYield , WasmtimeComplete > > ,
438+ fiber : Option < AlwaysMut < RawFiber < ' a > > > ,
438439 /// See `FiberResumeState`
439- state : Option < FiberResumeState > ,
440+ state : Option < AlwaysMut < FiberResumeState > > ,
440441 /// The Wasmtime `Engine` to which this fiber belongs.
441442 engine : Engine ,
442443 /// The id of the store with which this fiber was created.
@@ -446,9 +447,23 @@ pub(crate) struct StoreFiber<'a> {
446447 id : StoreId ,
447448}
448449
449- impl StoreFiber < ' _ > {
450+ struct RawFiber < ' a > ( WasmtimeFiber < ' a > ) ;
451+
452+ impl < ' a > StoreFiber < ' a > {
453+ /// Convenience method to peel off some layers of abstraction around the raw
454+ /// `wasmtime_fiber::Fiber`.
455+ fn fiber ( & mut self ) -> Option < & mut WasmtimeFiber < ' a > > {
456+ Some ( & mut self . fiber . as_mut ( ) ?. get_mut ( ) . 0 )
457+ }
458+
459+ /// Convenience method take the internal fiber and consume it, yielding its
460+ /// original stack.
461+ fn take_fiber_stack ( & mut self ) -> Option < FiberStack > {
462+ self . fiber . take ( ) . map ( |f| f. into_inner ( ) . 0 . into_stack ( ) )
463+ }
464+
450465 pub ( crate ) fn dispose ( & mut self , store : & mut StoreOpaque ) {
451- if let Some ( fiber) = & mut self . fiber {
466+ if let Some ( fiber) = self . fiber ( ) {
452467 if !fiber. done ( ) {
453468 let result = resume_fiber ( store, self , Err ( anyhow ! ( "future dropped" ) ) ) ;
454469 debug_assert ! ( result. is_ok( ) ) ;
@@ -469,16 +484,15 @@ impl Drop for StoreFiber<'_> {
469484 }
470485
471486 assert ! (
472- self . fiber. as_ref ( ) . unwrap( ) . done( ) ,
487+ self . fiber( ) . unwrap( ) . done( ) ,
473488 "attempted to drop in-progress fiber without first calling `StoreFiber::dispose`"
474489 ) ;
475490
476- self . state . take ( ) . unwrap ( ) . dispose ( ) ;
491+ self . state . take ( ) . unwrap ( ) . into_inner ( ) . dispose ( ) ;
477492
478493 unsafe {
479- self . engine
480- . allocator ( )
481- . deallocate_fiber_stack ( self . fiber . take ( ) . unwrap ( ) . into_stack ( ) ) ;
494+ let stack = self . take_fiber_stack ( ) . unwrap ( ) ;
495+ self . engine . allocator ( ) . deallocate_fiber_stack ( stack) ;
482496 }
483497 }
484498}
@@ -537,11 +551,7 @@ impl Drop for StoreFiber<'_> {
537551// declare the fiber as only containing Send data on its stack, despite not
538552// knowing for sure at compile time that this is correct. That's what `unsafe`
539553// in Rust is all about, though, right?
540- unsafe impl Send for StoreFiber < ' _ > { }
541- // See the docs about the `Send` impl above, which also apply to this `Sync`
542- // impl. `Sync` is needed since we store `StoreFiber`s and switch between them
543- // when executing components that export async-lifted functions.
544- unsafe impl Sync for StoreFiber < ' _ > { }
554+ unsafe impl Send for RawFiber < ' _ > { }
545555
546556/// State of the world when a fiber last suspended.
547557///
@@ -596,8 +606,7 @@ impl FiberResumeState {
596606 let tls = unsafe { self . tls . push ( ) } ;
597607 let mpk = swap_mpk_states ( self . mpk ) ;
598608 let async_guard_range = fiber
599- . fiber
600- . as_ref ( )
609+ . fiber ( )
601610 . unwrap ( )
602611 . stack ( )
603612 . guard_range ( )
@@ -723,25 +732,30 @@ fn resume_fiber<'a>(
723732
724733 impl Drop for Restore < ' _ , ' _ > {
725734 fn drop ( & mut self ) {
726- self . fiber . state = Some ( unsafe { self . state . take ( ) . unwrap ( ) . replace ( self . store ) } ) ;
735+ self . fiber . state =
736+ Some ( unsafe { self . state . take ( ) . unwrap ( ) . replace ( self . store ) . into ( ) } ) ;
727737 }
728738 }
729739 let result = unsafe {
730- let prev = fiber. state . take ( ) . unwrap ( ) . replace ( store, fiber) ;
740+ let prev = fiber
741+ . state
742+ . take ( )
743+ . unwrap ( )
744+ . into_inner ( )
745+ . replace ( store, fiber) ;
731746 let restore = Restore {
732747 store,
733748 fiber,
734749 state : Some ( prev) ,
735750 } ;
736- restore. fiber . fiber . as_ref ( ) . unwrap ( ) . resume ( result)
751+ restore. fiber . fiber ( ) . unwrap ( ) . resume ( result)
737752 } ;
738753
739754 match & result {
740755 // The fiber has finished, so recycle its stack by disposing of the
741756 // underlying fiber itself.
742757 Ok ( _) => {
743- let stack = fiber. fiber . take ( ) . map ( |f| f. into_stack ( ) ) ;
744- if let Some ( stack) = stack {
758+ if let Some ( stack) = fiber. take_fiber_stack ( ) {
745759 store. deallocate_fiber_stack ( stack) ;
746760 }
747761 }
@@ -761,7 +775,7 @@ fn resume_fiber<'a>(
761775 // pointer Wasmtime uses is not pointing anywhere within the
762776 // stack. If it is then that's a bug indicating that TLS management
763777 // in Wasmtime is incorrect.
764- if let Some ( range) = fiber. fiber . as_ref ( ) . unwrap ( ) . stack ( ) . range ( ) {
778+ if let Some ( range) = fiber. fiber ( ) . unwrap ( ) . stack ( ) . range ( ) {
765779 AsyncWasmCallState :: assert_current_state_not_in_range ( range) ;
766780 }
767781 }
@@ -826,19 +840,22 @@ pub(crate) fn make_fiber<'a>(
826840 fun ( reset. 0 )
827841 } ) ?;
828842 Ok ( StoreFiber {
829- state : Some ( FiberResumeState {
830- tls : crate :: runtime:: vm:: AsyncWasmCallState :: new ( ) ,
831- mpk : if track_pkey_context_switch {
832- Some ( ProtectionMask :: all ( ) )
833- } else {
834- None
835- } ,
836- stack_limit : usize:: MAX ,
837- executor,
838- } ) ,
843+ state : Some (
844+ FiberResumeState {
845+ tls : crate :: runtime:: vm:: AsyncWasmCallState :: new ( ) ,
846+ mpk : if track_pkey_context_switch {
847+ Some ( ProtectionMask :: all ( ) )
848+ } else {
849+ None
850+ } ,
851+ stack_limit : usize:: MAX ,
852+ executor,
853+ }
854+ . into ( ) ,
855+ ) ,
839856 engine,
840857 id,
841- fiber : Some ( fiber) ,
858+ fiber : Some ( RawFiber ( fiber) . into ( ) ) ,
842859 } )
843860}
844861
0 commit comments