Skip to content

Commit c2435c3

Browse files
author
Mirroring
committed
Merge commit 'd7ba761c7b1623388cd2e0f4ea8cc48e0d193335'
2 parents 7adb846 + d7ba761 commit c2435c3

File tree

10 files changed

+400
-15
lines changed

10 files changed

+400
-15
lines changed

src/runtime/src/coreclr/vm/clsload.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4660,6 +4660,22 @@ BOOL ClassLoader::CanAccessFamily(
46604660

46614661
#endif // #ifndef DACCESS_COMPILE
46624662

4663+
bool ClassLoader::EligibleForSpecialMarkerTypeUsage(Instantiation inst, MethodTable* pOwnerMT)
4664+
{
4665+
LIMITED_METHOD_DAC_CONTRACT;
4666+
4667+
if (pOwnerMT == NULL)
4668+
return false;
4669+
4670+
if (inst.GetNumArgs() > MethodTable::MaxGenericParametersForSpecialMarkerType)
4671+
return false;
4672+
4673+
if (!inst.ContainsAllOneType(pOwnerMT->GetSpecialInstantiationType()))
4674+
return false;
4675+
4676+
return true;
4677+
}
4678+
46634679
#ifdef DACCESS_COMPILE
46644680

46654681
void

src/runtime/src/coreclr/vm/clsload.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,8 @@ class ClassLoader
10041004
TypeHandle typeHnd,
10051005
ClassLoadLevel targetLevel);
10061006
#endif //!DACCESS_COMPILE
1007+
public:
1008+
static bool EligibleForSpecialMarkerTypeUsage(Instantiation inst, MethodTable* pOwnerMT);
10071009

10081010
}; // class ClassLoader
10091011

src/runtime/src/coreclr/vm/methodtablebuilder.cpp

Lines changed: 100 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9652,8 +9652,6 @@ MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
96529652
break;
96539653
}
96549654

9655-
bool uninstGenericCase = !retryWithExactInterfaces && pNewIntfMT->IsSpecialMarkerTypeForGenericCasting();
9656-
96579655
duplicates |= InsertMethodTable(pNewIntfMT, pExactMTs, nInterfacesCount, &nAssigned);
96589656

96599657
// We have a special algorithm for interface maps in CoreLib, which doesn't expand interfaces, and assumes no ambiguous
@@ -9663,23 +9661,112 @@ MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
96639661
MethodTable::InterfaceMapIterator intIt = pNewIntfMT->IterateInterfaceMap();
96649662
while (intIt.Next())
96659663
{
9666-
MethodTable *pItfPossiblyApprox = intIt.GetInterfaceApprox();
9667-
if (uninstGenericCase && pItfPossiblyApprox->HasInstantiation() && pItfPossiblyApprox->ContainsGenericVariables())
9664+
if (retryWithExactInterfaces)
96689665
{
9669-
// We allow a limited set of interface generic shapes with type variables. In particular, we require the
9670-
// instantiations to be exactly simple type variables, and to have a relatively small number of generic arguments
9671-
// so that the fallback instantiating logic works efficiently
9672-
if (InstantiationIsAllTypeVariables(pItfPossiblyApprox->GetInstantiation()) && pItfPossiblyApprox->GetInstantiation().GetNumArgs() <= MethodTable::MaxGenericParametersForSpecialMarkerType)
9666+
duplicates |= InsertMethodTable(intIt.GetInterface(pNewIntfMT, CLASS_LOAD_EXACTPARENTS), pExactMTs, nInterfacesCount, &nAssigned);
9667+
}
9668+
else
9669+
{
9670+
MethodTable *pItfPossiblyApprox = intIt.GetInterfaceApprox();
9671+
9672+
// pItfPossiblyApprox can be in 4 situations
9673+
// 1. It has no instantiation
9674+
// 2. It is a special marker type, AND pNewItfMT is a special marker type. Compute the exact instantiation as containing entirely a list of types corresponding to calling GetSpecialInstantiationType on pMT (This rule works based on the current behavior of GetSpecialInstantiationType where it treats all interfaces the same)
9675+
// 3. It is a special marker type, but pNewItfMT is NOT a special marker type. Compute the exact instantiation as containing entirely a list of types corresponding to calling GetSpecialInstantiationType on pNewItfMT
9676+
// 4. It is an exact instantiation
9677+
//
9678+
// NOTE: pItfPossiblyApprox must not be considered a special marker type if pNewItfMT has the MayHaveOpenInterfacesInInterfaceMap flag set
9679+
//
9680+
// Then determine if all of the following conditions hold true.
9681+
// 1. All generic arguments are the same (always true for cases 2 and 3 above)
9682+
// 2. The first generic argument in the instantiation is exactly the value of calling GetSpecialInstantiationType on pMT (always true for case 2)
9683+
//
9684+
// If so, then we should insert the special marker type
9685+
// Otherwise, we should insert the exact instantiation of the interface
9686+
// HOWEVER: If the exact instantiation IS a special marker interface, we need to retry with exact interfaces to avoid ambiguity situations
9687+
//
9688+
// NOTE: This is also part of the logic which determines if we need to call SetMayHaveOpenInterfacesInInterfaceMap. The CLR type system has a bug in its structure
9689+
// such that if you attempt to instantiate a type over its own type parameter from the open type, we will load the GenericTypeDefinition instead of loading
9690+
// a type explicitly instantiated over those type parameters. We re-use the GenericTypeDefinition as the special marker type, which leads to a conflict
9691+
// when something like that happens. So, we need to detect when something like that happens, and set the MayHaveOpenInterfacesInInterfaceMap flag,
9692+
// and avoid using the special marker type in those situations.
9693+
MethodTable *pItfToInsert = NULL;
9694+
bool intendedExactMatch = false;
9695+
9696+
if (!pItfPossiblyApprox->HasInstantiation())
9697+
{
9698+
// case 1
9699+
pItfToInsert = pItfPossiblyApprox;
9700+
intendedExactMatch = true;
9701+
}
9702+
else if (pItfPossiblyApprox->IsSpecialMarkerTypeForGenericCasting() && !pNewIntfMT->GetAuxiliaryData()->MayHaveOpenInterfacesInInterfaceMap())
96739703
{
9674-
pItfPossiblyApprox = ClassLoader::LoadTypeDefThrowing(pItfPossiblyApprox->GetModule(), pItfPossiblyApprox->GetCl(), ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef, 0, CLASS_LOAD_EXACTPARENTS).AsMethodTable();
9704+
// We are in case 2 or 3 above
9705+
bool pNewIntfMTIsSpecialMarkerType = pNewIntfMT->IsSpecialMarkerTypeForGenericCasting() && !pMT->GetAuxiliaryData()->MayHaveOpenInterfacesInInterfaceMap();
9706+
if (pNewIntfMTIsSpecialMarkerType)
9707+
{
9708+
// case 2
9709+
pItfToInsert = pItfPossiblyApprox; // We have the special marker type already, so this is what we insert
9710+
}
9711+
else
9712+
{
9713+
// case 3
9714+
bool mustUseSpecialMarkerType = pNewIntfMT->GetSpecialInstantiationType() == pMT->GetSpecialInstantiationType();
9715+
if (mustUseSpecialMarkerType)
9716+
{
9717+
pItfToInsert = pItfPossiblyApprox; // We have the special marker type already, so this is what we insert
9718+
}
9719+
else
9720+
{
9721+
pItfToInsert = intIt.GetInterface(pNewIntfMT, CLASS_LOAD_EXACTPARENTS);
9722+
intendedExactMatch = true;
9723+
}
9724+
}
96759725
}
96769726
else
96779727
{
9678-
retry = true;
9679-
break;
9728+
// case 4 (We have an exact interface)
9729+
if (ClassLoader::EligibleForSpecialMarkerTypeUsage(pItfPossiblyApprox->GetInstantiation(), pMT))
9730+
{
9731+
// Validated that all generic arguments are the same, and that the first generic argument in the instantiation is exactly the value of calling GetSpecialInstantiationType on pMT
9732+
// Then use the special marker type here
9733+
pItfToInsert = ClassLoader::LoadTypeDefThrowing(pItfPossiblyApprox->GetModule(), pItfPossiblyApprox->GetCl(), ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef, 0, CLASS_LOAD_EXACTPARENTS).AsMethodTable();
9734+
}
9735+
else
9736+
{
9737+
pItfToInsert = pItfPossiblyApprox;
9738+
intendedExactMatch = true;
9739+
}
96809740
}
9741+
9742+
if (pItfToInsert->IsSpecialMarkerTypeForGenericCasting())
9743+
{
9744+
if (intendedExactMatch)
9745+
{
9746+
// We are trying to insert a special marker type into the interface list, but it is exactly the same as the exact instantiation we should actually want, we need to set the
9747+
// MayHaveOpenInterfacesInInterfaceMap flag, so trigger the retry logic.
9748+
retry = true;
9749+
break;
9750+
}
9751+
else if (pMT->GetSpecialInstantiationType() == pItfToInsert->GetInstantiation()[0])
9752+
{
9753+
// We are trying to insert a special marker type into the interface list, but the first generic argument
9754+
// in the instantiation is exactly the value of calling GetSpecialInstantiationType on pMT.
9755+
// This implies that the special marker type is actually the exact instantiation that we should be using, which
9756+
// will cause the same ambiguity situation as above. Trigger a retry, which will set MayHaveOpenInterfacesInInterfaceMap
9757+
// and disable the special marker type behavior for this type.
9758+
retry = true;
9759+
break;
9760+
}
9761+
}
9762+
9763+
if (!intendedExactMatch)
9764+
{
9765+
_ASSERTE(pItfToInsert->IsSpecialMarkerTypeForGenericCasting());
9766+
}
9767+
9768+
duplicates |= InsertMethodTable(pItfToInsert, pExactMTs, nInterfacesCount, &nAssigned);
96819769
}
9682-
duplicates |= InsertMethodTable(intIt.GetInterface(pNewIntfMT, CLASS_LOAD_EXACTPARENTS), pExactMTs, nInterfacesCount, &nAssigned);
96839770
}
96849771
}
96859772

@@ -9716,7 +9803,7 @@ MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
97169803
_ASSERTE(!duplicates || !(pMT->GetModule()->IsSystem() && (pMT->IsValueType() || pMT->IsInterface())));
97179804

97189805
CONSISTENCY_CHECK(duplicates || (nAssigned == pMT->GetNumInterfaces()));
9719-
if (duplicates)
9806+
if (duplicates || (nAssigned != pMT->GetNumInterfaces()))
97209807
{
97219808
//#LoadExactInterfaceMap_Algorithm2
97229809
// Exact interface instantiation loading TECHNIQUE 2 - The exact instantiation has caused some duplicates to

src/runtime/src/coreclr/vm/siginfo.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,9 +1616,17 @@ TypeHandle SigPointer::GetTypeHandleThrowing(
16161616

16171617
Instantiation genericLoadInst(thisinst, ntypars);
16181618

1619-
if (pMTInterfaceMapOwner != NULL && genericLoadInst.ContainsAllOneType(pMTInterfaceMapOwner->GetSpecialInstantiationType()))
1619+
if (ClassLoader::EligibleForSpecialMarkerTypeUsage(genericLoadInst, pMTInterfaceMapOwner))
16201620
{
16211621
thRet = ClassLoader::LoadTypeDefThrowing(pGenericTypeModule, tkGenericType, ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef, 0, level);
1622+
if (thRet.AsMethodTable()->GetInstantiation()[0] == pMTInterfaceMapOwner->GetSpecialInstantiationType())
1623+
{
1624+
// We loaded the special marker type, but it is ALSO the exact expected type which isn't a valid combination
1625+
// In this case return something else (object) to indicate that
1626+
// we found an invalid situation and this function should be retried without the special marker type logic enabled.
1627+
thRet = TypeHandle(g_pObjectClass);
1628+
break;
1629+
}
16221630
}
16231631
else
16241632
{
@@ -1643,7 +1651,7 @@ TypeHandle SigPointer::GetTypeHandleThrowing(
16431651
// the loaded type is not the expected type we should be looking for to return a special marker type, but the normal load has
16441652
// found a type which claims to be a special marker type. In this case return something else (object) to indicate that
16451653
// we found an invalid situation and this function should be retried without the special marker type logic enabled.
1646-
thRet = TypeHandle(CoreLibBinder::GetElementType(ELEMENT_TYPE_OBJECT));
1654+
thRet = TypeHandle(g_pObjectClass);
16471655
break;
16481656
}
16491657
else if (!handlingRecursiveGenericFieldScenario)

src/runtime/src/coreclr/vm/typehandle.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,7 @@ class Instantiation
691691

692692
bool ContainsAllOneType(TypeHandle th)
693693
{
694+
LIMITED_METHOD_DAC_CONTRACT;
694695
for (DWORD i = GetNumArgs(); i > 0;)
695696
{
696697
if ((*this)[--i] != th)

src/runtime/src/tests/Directory.Build.props

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@
128128
<DefineConstants>$(DefineConstants);DEBUG;TRACE;XUNIT_PERF</DefineConstants>
129129
</PropertyGroup>
130130

131+
<PropertyGroup>
132+
<!-- The SDK for VB.NET requires the DefineConstants variable to be , delimited instead of ; -->
133+
<DefineConstants Condition="'$(MSBuildProjectExtension)' == '.vbproj'">$(DefineConstants.Replace(';',','))</DefineConstants>
134+
</PropertyGroup>
135+
131136
<!-- Setup the default output and intermediate paths -->
132137
<PropertyGroup>
133138
<SkipXunitDependencyCopying>true</SkipXunitDependencyCopying>

0 commit comments

Comments
 (0)