From 4b01ac0d72d2b271a3f664d1fe3761287f5efc6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Thu, 15 Nov 2018 14:08:27 +0100 Subject: Allow supressing exceptions in diamond inheritance cases (#20458) --- src/vm/comcallablewrapper.cpp | 5 ++-- src/vm/comdelegate.cpp | 4 +-- src/vm/custommarshalerinfo.cpp | 15 ++++++---- src/vm/dispatchinfo.cpp | 6 ++-- src/vm/jitinterface.cpp | 22 ++------------ src/vm/methodtable.cpp | 68 ++++++++++++++++++++++++++---------------- src/vm/methodtable.h | 18 ++++++----- src/vm/runtimehandles.cpp | 2 +- src/vm/virtualcallstub.cpp | 35 ++++++++++++++-------- src/vm/virtualcallstub.h | 5 ++-- 10 files changed, 98 insertions(+), 82 deletions(-) (limited to 'src') 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 // it looks like we need to pass an ownerType in here. // Why can we take a delegate to an interface method anyway? // - 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 // it looks like we need to pass an ownerType in here. // Why can we take a delegate to an interface method anyway? // - 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 (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. -- cgit v1.2.3