summaryrefslogtreecommitdiff
path: root/src/vm/methodtable.cpp
diff options
context:
space:
mode:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2018-11-15 14:08:27 +0100
committerGitHub <noreply@github.com>2018-11-15 14:08:27 +0100
commit4b01ac0d72d2b271a3f664d1fe3761287f5efc6a (patch)
treece702363d5b1a61f3783f8fc1e27dc182f71f8d6 /src/vm/methodtable.cpp
parentbf1a55fab3f07771632a76d52c6d9287a339bb79 (diff)
downloadcoreclr-4b01ac0d72d2b271a3f664d1fe3761287f5efc6a.tar.gz
coreclr-4b01ac0d72d2b271a3f664d1fe3761287f5efc6a.tar.bz2
coreclr-4b01ac0d72d2b271a3f664d1fe3761287f5efc6a.zip
Allow supressing exceptions in diamond inheritance cases (#20458)
Diffstat (limited to 'src/vm/methodtable.cpp')
-rw-r--r--src/vm/methodtable.cpp68
1 files changed, 42 insertions, 26 deletions
diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp
index 57f24959fa..b80f1e886d 100644
--- a/src/vm/methodtable.cpp
+++ b/src/vm/methodtable.cpp
@@ -799,7 +799,7 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule
TypeHandle resulTypeHnd = resultTypeObj->GetType();
MethodTable *pResultMT = resulTypeHnd.GetMethodTable();
- RETURN(pResultMT->GetMethodDescForInterfaceMethod(ownerType, pItfMD));
+ RETURN(pResultMT->GetMethodDescForInterfaceMethod(ownerType, pItfMD, TRUE /* throwOnConflict */));
}
#endif
@@ -820,7 +820,7 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule
#endif // !FEATURE_COMINTEROP
// Handle pure COM+ types.
- RETURN (pServerMT->GetMethodDescForInterfaceMethod(ownerType, pItfMD));
+ RETURN (pServerMT->GetMethodDescForInterfaceMethod(ownerType, pItfMD, TRUE /* throwOnConflict */));
}
#ifdef FEATURE_COMINTEROP
@@ -858,7 +858,7 @@ MethodDesc *MethodTable::GetMethodDescForComInterfaceMethod(MethodDesc *pItfMD,
// Calling GetTarget here instead of FindDispatchImpl gives us caching functionality to increase speed.
PCODE tgt = VirtualCallStubManager::GetTarget(
- pItfMT->GetLoaderAllocator()->GetDispatchToken(pItfMT->GetTypeID(), pItfMD->GetSlot()), this);
+ pItfMT->GetLoaderAllocator()->GetDispatchToken(pItfMT->GetTypeID(), pItfMD->GetSlot()), this, TRUE /* throwOnConflict */);
if (tgt != NULL)
{
@@ -2076,7 +2076,7 @@ BOOL MethodTable::ImplementsEquivalentInterface(MethodTable *pInterface)
}
//==========================================================================================
-MethodDesc *MethodTable::GetMethodDescForInterfaceMethod(MethodDesc *pInterfaceMD)
+MethodDesc *MethodTable::GetMethodDescForInterfaceMethod(MethodDesc *pInterfaceMD, BOOL throwOnConflict)
{
CONTRACTL
{
@@ -2087,11 +2087,11 @@ MethodDesc *MethodTable::GetMethodDescForInterfaceMethod(MethodDesc *pInterfaceM
CONTRACTL_END;
WRAPPER_NO_CONTRACT;
- return GetMethodDescForInterfaceMethod(TypeHandle(pInterfaceMD->GetMethodTable()), pInterfaceMD);
+ return GetMethodDescForInterfaceMethod(TypeHandle(pInterfaceMD->GetMethodTable()), pInterfaceMD, throwOnConflict);
}
//==========================================================================================
-MethodDesc *MethodTable::GetMethodDescForInterfaceMethod(TypeHandle ownerType, MethodDesc *pInterfaceMD)
+MethodDesc *MethodTable::GetMethodDescForInterfaceMethod(TypeHandle ownerType, MethodDesc *pInterfaceMD, BOOL throwOnConflict)
{
CONTRACTL
{
@@ -2109,17 +2109,27 @@ MethodDesc *MethodTable::GetMethodDescForInterfaceMethod(TypeHandle ownerType, M
MethodTable *pInterfaceMT = ownerType.AsMethodTable();
#ifdef CROSSGEN_COMPILE
- DispatchSlot implSlot(FindDispatchSlot(pInterfaceMT->GetTypeID(), pInterfaceMD->GetSlot()));
+ DispatchSlot implSlot(FindDispatchSlot(pInterfaceMT->GetTypeID(), pInterfaceMD->GetSlot(), throwOnConflict));
+ if (implSlot.IsNull())
+ {
+ _ASSERTE(!throwOnConflict);
+ return NULL;
+ }
PCODE pTgt = implSlot.GetTarget();
#else
PCODE pTgt = VirtualCallStubManager::GetTarget(
pInterfaceMT->GetLoaderAllocator()->GetDispatchToken(pInterfaceMT->GetTypeID(), pInterfaceMD->GetSlot()),
- this);
+ this, throwOnConflict);
+ if (pTgt == NULL)
+ {
+ _ASSERTE(!throwOnConflict);
+ return NULL;
+ }
#endif
pMD = MethodTable::GetMethodDescForSlotAddress(pTgt);
#ifdef _DEBUG
- MethodDesc *pDispSlotMD = FindDispatchSlotForInterfaceMD(ownerType, pInterfaceMD).GetMethodDesc();
+ MethodDesc *pDispSlotMD = FindDispatchSlotForInterfaceMD(ownerType, pInterfaceMD, throwOnConflict).GetMethodDesc();
_ASSERTE(pDispSlotMD == pMD);
#endif // _DEBUG
@@ -6918,7 +6928,8 @@ BOOL
MethodTable::FindDispatchImpl(
UINT32 typeID,
UINT32 slotNumber,
- DispatchSlot * pImplSlot)
+ DispatchSlot * pImplSlot,
+ BOOL throwOnConflict)
{
CONTRACT (BOOL) {
INSTANCE_CHECK;
@@ -7001,7 +7012,8 @@ MethodTable::FindDispatchImpl(
if (FindDefaultInterfaceImplementation(
pIfcMD, // the interface method being resolved
pIfcMT, // the interface being resolved
- &pDefaultMethod))
+ &pDefaultMethod,
+ throwOnConflict))
{
// Now, construct a DispatchSlot to return in *pImplSlot
DispatchSlot ds(pDefaultMethod->GetMethodEntryPoint());
@@ -7080,7 +7092,8 @@ void ThrowExceptionForConflictingOverride(
BOOL MethodTable::FindDefaultInterfaceImplementation(
MethodDesc *pInterfaceMD,
MethodTable *pInterfaceMT,
- MethodDesc **ppDefaultMethod
+ MethodDesc **ppDefaultMethod,
+ BOOL throwOnConflict
)
{
CONTRACT(BOOL) {
@@ -7313,7 +7326,11 @@ BOOL MethodTable::FindDefaultInterfaceImplementation(
}
else if (pBestCandidateMT != candidates[i].pMT)
{
- ThrowExceptionForConflictingOverride(this, pInterfaceMT, pInterfaceMD);
+ if (throwOnConflict)
+ ThrowExceptionForConflictingOverride(this, pInterfaceMT, pInterfaceMD);
+
+ *ppDefaultMethod = NULL;
+ RETURN(FALSE);
}
}
@@ -7331,17 +7348,17 @@ BOOL MethodTable::FindDefaultInterfaceImplementation(
#endif // DACCESS_COMPILE
//==========================================================================================
-DispatchSlot MethodTable::FindDispatchSlot(UINT32 typeID, UINT32 slotNumber)
+DispatchSlot MethodTable::FindDispatchSlot(UINT32 typeID, UINT32 slotNumber, BOOL throwOnConflict)
{
WRAPPER_NO_CONTRACT;
STATIC_CONTRACT_SO_TOLERANT;
DispatchSlot implSlot(NULL);
- FindDispatchImpl(typeID, slotNumber, &implSlot);
+ FindDispatchImpl(typeID, slotNumber, &implSlot, throwOnConflict);
return implSlot;
}
//==========================================================================================
-DispatchSlot MethodTable::FindDispatchSlot(DispatchToken tok)
+DispatchSlot MethodTable::FindDispatchSlot(DispatchToken tok, BOOL throwOnConflict)
{
CONTRACTL
{
@@ -7351,28 +7368,28 @@ DispatchSlot MethodTable::FindDispatchSlot(DispatchToken tok)
MODE_ANY;
}
CONTRACTL_END;
- return FindDispatchSlot(tok.GetTypeID(), tok.GetSlotNumber());
+ return FindDispatchSlot(tok.GetTypeID(), tok.GetSlotNumber(), throwOnConflict);
}
#ifndef DACCESS_COMPILE
//==========================================================================================
-DispatchSlot MethodTable::FindDispatchSlotForInterfaceMD(MethodDesc *pMD)
+DispatchSlot MethodTable::FindDispatchSlotForInterfaceMD(MethodDesc *pMD, BOOL throwOnConflict)
{
WRAPPER_NO_CONTRACT;
CONSISTENCY_CHECK(CheckPointer(pMD));
CONSISTENCY_CHECK(pMD->IsInterface());
- return FindDispatchSlotForInterfaceMD(TypeHandle(pMD->GetMethodTable()), pMD);
+ return FindDispatchSlotForInterfaceMD(TypeHandle(pMD->GetMethodTable()), pMD, throwOnConflict);
}
//==========================================================================================
-DispatchSlot MethodTable::FindDispatchSlotForInterfaceMD(TypeHandle ownerType, MethodDesc *pMD)
+DispatchSlot MethodTable::FindDispatchSlotForInterfaceMD(TypeHandle ownerType, MethodDesc *pMD, BOOL throwOnConflict)
{
WRAPPER_NO_CONTRACT;
CONSISTENCY_CHECK(!ownerType.IsNull());
CONSISTENCY_CHECK(CheckPointer(pMD));
CONSISTENCY_CHECK(pMD->IsInterface());
- return FindDispatchSlot(ownerType.GetMethodTable()->GetTypeID(), pMD->GetSlot());
+ return FindDispatchSlot(ownerType.GetMethodTable()->GetTypeID(), pMD->GetSlot(), throwOnConflict);
}
//==========================================================================================
@@ -9859,7 +9876,7 @@ MethodTable::TryResolveConstraintMethodApprox(
thInterfaceType.AsMethodTable()->GetCanonicalMethodTable())
{
cPotentialMatchingInterfaces++;
- pMD = pCanonMT->GetMethodDescForInterfaceMethod(thPotentialInterfaceType, pGenInterfaceMD);
+ pMD = pCanonMT->GetMethodDescForInterfaceMethod(thPotentialInterfaceType, pGenInterfaceMD, FALSE /* throwOnConflict */);
// See code:#TryResolveConstraintMethodApprox_DoNotReturnParentMethod
if ((pMD != NULL) && !pMD->GetMethodTable()->IsValueType())
@@ -9890,9 +9907,8 @@ MethodTable::TryResolveConstraintMethodApprox(
if (this->CanCastToInterface(pInterfaceMT))
{
// We can resolve to exact method
- pMD = this->GetMethodDescForInterfaceMethod(pInterfaceMT, pInterfaceMD);
- _ASSERTE(pMD != NULL);
- fIsExactMethodResolved = TRUE;
+ pMD = this->GetMethodDescForInterfaceMethod(pInterfaceMT, pInterfaceMD, FALSE /* throwOnConflict */);
+ fIsExactMethodResolved = pMD != NULL;
}
}
@@ -9910,7 +9926,7 @@ MethodTable::TryResolveConstraintMethodApprox(
// lookup at runtime, or when not sharing generic code).
if (pCanonMT->CanCastToInterface(thInterfaceType.GetMethodTable()))
{
- pMD = pCanonMT->GetMethodDescForInterfaceMethod(thInterfaceType, pGenInterfaceMD);
+ pMD = pCanonMT->GetMethodDescForInterfaceMethod(thInterfaceType, pGenInterfaceMD, FALSE /* throwOnConflict */);
if (pMD == NULL)
{
LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: failed to find method desc for interface method\n"));