From 318c8a32d62e1527aa8832ada79088df448669bc Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Fri, 23 Apr 2021 16:54:09 -0700 Subject: [PATCH] Adjust generic dictionary to be able to resolve to a code pointer the constrained ldftn and call scenarios - R2R is not yet handled with this change --- src/coreclr/vm/genericdict.cpp | 6 +++--- src/coreclr/vm/jitinterface.cpp | 18 +++++++++++++++--- src/coreclr/vm/methodtable.cpp | 11 ++++++----- src/coreclr/vm/methodtable.h | 5 +++-- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/coreclr/vm/genericdict.cpp b/src/coreclr/vm/genericdict.cpp index fd6ef6d57c288d..1b5f0e3a6edbe0 100644 --- a/src/coreclr/vm/genericdict.cpp +++ b/src/coreclr/vm/genericdict.cpp @@ -1382,11 +1382,11 @@ Dictionary::PopulateEntry( } _ASSERTE(!constraintType.IsNull()); - MethodDesc *pResolvedMD = constraintType.GetMethodTable()->TryResolveConstraintMethodApprox(ownerType, pMethod); + MethodDesc *pResolvedMD = constraintType.GetMethodTable()->TryResolveConstraintMethodApprox(ownerType, pMethod, !pMethod->IsStatic()); // All such calls should be resolvable. If not then for now just throw an error. _ASSERTE(pResolvedMD); - INDEBUG(if (!pResolvedMD) constraintType.GetMethodTable()->TryResolveConstraintMethodApprox(ownerType, pMethod);) + INDEBUG(if (!pResolvedMD) constraintType.GetMethodTable()->TryResolveConstraintMethodApprox(ownerType, pMethod, !pMethod->IsStatic());) if (!pResolvedMD) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); @@ -1396,7 +1396,7 @@ Dictionary::PopulateEntry( // In such case we would need to box the value type before we can dispatch to the implementation. // This would require us to make a "boxing stub". For now we leave the boxing stubs unimplemented. // It's not clear if anyone would need them and the implementation complexity is not worth it at this time. - if (!pResolvedMD->GetMethodTable()->IsValueType() && constraintType.GetMethodTable()->IsValueType()) + if (pResolvedMD->IsStatic() && !pResolvedMD->GetMethodTable()->IsValueType() && constraintType.GetMethodTable()->IsValueType()) { SString assemblyName; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 77f7201fe0a758..77b6b66ebcdcbe 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -5183,6 +5183,7 @@ void CEEInfo::getCallInfo( MethodDesc * directMethod = constrainedType.GetMethodTable()->TryResolveConstraintMethodApprox( exactType, pMD, + TRUE, /* allowInstParam, At compile time the exact destination cannot reliably be known */ &fForceUseRuntimeLookup); if (directMethod #ifdef FEATURE_DEFAULT_INTERFACES @@ -5395,9 +5396,20 @@ void CEEInfo::getCallInfo( { pResult->kind = CORINFO_CALL_CODE_POINTER; - // For reference types, the constrained type does not affect method resolution - DictionaryEntryKind entryKind = (!constrainedType.IsNull() && constrainedType.IsValueType()) ? ConstrainedMethodEntrySlot : MethodEntrySlot; - + DictionaryEntryKind entryKind; + if (constrainedType.IsNull() || ((flags & CORINFO_CALLINFO_CALLVIRT) && !constrainedType.IsValueType())) + { + // For reference types, the constrained type does not affect method resolution on a callvirt, and if there is no + // constraint, it doesn't effect it either + entryKind = MethodEntrySlot; + } + else + { + // constrained. callvirt case where the constraint type is a valuetype + // OR + // constrained. call or constrained. ldftn case + entryKind = ConstrainedMethodEntrySlot; + } ComputeRuntimeLookupForSharedGenericToken(entryKind, pResolvedToken, pConstrainedResolvedToken, diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index f77cd646a136ca..2b5edad919fae4 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -9173,11 +9173,11 @@ MethodDesc *MethodTable::GetDefaultConstructor(BOOL forceBoxedEntryPoint /* = FA //========================================================================================== // Finds the (non-unboxing) MethodDesc that implements the interface virtual static method pInterfaceMD. MethodDesc * -MethodTable::ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD) +MethodTable::ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD, BOOL allowInstParam) { for (MethodTable* pMT = this; pMT != nullptr; pMT = pMT->GetParentMethodTable()) { - MethodDesc* pMD = pMT->TryResolveVirtualStaticMethodOnThisType(pInterfaceMD); + MethodDesc* pMD = pMT->TryResolveVirtualStaticMethodOnThisType(pInterfaceMD, allowInstParam); if (pMD != nullptr) { return pMD; @@ -9190,7 +9190,7 @@ MethodTable::ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD) // Try to locate the appropriate MethodImpl matching a given interface static virtual method. // Returns nullptr on failure. MethodDesc* -MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodDesc* pInterfaceMD) +MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodDesc* pInterfaceMD, BOOL allowInstParam) { HRESULT hr = S_OK; IMDInternalImport* pMDInternalImport = GetMDImport(); @@ -9263,7 +9263,7 @@ MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodDesc* pInterfaceMD) if (pInterfaceMD->HasMethodInstantiation() || pMethodImpl->HasMethodInstantiation() || HasInstantiation()) { - return pMethodImpl->FindOrCreateAssociatedMethodDesc(pMethodImpl, this, FALSE, pInterfaceMD->GetMethodInstantiation(), TRUE); + return pMethodImpl->FindOrCreateAssociatedMethodDesc(pMethodImpl, this, FALSE, pInterfaceMD->GetMethodInstantiation(), allowInstParam); } else { @@ -9286,6 +9286,7 @@ MethodDesc * MethodTable::TryResolveConstraintMethodApprox( TypeHandle thInterfaceType, MethodDesc * pInterfaceMD, + BOOL allowInstParam, BOOL * pfForceUseRuntimeLookup) // = NULL { CONTRACTL { @@ -9295,7 +9296,7 @@ MethodTable::TryResolveConstraintMethodApprox( if (pInterfaceMD->IsStatic()) { - return ResolveVirtualStaticMethod(pInterfaceMD); + return ResolveVirtualStaticMethod(pInterfaceMD, allowInstParam); } // 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 b6abc43722bdd4..6c5e9f5573856f 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); + MethodDesc *ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD, BOOL allowInstParam); // Try a partial resolve of the constraint call, up to generic code sharing. // @@ -2297,6 +2297,7 @@ class MethodTable MethodDesc * TryResolveConstraintMethodApprox( TypeHandle ownerType, MethodDesc * pMD, + BOOL fExactResolution = FALSE, BOOL * pfForceUseRuntimeLookup = NULL); //------------------------------------------------------------------- @@ -2397,7 +2398,7 @@ class MethodTable // Try to resolve a given static virtual method override on this type. Return nullptr // when not found. - MethodDesc *TryResolveVirtualStaticMethodOnThisType(MethodDesc* pInterfaceMD); + MethodDesc *TryResolveVirtualStaticMethodOnThisType(MethodDesc* pInterfaceMD, BOOL allowInstParam); public: static MethodDesc *MapMethodDeclToMethodImpl(MethodDesc *pMDDecl);