@@ -146,6 +146,30 @@ public ref byte GetResultStorageOrNull()
146146 }
147147 }
148148
149+ [ StructLayout ( LayoutKind . Explicit ) ]
150+ internal unsafe ref struct AsyncDispatcherInfo
151+ {
152+ // Dispatcher info for next dispatcher present on stack, or
153+ // null if none.
154+ [ FieldOffset ( 0 ) ]
155+ public AsyncDispatcherInfo * Next ;
156+
157+ // Next continuation the dispatcher will process.
158+ #if TARGET_64BIT
159+ [ FieldOffset ( 8 ) ]
160+ #else
161+ [ FieldOffset ( 4 ) ]
162+ #endif
163+ public Continuation ? NextContinuation ;
164+
165+ // Information about current task dispatching, to be used for async
166+ // stackwalking.
167+ [ ThreadStatic ]
168+ internal static unsafe AsyncDispatcherInfo * t_current ; // Debugger depends on the exact name of this field.
169+ }
170+
171+
172+
149173 public static partial class AsyncHelpers
150174 {
151175#if FEATURE_INTERPRETER
@@ -417,19 +441,19 @@ private unsafe void DispatchContinuations()
417441 ExecutionAndSyncBlockStore contexts = default ;
418442 contexts . Push ( ) ;
419443
420- DispatcherInfo dispatcherInfo ;
421- dispatcherInfo . Next = t_dispatcherInfo ;
422- dispatcherInfo . NextContinuation = MoveContinuationState ( ) ;
423- t_dispatcherInfo = & dispatcherInfo ;
444+ AsyncDispatcherInfo asyncDispatcherInfo ;
445+ asyncDispatcherInfo . Next = AsyncDispatcherInfo . t_current ;
446+ asyncDispatcherInfo . NextContinuation = MoveContinuationState ( ) ;
447+ AsyncDispatcherInfo . t_current = & asyncDispatcherInfo ;
424448
425449 while ( true )
426450 {
427- Debug . Assert ( dispatcherInfo . NextContinuation != null ) ;
451+ Debug . Assert ( asyncDispatcherInfo . NextContinuation != null ) ;
428452 try
429453 {
430- Continuation curContinuation = dispatcherInfo . NextContinuation ;
454+ Continuation curContinuation = asyncDispatcherInfo . NextContinuation ;
431455 Continuation ? nextContinuation = curContinuation . Next ;
432- dispatcherInfo . NextContinuation = nextContinuation ;
456+ asyncDispatcherInfo . NextContinuation = nextContinuation ;
433457
434458 ref byte resultLoc = ref nextContinuation != null ? ref nextContinuation . GetResultStorageOrNull ( ) : ref GetResultStorage ( ) ;
435459 Continuation ? newContinuation = curContinuation . ResumeInfo ->Resume ( curContinuation , ref resultLoc ) ;
@@ -439,13 +463,13 @@ private unsafe void DispatchContinuations()
439463 newContinuation . Next = nextContinuation ;
440464 HandleSuspended ( ) ;
441465 contexts . Pop ( ) ;
442- t_dispatcherInfo = dispatcherInfo . Next ;
466+ AsyncDispatcherInfo . t_current = asyncDispatcherInfo . Next ;
443467 return ;
444468 }
445469 }
446470 catch ( Exception ex )
447471 {
448- Continuation ? handlerContinuation = UnwindToPossibleHandler ( dispatcherInfo . NextContinuation ) ;
472+ Continuation ? handlerContinuation = UnwindToPossibleHandler ( asyncDispatcherInfo . NextContinuation ) ;
449473 if ( handlerContinuation == null )
450474 {
451475 // Tail of AsyncTaskMethodBuilderT.SetException
@@ -455,7 +479,7 @@ private unsafe void DispatchContinuations()
455479
456480 contexts . Pop ( ) ;
457481
458- t_dispatcherInfo = dispatcherInfo . Next ;
482+ AsyncDispatcherInfo . t_current = asyncDispatcherInfo . Next ;
459483
460484 if ( ! successfullySet )
461485 {
@@ -466,16 +490,16 @@ private unsafe void DispatchContinuations()
466490 }
467491
468492 handlerContinuation . SetException ( ex ) ;
469- dispatcherInfo . NextContinuation = handlerContinuation ;
493+ asyncDispatcherInfo . NextContinuation = handlerContinuation ;
470494 }
471495
472- if ( dispatcherInfo . NextContinuation == null )
496+ if ( asyncDispatcherInfo . NextContinuation == null )
473497 {
474498 bool successfullySet = TrySetResult ( m_result ) ;
475499
476500 contexts . Pop ( ) ;
477501
478- t_dispatcherInfo = dispatcherInfo . Next ;
502+ AsyncDispatcherInfo . t_current = asyncDispatcherInfo . Next ;
479503
480504 if ( ! successfullySet )
481505 {
@@ -485,10 +509,10 @@ private unsafe void DispatchContinuations()
485509 return ;
486510 }
487511
488- if ( QueueContinuationFollowUpActionIfNecessary ( dispatcherInfo . NextContinuation ) )
512+ if ( QueueContinuationFollowUpActionIfNecessary ( asyncDispatcherInfo . NextContinuation ) )
489513 {
490514 contexts . Pop ( ) ;
491- t_dispatcherInfo = dispatcherInfo . Next ;
515+ AsyncDispatcherInfo . t_current = asyncDispatcherInfo . Next ;
492516 return ;
493517 }
494518 }
@@ -583,28 +607,6 @@ private bool QueueContinuationFollowUpActionIfNecessary(Continuation continuatio
583607 } ;
584608 }
585609
586- [ StructLayout ( LayoutKind . Explicit ) ]
587- internal unsafe ref struct DispatcherInfo
588- {
589- // Dispatcher info for next dispatcher present on stack, or
590- // null if none.
591- [ FieldOffset ( 0 ) ]
592- public DispatcherInfo * Next ;
593-
594- // Next continuation the dispatcher will process.
595- #if TARGET_64BIT
596- [ FieldOffset ( 8 ) ]
597- #else
598- [ FieldOffset ( 4 ) ]
599- #endif
600- public Continuation ? NextContinuation ;
601- }
602-
603- // Information about current task dispatching, to be used for async
604- // stackwalking.
605- [ ThreadStatic ]
606- internal static unsafe DispatcherInfo * t_dispatcherInfo ;
607-
608610 // Change return type to RuntimeAsyncTask<T?> -- no benefit since this is used for Task returning thunks only
609611#pragma warning disable CA1859
610612 // When a Task-returning thunk gets a continuation result
0 commit comments