Skip to content

Commit b295724

Browse files
authored
Fix spawning static constructors (#3250)
1 parent 68fff31 commit b295724

File tree

1 file changed

+62
-45
lines changed

1 file changed

+62
-45
lines changed

src/CLR/Core/Execution.cpp

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@ bool CLR_RT_ExecutionEngine::SpawnGenericTypeStaticConstructorsHelper(
11131113
record->m_flags &= ~CLR_RT_GenericCctorExecutionRecord::c_Scheduled;
11141114
}
11151115

1116-
// No more generic type .cctors for this assembly - set flag
1116+
// no more generic type .cctors for this assembly - set flag
11171117
assembly->flags |= CLR_RT_Assembly::StaticGenericConstructorsExecuted;
11181118
return false;
11191119
}
@@ -1164,69 +1164,86 @@ void CLR_RT_ExecutionEngine::SpawnStaticConstructor(CLR_RT_Thread *&pCctorThread
11641164
}
11651165
}
11661166

1167-
// first, find the AppDomainAssembly to run. (what about appdomains!!!)
1168-
NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem)
1167+
// keep iterating until no more static constructors can be spawned
1168+
// note that multiple passes may be needed to satisfy all dependencies
1169+
bool anySpawned;
1170+
1171+
do
11691172
{
1170-
// Check if regular static constructors need to be executed
1171-
if ((pASSM->flags & CLR_RT_Assembly::StaticConstructorsExecuted) == 0)
1172-
{
1173-
CLR_RT_MethodDef_Index index;
1174-
index.Set(pASSM->assemblyIndex, 0);
1175-
bool dependenciesSatisfied = true;
1173+
anySpawned = false;
11761174

1177-
// Check that all dependent assemblies have had regular static constructors run
1178-
CLR_RT_AssemblyRef_CrossReference *ar = pASSM->crossReferenceAssemblyRef;
1179-
for (int i = 0; i < pASSM->tablesSize[TBL_AssemblyRef]; i++, ar++)
1175+
NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem)
1176+
{
1177+
// Check if regular static constructors need to be executed
1178+
if ((pASSM->flags & CLR_RT_Assembly::StaticConstructorsExecuted) == 0)
11801179
{
1181-
if ((ar->target->flags & CLR_RT_Assembly::StaticConstructorsExecuted) == 0)
1180+
CLR_RT_MethodDef_Index index;
1181+
index.Set(pASSM->assemblyIndex, 0);
1182+
bool dependenciesSatisfied = true;
1183+
1184+
// Check that all dependent assemblies have had regular static constructors run
1185+
CLR_RT_AssemblyRef_CrossReference *ar = pASSM->crossReferenceAssemblyRef;
1186+
for (int i = 0; i < pASSM->tablesSize[TBL_AssemblyRef]; i++, ar++)
11821187
{
1183-
dependenciesSatisfied = false;
1184-
break;
1188+
if ((ar->target->flags & CLR_RT_Assembly::StaticConstructorsExecuted) == 0)
1189+
{
1190+
dependenciesSatisfied = false;
1191+
break;
1192+
}
11851193
}
1186-
}
11871194

1188-
if (dependenciesSatisfied)
1189-
{
1190-
// Run regular static constructors for this assembly
1191-
if (SpawnStaticConstructorHelper(pASSM, index))
1195+
if (dependenciesSatisfied)
11921196
{
1193-
return;
1197+
if (SpawnStaticConstructorHelper(pASSM, index))
1198+
{
1199+
return;
1200+
}
1201+
1202+
// returned false, meaning it set the flag and there are no more cctors for this assembly.
1203+
// flag that progress was made and we should re-iterate
1204+
anySpawned = true;
11941205
}
1195-
}
1196-
}
11971206

1198-
// Check if generic type static constructors need to be executed
1199-
if ((pASSM->flags & CLR_RT_Assembly::StaticGenericConstructorsExecuted) == 0)
1200-
{
1201-
bool dependenciesSatisfied = true;
1207+
// if there are dependencies not satisfied, just continue to next assembly
1208+
continue;
1209+
}
12021210

1203-
// Check that all dependent assemblies have had regular static constructors run
1204-
CLR_RT_AssemblyRef_CrossReference *ar = pASSM->crossReferenceAssemblyRef;
1205-
for (int i = 0; i < pASSM->tablesSize[TBL_AssemblyRef]; i++, ar++)
1211+
// Check if generic type static constructors need to be executed
1212+
if ((pASSM->flags & CLR_RT_Assembly::StaticGenericConstructorsExecuted) == 0)
12061213
{
1207-
if ((ar->target->flags & CLR_RT_Assembly::StaticConstructorsExecuted) == 0)
1214+
bool dependenciesSatisfied = true;
1215+
1216+
// Check that all dependent assemblies have had regular static constructors run
1217+
CLR_RT_AssemblyRef_CrossReference *ar = pASSM->crossReferenceAssemblyRef;
1218+
for (int i = 0; i < pASSM->tablesSize[TBL_AssemblyRef]; i++, ar++)
12081219
{
1209-
dependenciesSatisfied = false;
1210-
break;
1220+
if ((ar->target->flags & CLR_RT_Assembly::StaticConstructorsExecuted) == 0)
1221+
{
1222+
dependenciesSatisfied = false;
1223+
break;
1224+
}
12111225
}
1212-
}
1213-
1214-
if (dependenciesSatisfied)
1215-
{
1216-
// Run generic type static constructors for this assembly (starting from index 0)
1217-
CLR_RT_TypeSpec_Index startIndex;
1218-
startIndex.Set(pASSM->assemblyIndex, 0);
12191226

1220-
if (SpawnGenericTypeStaticConstructorsHelper(pASSM, startIndex))
1227+
if (dependenciesSatisfied)
12211228
{
1222-
return;
1229+
CLR_RT_TypeSpec_Index startIndex;
1230+
startIndex.Set(pASSM->assemblyIndex, 0);
1231+
1232+
if (SpawnGenericTypeStaticConstructorsHelper(pASSM, startIndex))
1233+
{
1234+
return;
1235+
}
1236+
1237+
// returned false, meaning it set the flag and there are no more generic cctors for this assembly.
1238+
// flag that progress was made and we should re-iterate
1239+
anySpawned = true;
12231240
}
12241241
}
12251242
}
1226-
}
1227-
NANOCLR_FOREACH_ASSEMBLY_END();
1243+
NANOCLR_FOREACH_ASSEMBLY_END();
1244+
1245+
} while (anySpawned);
12281246

1229-
// no more static constructors needed...
12301247
pCctorThread->DestroyInstance();
12311248
}
12321249
#endif // NANOCLR_APPDOMAINS

0 commit comments

Comments
 (0)