diff --git a/src/coreclr/vm/class.cpp b/src/coreclr/vm/class.cpp index 1a37e2346b0dbe..7fb8b2db0ad01c 100644 --- a/src/coreclr/vm/class.cpp +++ b/src/coreclr/vm/class.cpp @@ -692,6 +692,10 @@ HRESULT EEClass::AddMethod(MethodTable* pMT, mdMethodDef methodDef, MethodDesc** } // If the type is generic, then we need to update all existing instantiated types + // + // This code contains a race condition bug. Types that began loading before the metadata edit + // and are still loading at this point may not get updated. We assume that this issue does not + // have a meaningful impact on overall metadata update reliability. if (pMT->IsGenericTypeDefinition()) { LOG((LF_ENC, LL_INFO100, "EEClass::AddMethod Looking for existing instantiations in all assemblies\n")); @@ -705,23 +709,33 @@ HRESULT EEClass::AddMethod(MethodTable* pMT, mdMethodDef methodDef, MethodDesc** Module* pMod = pAssembly->GetModule(); LOG((LF_ENC, LL_INFO100, "EEClass::AddMethod Checking: %s mod:%p\n", pMod->GetDebugName(), pMod)); - EETypeHashTable* paramTypes = pMod->GetAvailableParamTypes(); - CrstHolder ch(pMod->GetClassLoader()->GetAvailableTypesLock()); - - EETypeHashTable::Iterator it(paramTypes); - EETypeHashEntry* pEntry; - while (paramTypes->FindNext(&it, &pEntry)) + InlineSArray instantiations; { - TypeHandle th = pEntry->GetTypeHandle(); - if (th.IsTypeDesc()) - continue; + EETypeHashTable* paramTypes = pMod->GetAvailableParamTypes(); + CrstHolder ch(pMod->GetClassLoader()->GetAvailableTypesLock()); - // Only update instantiations of the generic MethodTable we updated above. - MethodTable* pMTMaybe = th.AsMethodTable(); - if (!pMTMaybe->IsCanonicalMethodTable() || !pMT->HasSameTypeDefAs(pMTMaybe)) + EETypeHashTable::Iterator it(paramTypes); + EETypeHashEntry* pEntry; + while (paramTypes->FindNext(&it, &pEntry)) { - continue; + TypeHandle th = pEntry->GetTypeHandle(); + if (th.IsTypeDesc()) + continue; + + // Only update instantiations of the generic MethodTable we updated above. + MethodTable* pMTMaybe = th.AsMethodTable(); + if (!pMTMaybe->IsCanonicalMethodTable() || !pMT->HasSameTypeDefAs(pMTMaybe)) + { + continue; + } + + instantiations.Append(pMTMaybe); } + } + + for (COUNT_T i = 0; i < instantiations.GetCount(); i++) + { + MethodTable* pMTMaybe = instantiations[i]; // Create a primary MethodDesc on this instantiation. MethodDesc* pNewMDUnused;