@@ -338,6 +338,46 @@ SigPointer MethodDesc::GetAsyncThunkResultTypeSig()
338338 return SigPointer (returnTypeSig, (DWORD)(returnTypeSigEnd - returnTypeSig));
339339}
340340
341+ bool MethodDesc::IsValueTaskAsyncThunk ()
342+ {
343+ _ASSERTE (IsAsyncThunkMethod ());
344+ PCCOR_SIGNATURE pSigRaw;
345+ DWORD cSig;
346+ if (FAILED (GetMDImport ()->GetSigOfMethodDef (GetMemberDef (), &cSig, &pSigRaw)))
347+ {
348+ _ASSERTE (!" Loaded MethodDesc should not fail to get signature" );
349+ pSigRaw = NULL ;
350+ cSig = 0 ;
351+ }
352+
353+ SigPointer pSig (pSigRaw, cSig);
354+ uint32_t callConvInfo;
355+ IfFailThrow (pSig.GetCallingConvInfo (&callConvInfo));
356+
357+ if ((callConvInfo & IMAGE_CEE_CS_CALLCONV_GENERIC) != 0 )
358+ {
359+ // GenParamCount
360+ IfFailThrow (pSig.GetData (NULL ));
361+ }
362+
363+ // ParamCount
364+ IfFailThrow (pSig.GetData (NULL ));
365+
366+ // ReturnType comes now. Skip the modifiers.
367+ IfFailThrow (pSig.SkipCustomModifiers ());
368+
369+ // here we should have something Task, ValueTask, Task<retType> or ValueTask<retType>
370+ BYTE bElementType;
371+ IfFailThrow (pSig.GetByte (&bElementType));
372+
373+ // skip ELEMENT_TYPE_GENERICINST
374+ if (bElementType == ELEMENT_TYPE_GENERICINST)
375+ IfFailThrow (pSig.GetByte (&bElementType));
376+
377+ _ASSERTE (bElementType == ELEMENT_TYPE_VALUETYPE || bElementType == ELEMENT_TYPE_CLASS);
378+ return bElementType == ELEMENT_TYPE_VALUETYPE;
379+ }
380+
341381// Given a method Foo<T>, return a MethodSpec token for Foo<T> instantiated
342382// with the result type from the current async method's return type. For
343383// example, if "this" represents Task<List<T>> Foo<T>(), and "md" is
@@ -435,30 +475,32 @@ void MethodDesc::EmitAsyncMethodThunk(MethodDesc* pAsyncOtherVariant, MetaSig& m
435475 MethodDesc* mdIsCompleted;
436476 MethodDesc* mdGetResult;
437477
478+ bool isValueTask = IsValueTaskAsyncThunk ();
479+
438480 if (msig.IsReturnTypeVoid ())
439481 {
440- pMTTask = CoreLibBinder::GetClass (CLASS__TASK);
441- thTaskAwaiter = CoreLibBinder::GetClass (CLASS__TASK_AWAITER);
442- mdGetAwaiter = CoreLibBinder::GetMethod (METHOD__TASK__GET_AWAITER);
443- mdIsCompleted = CoreLibBinder::GetMethod (METHOD__TASK_AWAITER__GET_ISCOMPLETED);
444- mdGetResult = CoreLibBinder::GetMethod (METHOD__TASK_AWAITER__GET_RESULT);
482+ pMTTask = CoreLibBinder::GetClass (isValueTask ? CLASS__VALUETASK : CLASS__TASK);
483+ thTaskAwaiter = CoreLibBinder::GetClass (isValueTask ? CLASS__VALUETASK_AWAITER : CLASS__TASK_AWAITER);
484+ mdGetAwaiter = CoreLibBinder::GetMethod (isValueTask ? METHOD__VALUETASK__GET_AWAITER : METHOD__TASK__GET_AWAITER);
485+ mdIsCompleted = CoreLibBinder::GetMethod (isValueTask ? METHOD__VALUETASK_AWAITER__GET_ISCOMPLETED : METHOD__TASK_AWAITER__GET_ISCOMPLETED);
486+ mdGetResult = CoreLibBinder::GetMethod (isValueTask ? METHOD__VALUETASK_AWAITER__GET_RESULT : METHOD__TASK_AWAITER__GET_RESULT);
445487 }
446488 else
447489 {
448490 TypeHandle thLogicalRetType = msig.GetRetTypeHandleThrowing ();
449- MethodTable* pMTTaskOpen = CoreLibBinder::GetClass (CLASS__TASK_1);
491+ MethodTable* pMTTaskOpen = CoreLibBinder::GetClass (isValueTask ? CLASS__VALUETASK_1 : CLASS__TASK_1);
450492 pMTTask = ClassLoader::LoadGenericInstantiationThrowing (pMTTaskOpen->GetModule (), pMTTaskOpen->GetCl (), Instantiation (&thLogicalRetType, 1 )).GetMethodTable ();
451- MethodTable* pMTTaskAwaiterOpen = CoreLibBinder::GetClass (CLASS__TASK_AWAITER_1);
493+ MethodTable* pMTTaskAwaiterOpen = CoreLibBinder::GetClass (isValueTask ? CLASS__VALUETASK_AWAITER_1 : CLASS__TASK_AWAITER_1);
452494
453495 thTaskAwaiter = ClassLoader::LoadGenericInstantiationThrowing (pMTTaskAwaiterOpen->GetModule (), pMTTaskAwaiterOpen->GetCl (), Instantiation (&thLogicalRetType, 1 ));
454496
455- mdGetAwaiter = CoreLibBinder::GetMethod (METHOD__TASK_1__GET_AWAITER);
497+ mdGetAwaiter = CoreLibBinder::GetMethod (isValueTask ? METHOD__VALUETASK_1__GET_AWAITER : METHOD__TASK_1__GET_AWAITER);
456498 mdGetAwaiter = MethodDesc::FindOrCreateAssociatedMethodDesc (mdGetAwaiter, pMTTask, FALSE , Instantiation (), FALSE );
457499
458- mdIsCompleted = CoreLibBinder::GetMethod (METHOD__TASK_AWAITER_1__GET_ISCOMPLETED);
500+ mdIsCompleted = CoreLibBinder::GetMethod (isValueTask ? METHOD__VALUETASK_AWAITER_1__GET_ISCOMPLETED : METHOD__TASK_AWAITER_1__GET_ISCOMPLETED);
459501 mdIsCompleted = MethodDesc::FindOrCreateAssociatedMethodDesc (mdIsCompleted, thTaskAwaiter.GetMethodTable (), FALSE , Instantiation (), FALSE );
460502
461- mdGetResult = CoreLibBinder::GetMethod (METHOD__TASK_AWAITER_1__GET_RESULT);
503+ mdGetResult = CoreLibBinder::GetMethod (isValueTask ? METHOD__VALUETASK_AWAITER_1__GET_RESULT : METHOD__TASK_AWAITER_1__GET_RESULT);
462504 mdGetResult = MethodDesc::FindOrCreateAssociatedMethodDesc (mdGetResult, thTaskAwaiter.GetMethodTable (), FALSE , Instantiation (), FALSE );
463505 }
464506
@@ -550,7 +592,19 @@ void MethodDesc::EmitAsyncMethodThunk(MethodDesc* pAsyncOtherVariant, MetaSig& m
550592 getResultToken = pCode->GetToken (mdGetResult);
551593 }
552594
553- pCode->EmitCALLVIRT (getAwaiterToken, 1 , 1 );
595+ if (isValueTask)
596+ {
597+ LocalDesc valuetaskLocalDesc (pMTTask);
598+ DWORD valuetaskLocal = pCode->NewLocal (valuetaskLocalDesc);
599+ pCode->EmitSTLOC (valuetaskLocal);
600+ pCode->EmitLDLOCA (valuetaskLocal);
601+ pCode->EmitCALL (getAwaiterToken, 1 , 1 );
602+ }
603+ else
604+ {
605+ pCode->EmitCALLVIRT (getAwaiterToken, 1 , 1 );
606+ }
607+
554608 pCode->EmitSTLOC (awaiterLocal);
555609 pCode->EmitLDLOCA (awaiterLocal);
556610 pCode->EmitCALL (getIsCompletedToken, 1 , 1 );
0 commit comments