From 72c6cdc3029482c9f7848a1878f032e112a5bcd9 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Mon, 26 Apr 2021 15:51:53 -0700 Subject: [PATCH] - Pass thru allowInstParam flag from jit interface to TryResolveConstraintMethodApprox function - On resolution failure when resolving during the JIT allow returning NULL. (In that case force the resolution to be runtime) - When performing runtime resolution do not add an extra inst parameter. --- src/coreclr/vm/jitinterface.cpp | 22 ++++++++++++++++++---- src/coreclr/vm/jitinterface.h | 1 + src/coreclr/vm/methodtable.cpp | 15 ++++++++++++--- src/coreclr/vm/methodtable.h | 2 +- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 77b6b66ebcdcb..16d80be5f154a 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -5183,7 +5183,7 @@ void CEEInfo::getCallInfo( MethodDesc * directMethod = constrainedType.GetMethodTable()->TryResolveConstraintMethodApprox( exactType, pMD, - TRUE, /* allowInstParam, At compile time the exact destination cannot reliably be known */ + !!(flags & CORINFO_CALLINFO_ALLOWINSTPARAM), &fForceUseRuntimeLookup); if (directMethod #ifdef FEATURE_DEFAULT_INTERFACES @@ -5347,7 +5347,8 @@ void CEEInfo::getCallInfo( // Direct calls to abstract methods are not allowed if (IsMdAbstract(dwTargetMethodAttrs) && // Compensate for always treating delegates as direct calls above - !(((flags & CORINFO_CALLINFO_LDFTN) && (flags & CORINFO_CALLINFO_CALLVIRT) && !resolvedCallVirt))) + !(((flags & CORINFO_CALLINFO_LDFTN) && (flags & CORINFO_CALLINFO_CALLVIRT) && !resolvedCallVirt)) + && !(IsMdStatic(dwTargetMethodAttrs) && fForceUseRuntimeLookup)) { COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL); } @@ -5712,7 +5713,19 @@ void CEEInfo::getCallInfo( pResult->methodFlags = getMethodAttribsInternal(pResult->hMethod); - SignatureKind signatureKind = flags & CORINFO_CALLINFO_CALLVIRT && !(pResult->kind == CORINFO_CALL) ? SK_VIRTUAL_CALLSITE : SK_CALLSITE; + SignatureKind signatureKind; + if (flags & CORINFO_CALLINFO_CALLVIRT && !(pResult->kind == CORINFO_CALL)) + { + signatureKind = SK_VIRTUAL_CALLSITE; + } + else if ((pResult->kind == CORINFO_CALL_CODE_POINTER) && IsMdVirtual(dwTargetMethodAttrs) && IsMdStatic(dwTargetMethodAttrs)) + { + signatureKind = SK_STATIC_VIRTUAL_CODEPOINTER_CALLSITE; + } + else + { + signatureKind = SK_CALLSITE; + } getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL, signatureKind); if (flags & CORINFO_CALLINFO_VERIFICATION) @@ -8647,7 +8660,8 @@ CEEInfo::getMethodSigInternal( BOOL isCallSiteThatGoesThroughInstantiatingStub = signatureKind == SK_VIRTUAL_CALLSITE && !ftn->IsStatic() && - ftn->GetMethodTable()->IsInterface(); + ftn->GetMethodTable()->IsInterface() || + signatureKind == SK_STATIC_VIRTUAL_CODEPOINTER_CALLSITE; if (!isCallSiteThatGoesThroughInstantiatingStub) sigRet->callConv = (CorInfoCallConv) (sigRet->callConv | CORINFO_CALLCONV_PARAMTYPE); } diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index bddc24fc4c3df..7cdba53f1cfd8 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -34,6 +34,7 @@ enum SignatureKind SK_NOT_CALLSITE, SK_CALLSITE, SK_VIRTUAL_CALLSITE, + SK_STATIC_VIRTUAL_CODEPOINTER_CALLSITE, }; class Stub; diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 2fd66badafe8c..6f538666359b8 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -9173,7 +9173,7 @@ MethodDesc *MethodTable::GetDefaultConstructor(BOOL forceBoxedEntryPoint /* = FA //========================================================================================== // Finds the (non-unboxing) MethodDesc that implements the interface virtual static method pInterfaceMD. MethodDesc * -MethodTable::ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD, BOOL allowInstParam) +MethodTable::ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD, BOOL allowInstParam, BOOL allowNullResult) { for (MethodTable* pMT = this; pMT != nullptr; pMT = pMT->GetParentMethodTable()) { @@ -9183,7 +9183,11 @@ MethodTable::ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD, BOOL allowInst return pMD; } } - COMPlusThrow(kTypeLoadException, E_NOTIMPL); + + if (allowNullResult) + return NULL; + else + COMPlusThrow(kTypeLoadException, E_NOTIMPL); } //========================================================================================== @@ -9298,7 +9302,12 @@ MethodTable::TryResolveConstraintMethodApprox( if (pInterfaceMD->IsStatic()) { - return ResolveVirtualStaticMethod(pInterfaceMD, allowInstParam); + MethodDesc *result = ResolveVirtualStaticMethod(pInterfaceMD, allowInstParam, pfForceUseRuntimeLookup != NULL); + if (result == NULL) + { + *pfForceUseRuntimeLookup = TRUE; + } + return result; } // We can't resolve constraint calls effectively for reference types, and there's diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 6c5e9f5573856..eb181d920679c 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -2280,7 +2280,7 @@ class MethodTable // Resolve virtual static interface method pInterfaceMD on this type. - MethodDesc *ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD, BOOL allowInstParam); + MethodDesc *ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD, BOOL allowInstParam, BOOL allowNullResult); // Try a partial resolve of the constraint call, up to generic code sharing. //