From 5c55368c8946b8a0c1752a4c96e1f35c583c2087 Mon Sep 17 00:00:00 2001 From: Tomas Date: Wed, 21 Apr 2021 22:17:53 +0200 Subject: [PATCH] First version of method resolution - Scenario1-5 passing --- src/coreclr/vm/methodtable.cpp | 89 +++++++++++++++++++++++++++++++++- src/coreclr/vm/methodtable.h | 4 ++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 6e9d8288d8f444..747831bb73642a 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -9175,10 +9175,97 @@ MethodDesc *MethodTable::GetDefaultConstructor(BOOL forceBoxedEntryPoint /* = FA MethodDesc * MethodTable::ResolveVirtualStaticMethod(MethodDesc* pInterfaceMD) { - // TODO + for (MethodTable* pMT = this; pMT != nullptr; pMT = pMT->GetParentMethodTable()) + { + MethodDesc* pMD = pMT->TryResolveVirtualStaticMethodOnThisType(pInterfaceMD); + if (pMD != nullptr) + { + return pMD; + } + } COMPlusThrow(kTypeLoadException, E_NOTIMPL); } +//========================================================================================== +// Try to locate the appropriate MethodImpl matching a given interface static virtual method. +// Returns nullptr on failure. +MethodDesc* +MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodDesc* pInterfaceMD) +{ + HRESULT hr = S_OK; + IMDInternalImport* pMDInternalImport = GetMDImport(); + HENUMInternalMethodImplHolder hEnumMethodImpl(pMDInternalImport); + hr = hEnumMethodImpl.EnumMethodImplInitNoThrow(GetCl()); + + if (FAILED(hr)) + { + COMPlusThrow(kTypeLoadException, hr); + } + + // This gets the count out of the metadata interface. + uint32_t dwNumberMethodImpls = hEnumMethodImpl.EnumMethodImplGetCount(); + + // Iterate through each MethodImpl declared on this class + for (uint32_t i = 0; i < dwNumberMethodImpls; i++) + { + mdToken methodBody; + mdToken methodDecl; + hr = hEnumMethodImpl.EnumMethodImplNext(&methodBody, &methodDecl); + if (FAILED(hr)) + { + COMPlusThrow(kTypeLoadException, hr); + } + if (hr == S_FALSE) + { + // In the odd case that the enumerator fails before we've reached the total reported + // entries, let's reset the count and just break out. (Should we throw?) + break; + } + mdToken tkParent; + hr = pMDInternalImport->GetParentToken(methodDecl, &tkParent); + if (FAILED(hr)) + { + COMPlusThrow(kTypeLoadException, hr); + } + MethodTable *pInterfaceMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing( + GetModule(), + tkParent, + NULL /*SigTypeContext*/) + .GetMethodTable(); + if (pInterfaceMT != pInterfaceMD->GetMethodTable()) + { + continue; + } + MethodDesc *pMethodDecl = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec( + GetModule(), + methodDecl, + NULL /*SigTypeContext*/, + /* strictMetadataChecks */ FALSE, + /* allowInstParam */ FALSE); + if (pMethodDecl == nullptr) + { + COMPlusThrow(kTypeLoadException, E_FAIL); + } + if (pMethodDecl != pInterfaceMD) + { + continue; + } + MethodDesc *pMethodImpl = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec( + GetModule(), + methodBody, + NULL /*SigTypeContext*/, + /* strictMetadataChecks */ FALSE, + /* allowInstParam */ FALSE); + if (pMethodImpl == nullptr) + { + COMPlusThrow(kTypeLoadException, E_FAIL); + } + return pMethodImpl; + } + + return nullptr; +} + //========================================================================================== // Finds the (non-unboxing) MethodDesc that implements the interface method pInterfaceMD. // diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index d5984745910c36..b6abc43722bdd4 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -2395,6 +2395,10 @@ class MethodTable // when it comes to dispatching pItfMT methods. BOOL HasSameInterfaceImplementationAsParent(MethodTable *pItfMT, MethodTable *pParentMT); + // Try to resolve a given static virtual method override on this type. Return nullptr + // when not found. + MethodDesc *TryResolveVirtualStaticMethodOnThisType(MethodDesc* pInterfaceMD); + public: static MethodDesc *MapMethodDeclToMethodImpl(MethodDesc *pMDDecl);