Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 27 additions & 13 deletions src/coreclr/vm/class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment on lines +696 to +698
if (pMT->IsGenericTypeDefinition())
{
LOG((LF_ENC, LL_INFO100, "EEClass::AddMethod Looking for existing instantiations in all assemblies\n"));
Expand All @@ -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<MethodTable*, 8> instantiations;
{
TypeHandle th = pEntry->GetTypeHandle();
if (th.IsTypeDesc())
continue;
EETypeHashTable* paramTypes = pMod->GetAvailableParamTypes();
CrstHolder ch(pMod->GetClassLoader()->GetAvailableTypesLock());

Comment on lines +712 to 716
// 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++)
Comment on lines +732 to +736
{
MethodTable* pMTMaybe = instantiations[i];

// Create a primary MethodDesc on this instantiation.
MethodDesc* pNewMDUnused;
Expand Down
Loading