@@ -475,27 +475,30 @@ void MethodDesc::EmitAsyncMethodThunk(MethodDesc* pAsyncOtherVariant, MetaSig& m
475475 _ASSERTE (!pAsyncOtherVariant->IsVoid ());
476476
477477 // Implement IL that is effectively the following:
478- /*
479- {
480- Task task = other(arg);
481- if (!task.IsCompleted)
482- {
483- // Magic function which will suspend the current run of async methods
484- AsyncHelpers.TransparentAwaitTask(task);
485- }
486- return AsyncHelpers.CompletedTaskResult(task);
487- }
478+ // {
479+ // Task task = other(arg);
480+ // if (!task.IsCompleted)
481+ // {
482+ // // Magic function which will suspend the current run of async methods
483+ // AsyncHelpers.TransparentAwait(task);
484+ // }
485+ // return AsyncHelpers.CompletedTaskResult(task);
486+ // }
488487
489- For ValueTask:
490- {
491- ValueTask vt = other(arg);
492- if (vt.IsCompleted)
493- return vt.Result/vt.ThrowIfCompletedUnsuccessfully();
488+ // For ValueTask:
494489
495- Task task = vt.AsTask();
496- <same code as above>
497- }
498- */
490+ // {
491+ // ValueTask vt = other(arg);
492+ // if (!vt.IsCompleted)
493+ // {
494+ // taskOrNotifier = vt.AsTaskOrNotifier()
495+
496+ // // Magic function which will suspend the current run of async methods
497+ // AsyncHelpers.TransparentAwait(taskOrNotifier);
498+ // }
499+
500+ // return vt.Result/vt.ThrowIfCompletedUnsuccessfully();
501+ // }
499502 ILCodeStream* pCode = pSL->NewCodeStream (ILStubLinker::kDispatch );
500503
501504 int userFuncToken;
@@ -563,32 +566,27 @@ void MethodDesc::EmitAsyncMethodThunk(MethodDesc* pAsyncOtherVariant, MetaSig& m
563566 pCode->EmitLDARG (localArg++);
564567 }
565568
569+ // other(arg)
566570 pCode->EmitCALL (userFuncToken, localArg, 1 );
567571
568572 TypeHandle thLogicalRetType = msig.GetRetTypeHandleThrowing ();
569573 if (IsValueTaskAsyncThunk ())
570574 {
571- // Emit
572- // if (vtask.IsCompleted)
573- // return vtask.Result/vtask.ThrowIfCompletedUnsuccessfully()
574- // task = vtask.AsTask()
575- //
576-
577575 MethodTable* pMTValueTask;
578576 int isCompletedToken;
579577 int completionResultToken;
580- int asTaskToken ;
578+ int asTaskOrNotifierToken ;
581579 if (msig.IsReturnTypeVoid ())
582580 {
583581 pMTValueTask = CoreLibBinder::GetClass (CLASS__VALUETASK);
584582
585583 MethodDesc* pMDValueTaskIsCompleted = CoreLibBinder::GetMethod (METHOD__VALUETASK__GET_ISCOMPLETED);
586584 MethodDesc* pMDCompletionResult = CoreLibBinder::GetMethod (METHOD__VALUETASK__THROW_IF_COMPLETED_UNSUCCESSFULLY);
587- MethodDesc* pMDAsTask = CoreLibBinder::GetMethod (METHOD__VALUETASK__AS_TASK );
585+ MethodDesc* pMDAsTaskOrNotifier = CoreLibBinder::GetMethod (METHOD__VALUETASK__AS_TASK_OR_NOTIFIER );
588586
589587 isCompletedToken = pCode->GetToken (pMDValueTaskIsCompleted);
590588 completionResultToken = pCode->GetToken (pMDCompletionResult);
591- asTaskToken = pCode->GetToken (pMDAsTask );
589+ asTaskOrNotifierToken = pCode->GetToken (pMDAsTaskOrNotifier );
592590 }
593591 else
594592 {
@@ -597,73 +595,75 @@ void MethodDesc::EmitAsyncMethodThunk(MethodDesc* pAsyncOtherVariant, MetaSig& m
597595
598596 MethodDesc* pMDValueTaskIsCompleted = CoreLibBinder::GetMethod (METHOD__VALUETASK_1__GET_ISCOMPLETED);
599597 MethodDesc* pMDCompletionResult = CoreLibBinder::GetMethod (METHOD__VALUETASK_1__GET_RESULT);
600- MethodDesc* pMDAsTask = CoreLibBinder::GetMethod (METHOD__VALUETASK_1__AS_TASK );
598+ MethodDesc* pMDAsTaskOrNotifier = CoreLibBinder::GetMethod (METHOD__VALUETASK_1__AS_TASK_OR_NOTIFIER );
601599
602600 pMDValueTaskIsCompleted = FindOrCreateAssociatedMethodDesc (pMDValueTaskIsCompleted, pMTValueTask, FALSE , Instantiation (), FALSE );
603601 pMDCompletionResult = FindOrCreateAssociatedMethodDesc (pMDCompletionResult, pMTValueTask, FALSE , Instantiation (), FALSE );
604- pMDAsTask = FindOrCreateAssociatedMethodDesc (pMDAsTask , pMTValueTask, FALSE , Instantiation (), FALSE );
602+ pMDAsTaskOrNotifier = FindOrCreateAssociatedMethodDesc (pMDAsTaskOrNotifier , pMTValueTask, FALSE , Instantiation (), FALSE );
605603
606604 isCompletedToken = GetTokenForGenericTypeMethodCallWithAsyncReturnType (pCode, pMDValueTaskIsCompleted);
607605 completionResultToken = GetTokenForGenericTypeMethodCallWithAsyncReturnType (pCode, pMDCompletionResult);
608- asTaskToken = GetTokenForGenericTypeMethodCallWithAsyncReturnType (pCode, pMDAsTask );
606+ asTaskOrNotifierToken = GetTokenForGenericTypeMethodCallWithAsyncReturnType (pCode, pMDAsTaskOrNotifier );
609607 }
610608
611609 LocalDesc valueTaskLocalDesc (pMTValueTask);
612610 DWORD valueTaskLocal = pCode->NewLocal (valueTaskLocalDesc);
613- ILCodeLabel* valueTaskNotCompletedLabel = pCode->NewCodeLabel ();
611+ ILCodeLabel* valueTaskCompletedLabel = pCode->NewCodeLabel ();
614612
615613 // Store value task returned by call to actual user func
616614 pCode->EmitSTLOC (valueTaskLocal);
617-
618615 pCode->EmitLDLOCA (valueTaskLocal);
619616 pCode->EmitCALL (isCompletedToken, 1 , 1 );
620- pCode->EmitBRFALSE (valueTaskNotCompletedLabel );
617+ pCode->EmitBRTRUE (valueTaskCompletedLabel );
621618
622619 pCode->EmitLDLOCA (valueTaskLocal);
623- pCode->EmitCALL (completionResultToken , 1 , msig. IsReturnTypeVoid () ? 0 : 1 );
624- pCode->EmitRET ( );
620+ pCode->EmitCALL (asTaskOrNotifierToken , 1 , 1 );
621+ pCode->EmitCALL (METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT, 1 , 0 );
625622
626- pCode->EmitLabel (valueTaskNotCompletedLabel );
623+ pCode->EmitLabel (valueTaskCompletedLabel );
627624 pCode->EmitLDLOCA (valueTaskLocal);
628- pCode->EmitCALL (asTaskToken, 1 , 1 );
629- }
630-
631- MethodTable* pMTTask;
632-
633- int completedTaskResultToken;
634- if (msig.IsReturnTypeVoid ())
635- {
636- pMTTask = CoreLibBinder::GetClass (CLASS__TASK);
637-
638- MethodDesc* pMDCompletedTask = CoreLibBinder::GetMethod (METHOD__ASYNC_HELPERS__COMPLETED_TASK);
639- completedTaskResultToken = pCode->GetToken (pMDCompletedTask);
625+ pCode->EmitCALL (completionResultToken, 1 , msig.IsReturnTypeVoid () ? 0 : 1 );
626+ pCode->EmitRET ();
640627 }
641628 else
642629 {
643- MethodTable* pMTTaskOpen = CoreLibBinder::GetClass (CLASS__TASK_1);
644- pMTTask = ClassLoader::LoadGenericInstantiationThrowing (pMTTaskOpen->GetModule (), pMTTaskOpen->GetCl (), Instantiation (&thLogicalRetType, 1 )).GetMethodTable ();
630+ MethodTable* pMTTask;
645631
646- MethodDesc* pMDCompletedTaskResult = CoreLibBinder::GetMethod (METHOD__ASYNC_HELPERS__COMPLETED_TASK_RESULT) ;
647- pMDCompletedTaskResult = FindOrCreateAssociatedMethodDesc (pMDCompletedTaskResult, pMDCompletedTaskResult-> GetMethodTable (), FALSE , Instantiation (&thLogicalRetType, 1 ), FALSE );
648- completedTaskResultToken = GetTokenForGenericMethodCallWithAsyncReturnType (pCode, pMDCompletedTaskResult);
649- }
632+ int completedTaskResultToken ;
633+ if (msig. IsReturnTypeVoid ())
634+ {
635+ pMTTask = CoreLibBinder::GetClass (CLASS__TASK);
650636
651- LocalDesc taskLocalDesc (pMTTask);
652- DWORD taskLocal = pCode->NewLocal (taskLocalDesc);
653- ILCodeLabel* pGetResultLabel = pCode->NewCodeLabel ();
637+ MethodDesc* pMDCompletedTask = CoreLibBinder::GetMethod (METHOD__ASYNC_HELPERS__COMPLETED_TASK);
638+ completedTaskResultToken = pCode->GetToken (pMDCompletedTask);
639+ }
640+ else
641+ {
642+ MethodTable* pMTTaskOpen = CoreLibBinder::GetClass (CLASS__TASK_1);
643+ pMTTask = ClassLoader::LoadGenericInstantiationThrowing (pMTTaskOpen->GetModule (), pMTTaskOpen->GetCl (), Instantiation (&thLogicalRetType, 1 )).GetMethodTable ();
654644
655- // Store task returned by actual user func or by ValueTask.AsTask
656- pCode->EmitSTLOC (taskLocal);
645+ MethodDesc* pMDCompletedTaskResult = CoreLibBinder::GetMethod (METHOD__ASYNC_HELPERS__COMPLETED_TASK_RESULT);
646+ pMDCompletedTaskResult = FindOrCreateAssociatedMethodDesc (pMDCompletedTaskResult, pMDCompletedTaskResult->GetMethodTable (), FALSE , Instantiation (&thLogicalRetType, 1 ), FALSE );
647+ completedTaskResultToken = GetTokenForGenericMethodCallWithAsyncReturnType (pCode, pMDCompletedTaskResult);
648+ }
657649
658- pCode-> EmitLDLOC (taskLocal );
659- pCode->EmitCALL (METHOD__TASK__GET_ISCOMPLETED, 1 , 1 );
660- pCode->EmitBRTRUE (pGetResultLabel );
650+ LocalDesc taskLocalDesc (pMTTask );
651+ DWORD taskLocal = pCode->NewLocal (taskLocalDesc );
652+ ILCodeLabel* pGetResultLabel = pCode->NewCodeLabel ( );
661653
662- pCode-> EmitLDLOC (taskLocal);
663- pCode->EmitCALL (METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_TASK, 1 , 0 );
654+ // Store task returned by actual user func or by ValueTask.AsTask
655+ pCode->EmitSTLOC (taskLocal );
664656
665- pCode->EmitLabel (pGetResultLabel);
666- pCode->EmitLDLOC (taskLocal);
667- pCode->EmitCALL (completedTaskResultToken, 1 , msig.IsReturnTypeVoid () ? 0 : 1 );
668- pCode->EmitRET ();
657+ pCode->EmitLDLOC (taskLocal);
658+ pCode->EmitCALL (METHOD__TASK__GET_ISCOMPLETED, 1 , 1 );
659+ pCode->EmitBRTRUE (pGetResultLabel);
660+
661+ pCode->EmitLDLOC (taskLocal);
662+ pCode->EmitCALL (METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT, 1 , 0 );
663+
664+ pCode->EmitLabel (pGetResultLabel);
665+ pCode->EmitLDLOC (taskLocal);
666+ pCode->EmitCALL (completedTaskResultToken, 1 , msig.IsReturnTypeVoid () ? 0 : 1 );
667+ pCode->EmitRET ();
668+ }
669669}
0 commit comments