From 9fb6e818cda2e4364e085fe0b8ecebed97db9596 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Tue, 29 Jun 2021 09:43:48 -0700 Subject: [PATCH] Handle marker types with more than 1 generic argument correctly when they must be materialized into full types (#54875) --- src/coreclr/vm/methodtable.cpp | 8 ++++++-- src/coreclr/vm/methodtable.h | 2 ++ src/coreclr/vm/methodtablebuilder.cpp | 5 +++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 3539acaf79f14b..a7f41cce5cd07a 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -9820,8 +9820,12 @@ PTR_MethodTable MethodTable::InterfaceMapIterator::GetInterface(MethodTable* pMT MethodTable *pResult = m_pMap->GetMethodTable(); if (pResult->IsSpecialMarkerTypeForGenericCasting()) { - TypeHandle ownerAsInst(pMTOwner); - Instantiation inst(&ownerAsInst, 1); + TypeHandle ownerAsInst[MaxGenericParametersForSpecialMarkerType]; + for (DWORD i = 0; i < MaxGenericParametersForSpecialMarkerType; i++) + ownerAsInst[i] = pMTOwner; + + _ASSERTE(pResult->GetInstantiation().GetNumArgs() <= MaxGenericParametersForSpecialMarkerType); + Instantiation inst(ownerAsInst, pResult->GetInstantiation().GetNumArgs()); pResult = ClassLoader::LoadGenericInstantiationThrowing(pResult->GetModule(), pResult->GetCl(), inst, ClassLoader::LoadTypes, loadLevel).AsMethodTable(); if (pResult->IsFullyLoaded()) SetInterface(pResult); diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 3fbc6826ed2c6e..476a1cd3faab87 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -1254,6 +1254,8 @@ class MethodTable return IsGenericTypeDefinition(); } + static const DWORD MaxGenericParametersForSpecialMarkerType = 8; + static BOOL ComputeContainsGenericVariables(Instantiation inst); inline void SetContainsGenericVariables() diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 0d372a4659b6c6..89926ffdaae020 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -9147,8 +9147,9 @@ MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT) if (uninstGenericCase && pItfPossiblyApprox->HasInstantiation() && pItfPossiblyApprox->ContainsGenericVariables()) { // We allow a limited set of interface generic shapes with type variables. In particular, we require the - // instantiations to be exactly simple type variables - if (InstantiationIsAllTypeVariables(pItfPossiblyApprox->GetInstantiation())) + // instantiations to be exactly simple type variables, and to have a relatively small number of generic arguments + // so that the fallback instantiating logic works efficiently + if (InstantiationIsAllTypeVariables(pItfPossiblyApprox->GetInstantiation()) && pItfPossiblyApprox->GetInstantiation().GetNumArgs() <= MethodTable::MaxGenericParametersForSpecialMarkerType) { pItfPossiblyApprox = ClassLoader::LoadTypeDefThrowing(pItfPossiblyApprox->GetModule(), pItfPossiblyApprox->GetCl(), ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef, 0, CLASS_LOAD_EXACTPARENTS).AsMethodTable(); }