Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 88 additions & 1 deletion src/coreclr/vm/methodtable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MethodImpl matching actually just looks through the set of Methods to find the one with the matching MethodDef token, and it doesn't actually do resolution via the 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.
//
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/vm/methodtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down