Skip to content

Commit 1752b96

Browse files
authored
[RuntimeAsync] Tweak some reflection scenarios around async methods. (#118045)
[RuntimeAsync] Tweak some reflection scenarios around async methods. (#118045)
1 parent e11a3d4 commit 1752b96

File tree

16 files changed

+272
-82
lines changed

16 files changed

+272
-82
lines changed

src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2736,20 +2736,30 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn
27362736
im.InterfaceMethods = new MethodInfo[ifaceVirtualMethodCount];
27372737
im.TargetMethods = new MethodInfo[ifaceVirtualMethodCount];
27382738

2739+
int actualCount = 0;
27392740
for (int i = 0; i < ifaceVirtualMethodCount; i++)
27402741
{
27412742
RuntimeMethodHandleInternal ifaceRtMethodHandle = RuntimeTypeHandle.GetMethodAt(ifaceRtType, i);
27422743

2744+
// GetMethodAt may return null handle for methods that do not exist or are not supposed
2745+
// to be seen in reflection. One example is async variant methods.
2746+
// We do not record mapping for interface methods that do not exist.
2747+
if (ifaceRtMethodHandle.IsNullHandle())
2748+
continue;
2749+
27432750
// GetMethodBase will convert this to the instantiating/unboxing stub if necessary
27442751
MethodBase ifaceMethodBase = GetMethodBase(ifaceRtType, ifaceRtMethodHandle)!;
27452752
Debug.Assert(ifaceMethodBase is RuntimeMethodInfo);
2746-
im.InterfaceMethods[i] = (MethodInfo)ifaceMethodBase;
2753+
im.InterfaceMethods[actualCount] = (MethodInfo)ifaceMethodBase;
27472754

27482755
// If the impl is null, then virtual stub dispatch is active.
27492756
RuntimeMethodHandleInternal classRtMethodHandle = TypeHandle.GetInterfaceMethodImplementation(ifaceRtTypeHandle, ifaceRtMethodHandle);
27502757

27512758
if (classRtMethodHandle.IsNullHandle())
2759+
{
2760+
actualCount++;
27522761
continue;
2762+
}
27532763

27542764
// If we resolved to an interface method, use the interface type as reflected type. Otherwise use `this`.
27552765
RuntimeType reflectedType = RuntimeMethodHandle.GetDeclaringType(classRtMethodHandle);
@@ -2764,10 +2774,16 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn
27642774
// the TargetMethod provided to us by runtime internals may be a generic method instance,
27652775
// potentially with invalid arguments. TargetMethods in the InterfaceMap should never be
27662776
// instances, only definitions.
2767-
im.TargetMethods[i] = (targetMethod is { IsGenericMethod: true, IsGenericMethodDefinition: false })
2777+
im.TargetMethods[actualCount++] = (targetMethod is { IsGenericMethod: true, IsGenericMethodDefinition: false })
27682778
? targetMethod.GetGenericMethodDefinition() : targetMethod!;
27692779
}
27702780

2781+
if (actualCount != ifaceVirtualMethodCount)
2782+
{
2783+
Array.Resize(ref im.InterfaceMethods, actualCount);
2784+
Array.Resize(ref im.TargetMethods, actualCount);
2785+
}
2786+
27712787
return im;
27722788
}
27732789
#endregion

src/coreclr/vm/asyncthunks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ bool MethodDesc::TryGenerateAsyncThunk(DynamicResolver** resolver, COR_ILMETHOD_
1818
_ASSERTE(methodILDecoder != NULL);
1919
_ASSERTE(*resolver == NULL && *methodILDecoder == NULL);
2020
_ASSERTE(IsIL());
21-
_ASSERTE(GetRVA() == 0);
21+
_ASSERTE(!HasILHeader());
2222

2323
if (!IsAsyncThunkMethod())
2424
{

src/coreclr/vm/codeversion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ PTR_COR_ILMETHOD ILCodeVersion::GetIL() const
913913
{
914914
PTR_Module pModule = GetModule();
915915
PTR_MethodDesc pMethodDesc = dac_cast<PTR_MethodDesc>(pModule->LookupMethodDef(GetMethodDef()));
916-
if (pMethodDesc != NULL)
916+
if (pMethodDesc != NULL && pMethodDesc->MayHaveILHeader())
917917
{
918918
pIL = dac_cast<PTR_COR_ILMETHOD>(pMethodDesc->GetILHeader());
919919
}

src/coreclr/vm/dwbucketmanager.hpp

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,6 @@ class BaseBucketParamsManager
326326
void GetExceptionName(_Out_writes_(maxLength) WCHAR* targetParam, int maxLength);
327327
void GetPackageMoniker(_Out_writes_(maxLength) WCHAR* targetParam, int maxLength);
328328
void GetPRAID(_Out_writes_(maxLength) WCHAR* targetParam, int maxLength);
329-
void GetIlRva(_Out_writes_(maxLength) WCHAR* targetParam, int maxLength);
330329

331330
public:
332331
BaseBucketParamsManager(GenericModeBlock* pGenericModeBlock, TypeOfReportedError typeOfError, PCODE initialFaultingPc, Thread* pFaultingThread, OBJECTREF* pThrownException);
@@ -810,31 +809,6 @@ void BaseBucketParamsManager::GetPRAID(_Out_writes_(maxLength) WCHAR* targetPara
810809
_ASSERTE(!"PRAID support NYI for CoreCLR");
811810
}
812811

813-
void BaseBucketParamsManager::GetIlRva(_Out_writes_(maxLength) WCHAR* targetParam, int maxLength)
814-
{
815-
CONTRACTL
816-
{
817-
NOTHROW;
818-
GC_NOTRIGGER;
819-
MODE_ANY;
820-
}
821-
CONTRACTL_END;
822-
823-
DWORD ilOffset = GetILOffset();
824-
825-
if (ilOffset == MAXDWORD)
826-
ilOffset = 0;
827-
828-
if (m_pFaultingMD)
829-
ilOffset += m_pFaultingMD->GetRVA();
830-
831-
_snwprintf_s(targetParam,
832-
maxLength,
833-
_TRUNCATE,
834-
W("%x"),
835-
ilOffset);
836-
}
837-
838812
// helper functions
839813

840814
DWORD BaseBucketParamsManager::GetILOffset()

src/coreclr/vm/eedbginterface.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,6 @@ class EEDebugInterface
264264

265265
virtual COR_ILMETHOD* MethodDescGetILHeader(MethodDesc *pFD) = 0;
266266

267-
virtual ULONG MethodDescGetRVA(MethodDesc *pFD) = 0;
268-
269267
virtual void MarkDebuggerAttached(void) = 0;
270268

271269
virtual void MarkDebuggerUnattached(void) = 0;

src/coreclr/vm/eedbginterfaceimpl.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -721,19 +721,6 @@ COR_ILMETHOD* EEDbgInterfaceImpl::MethodDescGetILHeader(MethodDesc *pFD)
721721
RETURN NULL;
722722
}
723723

724-
ULONG EEDbgInterfaceImpl::MethodDescGetRVA(MethodDesc *pFD)
725-
{
726-
CONTRACTL
727-
{
728-
NOTHROW;
729-
GC_NOTRIGGER;
730-
PRECONDITION(CheckPointer(pFD));
731-
}
732-
CONTRACTL_END;
733-
734-
return pFD->GetRVA();
735-
}
736-
737724
MethodDesc *EEDbgInterfaceImpl::FindLoadedMethodRefOrDef(Module* pModule,
738725
mdToken memberRef)
739726
{

src/coreclr/vm/eedbginterfaceimpl.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,6 @@ class EEDbgInterfaceImpl : public EEDebugInterface
156156

157157
COR_ILMETHOD* MethodDescGetILHeader(MethodDesc *pFD);
158158

159-
ULONG MethodDescGetRVA(MethodDesc *pFD);
160-
161159
MethodDesc *FindLoadedMethodRefOrDef(Module* pModule,
162160
mdToken memberRef);
163161

src/coreclr/vm/jitinterface.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7680,20 +7680,16 @@ CEEInfo::getMethodInfo(
76807680
JIT_TO_EE_TRANSITION();
76817681

76827682
MethodDesc* ftn = GetMethod(ftnHnd);
7683-
if (ftn->IsDynamicMethod())
7684-
{
7685-
getMethodInfoWorker(ftn, NULL, methInfo, context);
7686-
result = true;
7687-
}
7688-
else if (!ftn->IsWrapperStub() && ftn->HasILHeader())
7683+
if (ftn->HasILHeader())
76897684
{
76907685
// Get the IL header and set it.
76917686
COR_ILMETHOD_DECODER header(ftn->GetILHeader(), ftn->GetMDImport(), NULL);
76927687
getMethodInfoWorker(ftn, &header, methInfo, context);
76937688
result = true;
76947689
}
7695-
else if (ftn->IsIL() && ftn->GetRVA() == 0) // IL methods with no RVA indicate there is no implementation defined in metadata.
7690+
else if (ftn->IsIL() || ftn->IsDynamicMethod())
76967691
{
7692+
// IL methods with no IL header indicate there is no implementation defined in metadata.
76977693
getMethodInfoWorker(ftn, NULL, methInfo, context);
76987694
result = true;
76997695
}
@@ -7875,7 +7871,7 @@ CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller,
78757871
goto exit;
78767872
}
78777873
}
7878-
else if (pCallee->IsIL() && pCallee->GetRVA() == 0)
7874+
else if (pCallee->IsIL())
78797875
{
78807876
CORINFO_METHOD_INFO methodInfo;
78817877
getMethodInfoWorker(pCallee, NULL, &methodInfo);
@@ -12788,7 +12784,7 @@ void CEECodeGenInfo::getEHinfo(
1278812784
COR_ILMETHOD_DECODER header(pMD->GetILHeader(), pMD->GetMDImport(), NULL);
1278912785
getEHinfoHelper(ftn, EHnumber, clause, &header);
1279012786
}
12791-
else if (pMD->IsIL() && pMD->GetRVA() == 0)
12787+
else if (pMD->IsIL())
1279212788
{
1279312789
TransientMethodDetails* details;
1279412790
if (!FindTransientMethodDetails(pMD, &details))

src/coreclr/vm/method.cpp

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,8 +1123,10 @@ BOOL MethodDesc::HasRetBuffArg()
11231123
}
11241124

11251125
//*******************************************************************************
1126-
// This returns the offset of the IL.
1127-
// The offset is relative to the base of the IL image.
1126+
// This typically returns the offset of the IL.
1127+
// Another case when a method may have an RVA is earlybound IJW PInvokes,
1128+
// in which case the RVA is referring to native code.
1129+
// The offset is relative to the base of the image.
11281130
ULONG MethodDesc::GetRVA()
11291131
{
11301132
CONTRACTL
@@ -1133,27 +1135,11 @@ ULONG MethodDesc::GetRVA()
11331135
GC_NOTRIGGER;
11341136
FORBID_FAULT;
11351137
SUPPORTS_DAC;
1138+
PRECONDITION((IsIL() && MayHaveILHeader()) ||
1139+
(IsPInvoke() && ((PInvokeMethodDesc*)this)->IsEarlyBound()));
11361140
}
11371141
CONTRACTL_END
11381142

1139-
if (IsRuntimeSupplied())
1140-
{
1141-
return 0;
1142-
}
1143-
1144-
// Methods without metadata don't have an RVA. Examples are IL stubs and LCG methods.
1145-
if (IsNoMetadata())
1146-
{
1147-
return 0;
1148-
}
1149-
1150-
// Between two Async variants of the same method only one represents the actual IL.
1151-
// It is the variant that is not a thunk.
1152-
if (IsAsyncThunkMethod())
1153-
{
1154-
return 0;
1155-
}
1156-
11571143
if (GetMemberDef() & 0x00FFFFFF)
11581144
{
11591145
Module *pModule = GetModule();
@@ -1198,8 +1184,7 @@ COR_ILMETHOD* MethodDesc::GetILHeader()
11981184
{
11991185
THROWS;
12001186
GC_NOTRIGGER;
1201-
PRECONDITION(IsIL());
1202-
PRECONDITION(!IsUnboxingStub());
1187+
PRECONDITION(MayHaveILHeader());
12031188
}
12041189
CONTRACTL_END
12051190

src/coreclr/vm/method.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,8 @@ class MethodDesc
901901
MODE_ANY;
902902
}
903903
CONTRACTL_END;
904-
return IsIL() && !IsUnboxingStub() && GetRVA();
904+
905+
return MayHaveILHeader() && GetRVA();
905906
}
906907

907908
COR_ILMETHOD* GetILHeader();
@@ -1499,6 +1500,14 @@ class MethodDesc
14991500

15001501
BOOL MayHaveNativeCode();
15011502

1503+
BOOL MayHaveILHeader()
1504+
{
1505+
LIMITED_METHOD_DAC_CONTRACT;
1506+
1507+
// methods with transient IL bodies do not have IL headers
1508+
return IsIL() && !IsUnboxingStub() && !IsAsyncThunkMethod();
1509+
}
1510+
15021511
ULONG GetRVA();
15031512

15041513
public:

0 commit comments

Comments
 (0)