summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/vm/comcallablewrapper.cpp5
-rw-r--r--src/vm/comdelegate.cpp4
-rw-r--r--src/vm/custommarshalerinfo.cpp15
-rw-r--r--src/vm/dispatchinfo.cpp6
-rw-r--r--src/vm/jitinterface.cpp22
-rw-r--r--src/vm/methodtable.cpp68
-rw-r--r--src/vm/methodtable.h18
-rw-r--r--src/vm/runtimehandles.cpp2
-rw-r--r--src/vm/virtualcallstub.cpp35
-rw-r--r--src/vm/virtualcallstub.h5
10 files changed, 98 insertions, 82 deletions
diff --git a/src/vm/comcallablewrapper.cpp b/src/vm/comcallablewrapper.cpp
index 36208244a8..06a99e1c2f 100644
--- a/src/vm/comcallablewrapper.cpp
+++ b/src/vm/comcallablewrapper.cpp
@@ -4678,7 +4678,7 @@ BOOL ComMethodTable::LayOutInterfaceMethodTable(MethodTable* pClsMT)
}
else if (pClsMT != NULL)
{
- DispatchSlot impl(pClsMT->FindDispatchSlotForInterfaceMD(pIntfMD));
+ DispatchSlot impl(pClsMT->FindDispatchSlotForInterfaceMD(pIntfMD, FALSE /* throwOnConflict */));
pClassMD = impl.GetMethodDesc();
}
@@ -6494,7 +6494,8 @@ MethodDesc * ComCallWrapperTemplate::GetICustomQueryInterfaceGetInterfaceMD()
if (m_pICustomQueryInterfaceGetInterfaceMD == NULL)
m_pICustomQueryInterfaceGetInterfaceMD = m_thClass.GetMethodTable()->GetMethodDescForInterfaceMethod(
- MscorlibBinder::GetMethod(METHOD__ICUSTOM_QUERYINTERFACE__GET_INTERFACE));
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_QUERYINTERFACE__GET_INTERFACE),
+ TRUE /* throwOnConflict */);
RETURN m_pICustomQueryInterfaceGetInterfaceMD;
}
diff --git a/src/vm/comdelegate.cpp b/src/vm/comdelegate.cpp
index 124ebc4c6d..6ffa26709c 100644
--- a/src/vm/comdelegate.cpp
+++ b/src/vm/comdelegate.cpp
@@ -1663,7 +1663,7 @@ FCIMPL3(PCODE, COMDelegate::AdjustTarget, Object* refThisUNSAFE, Object* targetU
// <TODO>it looks like we need to pass an ownerType in here.
// Why can we take a delegate to an interface method anyway? </TODO>
//
- pCorrectedMethod = pMTTarg->FindDispatchSlotForInterfaceMD(pCorrectedMethod).GetMethodDesc();
+ pCorrectedMethod = pMTTarg->FindDispatchSlotForInterfaceMD(pCorrectedMethod, TRUE /* throwOnConflict */).GetMethodDesc();
_ASSERTE(pCorrectedMethod != NULL);
}
}
@@ -1836,7 +1836,7 @@ FCIMPL3(void, COMDelegate::DelegateConstruct, Object* refThisUNSAFE, Object* tar
// <TODO>it looks like we need to pass an ownerType in here.
// Why can we take a delegate to an interface method anyway? </TODO>
//
- MethodDesc * pDispatchSlotMD = pMTTarg->FindDispatchSlotForInterfaceMD(pMeth).GetMethodDesc();
+ MethodDesc * pDispatchSlotMD = pMTTarg->FindDispatchSlotForInterfaceMD(pMeth, TRUE /* throwOnConflict */).GetMethodDesc();
if (pDispatchSlotMD == NULL)
{
COMPlusThrow(kArgumentException, W("Arg_DlgtTargMeth"));
diff --git a/src/vm/custommarshalerinfo.cpp b/src/vm/custommarshalerinfo.cpp
index f9cb61296d..7201e106b8 100644
--- a/src/vm/custommarshalerinfo.cpp
+++ b/src/vm/custommarshalerinfo.cpp
@@ -294,24 +294,29 @@ MethodDesc *CustomMarshalerInfo::GetCustomMarshalerMD(EnumCustomMarshalerMethods
{
case CustomMarshalerMethods_MarshalNativeToManaged:
pMD = pMT->GetMethodDescForInterfaceMethod(
- MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__MARSHAL_NATIVE_TO_MANAGED));
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__MARSHAL_NATIVE_TO_MANAGED),
+ TRUE /* throwOnConflict */);
break;
case CustomMarshalerMethods_MarshalManagedToNative:
pMD = pMT->GetMethodDescForInterfaceMethod(
- MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__MARSHAL_MANAGED_TO_NATIVE));
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__MARSHAL_MANAGED_TO_NATIVE),
+ TRUE /* throwOnConflict */);
break;
case CustomMarshalerMethods_CleanUpNativeData:
pMD = pMT->GetMethodDescForInterfaceMethod(
- MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__CLEANUP_NATIVE_DATA));
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__CLEANUP_NATIVE_DATA),
+ TRUE /* throwOnConflict */);
break;
case CustomMarshalerMethods_CleanUpManagedData:
pMD = pMT->GetMethodDescForInterfaceMethod(
- MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__CLEANUP_MANAGED_DATA));
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__CLEANUP_MANAGED_DATA),
+ TRUE /* throwOnConflict */);
break;
case CustomMarshalerMethods_GetNativeDataSize:
pMD = pMT->GetMethodDescForInterfaceMethod(
- MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__GET_NATIVE_DATA_SIZE));
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__GET_NATIVE_DATA_SIZE),
+ TRUE /* throwOnConflict */);
break;
case CustomMarshalerMethods_GetInstance:
// Must look this up by name since it's static
diff --git a/src/vm/dispatchinfo.cpp b/src/vm/dispatchinfo.cpp
index 393c2aaf95..fe79ac6260 100644
--- a/src/vm/dispatchinfo.cpp
+++ b/src/vm/dispatchinfo.cpp
@@ -2702,7 +2702,7 @@ MethodDesc* DispatchInfo::GetCustomAttrProviderMD(TypeHandle hndCustomAttrProvid
CONTRACT_END;
MethodTable *pMT = hndCustomAttrProvider.AsMethodTable();
- MethodDesc *pMD = pMT->GetMethodDescForInterfaceMethod(MscorlibBinder::GetMethod(METHOD__ICUSTOM_ATTR_PROVIDER__GET_CUSTOM_ATTRIBUTES));
+ MethodDesc *pMD = pMT->GetMethodDescForInterfaceMethod(MscorlibBinder::GetMethod(METHOD__ICUSTOM_ATTR_PROVIDER__GET_CUSTOM_ATTRIBUTES), TRUE /* throwOnConflict */);
// Return the specified method desc.
RETURN pMD;
@@ -3542,7 +3542,7 @@ MethodDesc* DispatchExInfo::GetIReflectMD(BinderMethodID Method)
CONTRACT_END;
MethodTable *pMT = m_pSimpleWrapperOwner->GetMethodTable();
- MethodDesc *pMD = pMT->GetMethodDescForInterfaceMethod(MscorlibBinder::GetMethod(Method));
+ MethodDesc *pMD = pMT->GetMethodDescForInterfaceMethod(MscorlibBinder::GetMethod(Method), TRUE /* throwOnConflict */);
// Return the specified method desc.
RETURN pMD;
@@ -3562,7 +3562,7 @@ MethodDesc* DispatchExInfo::GetIExpandoMD(BinderMethodID Method)
CONTRACT_END;
MethodTable *pMT = m_pSimpleWrapperOwner->GetMethodTable();
- MethodDesc *pMD = pMT->GetMethodDescForInterfaceMethod(MscorlibBinder::GetMethod(Method));
+ MethodDesc *pMD = pMT->GetMethodDescForInterfaceMethod(MscorlibBinder::GetMethod(Method), TRUE /* throwOnConflict */);
// Return the specified method desc.
RETURN pMD;
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp
index 4423c98f8a..51ab2cecab 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -8850,29 +8850,11 @@ CORINFO_METHOD_HANDLE CEEInfo::resolveVirtualMethodHelper(CORINFO_METHOD_HANDLE
pOwnerMT = pOwnerMT->GetCanonicalMethodTable();
}
- // In a try block because the interface method resolution might end up being
- // ambiguous (diamond inheritance case of default interface methods).
- EX_TRY
- {
- pDevirtMD = pDerivedMT->GetMethodDescForInterfaceMethod(TypeHandle(pOwnerMT), pBaseMD);
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(RethrowTransientExceptions)
+ pDevirtMD = pDerivedMT->GetMethodDescForInterfaceMethod(TypeHandle(pOwnerMT), pBaseMD, FALSE /* throwOnConflict */);
}
else if (!pBaseMD->HasClassOrMethodInstantiation())
{
- // In a try block because the interface method resolution might end up being
- // ambiguous (diamond inheritance case of default interface methods).
- EX_TRY
- {
- pDevirtMD = pDerivedMT->GetMethodDescForInterfaceMethod(pBaseMD);
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(RethrowTransientExceptions)
+ pDevirtMD = pDerivedMT->GetMethodDescForInterfaceMethod(pBaseMD, FALSE /* throwOnConflict */);
}
if (pDevirtMD == nullptr)
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"));
diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h
index 9b78ddade5..2367d38c6b 100644
--- a/src/vm/methodtable.h
+++ b/src/vm/methodtable.h
@@ -2200,8 +2200,8 @@ public:
BOOL ImplementsInterface(MethodTable *pInterface);
BOOL ImplementsEquivalentInterface(MethodTable *pInterface);
- MethodDesc *GetMethodDescForInterfaceMethod(TypeHandle ownerType, MethodDesc *pInterfaceMD);
- MethodDesc *GetMethodDescForInterfaceMethod(MethodDesc *pInterfaceMD); // You can only use this one for non-generic interfaces
+ MethodDesc *GetMethodDescForInterfaceMethod(TypeHandle ownerType, MethodDesc *pInterfaceMD, BOOL throwOnConflict);
+ MethodDesc *GetMethodDescForInterfaceMethod(MethodDesc *pInterfaceMD, BOOL throwOnConflict); // You can only use this one for non-generic interfaces
//-------------------------------------------------------------------
// INTERFACE MAP.
@@ -2453,26 +2453,28 @@ public:
BOOL FindDispatchImpl(
UINT32 typeID,
UINT32 slotNumber,
- DispatchSlot * pImplSlot);
+ DispatchSlot * pImplSlot,
+ BOOL throwOnConflict);
#ifndef DACCESS_COMPILE
BOOL FindDefaultInterfaceImplementation(
MethodDesc *pInterfaceMD,
MethodTable *pObjectMT,
- MethodDesc **ppDefaultMethod);
+ MethodDesc **ppDefaultMethod,
+ BOOL throwOnConflict);
#endif // DACCESS_COMPILE
- DispatchSlot FindDispatchSlot(UINT32 typeID, UINT32 slotNumber);
+ DispatchSlot FindDispatchSlot(UINT32 typeID, UINT32 slotNumber, BOOL throwOnConflict);
- DispatchSlot FindDispatchSlot(DispatchToken tok);
+ DispatchSlot FindDispatchSlot(DispatchToken tok, BOOL throwOnConflict);
// You must use the second of these two if there is any chance the pMD is a method
// on a generic interface such as IComparable<T> (which it normally can be). The
// ownerType is used to provide an exact qualification in the case the pMD is
// a shared method descriptor.
- DispatchSlot FindDispatchSlotForInterfaceMD(MethodDesc *pMD);
- DispatchSlot FindDispatchSlotForInterfaceMD(TypeHandle ownerType, MethodDesc *pMD);
+ DispatchSlot FindDispatchSlotForInterfaceMD(MethodDesc *pMD, BOOL throwOnConflict);
+ DispatchSlot FindDispatchSlotForInterfaceMD(TypeHandle ownerType, MethodDesc *pMD, BOOL throwOnConflict);
MethodDesc *ReverseInterfaceMDLookup(UINT32 slotNumber);
diff --git a/src/vm/runtimehandles.cpp b/src/vm/runtimehandles.cpp
index a8a2d31950..913ca1f555 100644
--- a/src/vm/runtimehandles.cpp
+++ b/src/vm/runtimehandles.cpp
@@ -1179,7 +1179,7 @@ MethodDesc* QCALLTYPE RuntimeTypeHandle::GetInterfaceMethodImplementation(Enregi
// with at least an abstract method. b19897_GetInterfaceMap_Abstract.exe tests this case.
//@TODO:STUBDISPATCH: Don't need to track down the implementation, just the declaration, and this can
//@TODO: be done faster - just need to make a function FindDispatchDecl.
- DispatchSlot slot(typeHandle.GetMethodTable()->FindDispatchSlotForInterfaceMD(thOwnerOfMD, pMD));
+ DispatchSlot slot(typeHandle.GetMethodTable()->FindDispatchSlotForInterfaceMD(thOwnerOfMD, pMD, TRUE /* throwOnConflict */));
if (!slot.IsNull())
pResult = slot.GetMethodDesc();
diff --git a/src/vm/virtualcallstub.cpp b/src/vm/virtualcallstub.cpp
index 78a37483b5..c6fa8528d3 100644
--- a/src/vm/virtualcallstub.cpp
+++ b/src/vm/virtualcallstub.cpp
@@ -1911,7 +1911,7 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite,
if (target == NULL)
{
CONSISTENCY_CHECK(stub == CALL_STUB_EMPTY_ENTRY);
- patch = Resolver(objectType, token, protectedObj, &target);
+ patch = Resolver(objectType, token, protectedObj, &target, TRUE /* throwOnConflict */);
#if defined(_DEBUG)
if ( !objectType->IsComObjectType() &&
@@ -2196,7 +2196,8 @@ VirtualCallStubManager::Resolver(
MethodTable * pMT,
DispatchToken token,
OBJECTREF * protectedObj, // this one can actually be NULL, consider using pMT is you don't need the object itself
- PCODE * ppTarget)
+ PCODE * ppTarget,
+ BOOL throwOnConflict)
{
CONTRACTL {
THROWS;
@@ -2211,7 +2212,7 @@ VirtualCallStubManager::Resolver(
if (token.IsTypedToken())
{
dbg_pTokenMT = GetThread()->GetDomain()->LookupType(token.GetTypeID());
- dbg_pTokenMD = dbg_pTokenMT->FindDispatchSlot(token.GetSlotNumber()).GetMethodDesc();
+ dbg_pTokenMD = dbg_pTokenMT->FindDispatchSlot(token.GetSlotNumber(), throwOnConflict).GetMethodDesc();
}
#endif // _DEBUG
@@ -2226,7 +2227,7 @@ VirtualCallStubManager::Resolver(
MethodDesc * pMD = NULL;
BOOL fShouldPatch = FALSE;
- DispatchSlot implSlot(pMT->FindDispatchSlot(token));
+ DispatchSlot implSlot(pMT->FindDispatchSlot(token, throwOnConflict));
// If we found a target, then just figure out if we're allowed to create a stub around
// this target and backpatch the callsite.
@@ -2310,7 +2311,7 @@ VirtualCallStubManager::Resolver(
else if (pMT->IsComObjectType() && IsInterfaceToken(token))
{
MethodTable * pItfMT = GetTypeFromToken(token);
- implSlot = pItfMT->FindDispatchSlot(token.GetSlotNumber());
+ implSlot = pItfMT->FindDispatchSlot(token.GetSlotNumber(), throwOnConflict);
if (pItfMT->HasInstantiation())
{
@@ -2370,7 +2371,7 @@ VirtualCallStubManager::Resolver(
TypeHandle resulTypeHnd = resultTypeObj->GetType();
MethodTable *pResultMT = resulTypeHnd.GetMethodTable();
- return Resolver(pResultMT, token, protectedObj, ppTarget);
+ return Resolver(pResultMT, token, protectedObj, ppTarget, throwOnConflict);
}
#endif // FEATURE_ICASTABLE
@@ -2381,7 +2382,7 @@ VirtualCallStubManager::Resolver(
if (token.IsTypedToken())
{
pTokenMT = GetThread()->GetDomain()->LookupType(token.GetTypeID());
- pTokenMD = pTokenMT->FindDispatchSlot(token.GetSlotNumber()).GetMethodDesc();
+ pTokenMD = pTokenMT->FindDispatchSlot(token.GetSlotNumber(), throwOnConflict).GetMethodDesc();
}
#ifdef FEATURE_COMINTEROP
@@ -2395,6 +2396,13 @@ VirtualCallStubManager::Resolver(
}
else
#endif // FEATURE_COMINTEROP
+ if (!throwOnConflict)
+ {
+ // Assume we got null because there was a default interface method conflict
+ *ppTarget = NULL;
+ return FALSE;
+ }
+ else
{
// Method not found, and this should never happen for anything but equivalent types
CONSISTENCY_CHECK(!implSlot.IsNull() && "Valid method implementation was not found.");
@@ -2532,7 +2540,8 @@ PCODE VirtualCallStubManager::CacheLookup(size_t token, UINT16 tokenHash, Method
PCODE
VirtualCallStubManager::GetTarget(
DispatchToken token,
- MethodTable * pMT)
+ MethodTable * pMT,
+ BOOL throwOnConflict)
{
CONTRACTL {
THROWS;
@@ -2563,8 +2572,8 @@ VirtualCallStubManager::GetTarget(
// TODO: passing NULL as protectedObj here can lead to incorrect behavior for ICastable objects
// We need to review if this is the case and refactor this code if we want ICastable to become officially supported
- fPatch = Resolver(pMT, token, NULL, &target);
- _ASSERTE(target != NULL);
+ fPatch = Resolver(pMT, token, NULL, &target, throwOnConflict);
+ _ASSERTE(!throwOnConflict || target != NULL);
#ifndef STUB_DISPATCH_PORTABLE
if (fPatch)
@@ -2624,13 +2633,13 @@ VirtualCallStubManager::TraceResolver(
CONSISTENCY_CHECK(CheckPointer(pMT));
- DispatchSlot slot(pMT->FindDispatchSlot(token));
+ DispatchSlot slot(pMT->FindDispatchSlot(token, TRUE /* throwOnConflict */));
if (slot.IsNull() && IsInterfaceToken(token) && pMT->IsComObjectType())
{
MethodDesc * pItfMD = GetInterfaceMethodDescFromToken(token);
CONSISTENCY_CHECK(pItfMD->GetMethodTable()->GetSlot(pItfMD->GetSlot()) == pItfMD->GetMethodEntryPoint());
- slot = pItfMD->GetMethodTable()->FindDispatchSlot(pItfMD->GetSlot());
+ slot = pItfMD->GetMethodTable()->FindDispatchSlot(pItfMD->GetSlot(), TRUE /* throwOnConflict */);
}
return (StubManager::TraceStub(slot.GetTarget(), trace));
@@ -4148,7 +4157,7 @@ MethodDesc *VirtualCallStubManagerManager::Entry2MethodDesc(
PCODE target = NULL;
// TODO: passing NULL as protectedObj here can lead to incorrect behavior for ICastable objects
// We need to review if this is the case and refactor this code if we want ICastable to become officially supported
- VirtualCallStubManager::Resolver(pMT, token, NULL, &target);
+ VirtualCallStubManager::Resolver(pMT, token, NULL, &target, TRUE /* throwOnConflict */);
return pMT->GetMethodDescForSlotAddress(target);
}
diff --git a/src/vm/virtualcallstub.h b/src/vm/virtualcallstub.h
index 1d22e467c4..360f04a7df 100644
--- a/src/vm/virtualcallstub.h
+++ b/src/vm/virtualcallstub.h
@@ -539,7 +539,8 @@ private:
static BOOL Resolver(MethodTable * pMT,
DispatchToken token,
OBJECTREF * protectedObj,
- PCODE * ppTarget);
+ PCODE * ppTarget,
+ BOOL throwOnConflict);
// This can be used to find a target without needing the ability to throw
static BOOL TraceResolver(Object *pObj, DispatchToken token, TraceDestination *trace);
@@ -561,7 +562,7 @@ public:
static PCODE CacheLookup(size_t token, UINT16 tokenHash, MethodTable *pMT);
// Full exhaustive lookup. THROWS, GC_TRIGGERS
- static PCODE GetTarget(DispatchToken token, MethodTable *pMT);
+ static PCODE GetTarget(DispatchToken token, MethodTable *pMT, BOOL throwOnConflict);
private:
// Given a dispatch token, return true if the token represents an interface, false if just a slot.