Skip to content

Commit 607f74d

Browse files
Add support for statics access from shared generic code, as well as precise-init static class construction (#117110)
* Add support for statics access from shared generic code, as well as precise-init static class construction - There is another renaming of the helpers call opcodes to allow distinguishing between whether or not the arg is supplied via svar or dataindex. - More tests to cover these scenarios - This should finish up the support for shared generics Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent c02569b commit 607f74d

File tree

6 files changed

+214
-23
lines changed

6 files changed

+214
-23
lines changed

src/coreclr/interpreter/compiler.cpp

Lines changed: 98 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,11 +1240,9 @@ InterpCompiler::InterpCompiler(COMP_HANDLE compHnd,
12401240
m_compScopeHnd = methodInfo->scope;
12411241
m_compHnd = compHnd;
12421242
m_methodInfo = methodInfo;
1243-
1244-
#ifdef DEBUG
1245-
12461243
m_classHnd = compHnd->getMethodClass(m_methodHnd);
12471244

1245+
#ifdef DEBUG
12481246
m_methodName = ::PrintMethodName(compHnd, m_classHnd, m_methodHnd, &m_methodInfo->args,
12491247
/* includeAssembly */ false,
12501248
/* includeClass */ true,
@@ -2329,7 +2327,7 @@ void InterpCompiler::EmitPushHelperCall_2(const CorInfoHelpFunc ftn, const CORIN
23292327

23302328
if (handleData.argType == HelperArgType::GenericResolution)
23312329
{
2332-
AddIns(INTOP_CALL_HELPER_P_GP);
2330+
AddIns(INTOP_CALL_HELPER_P_GS);
23332331
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(ftn);
23342332
m_pLastNewIns->data[1] = handleData.dataItemIndex;
23352333

@@ -2338,7 +2336,7 @@ void InterpCompiler::EmitPushHelperCall_2(const CorInfoHelpFunc ftn, const CORIN
23382336
}
23392337
else
23402338
{
2341-
AddIns(INTOP_CALL_HELPER_P_PP);
2339+
AddIns(INTOP_CALL_HELPER_P_PS);
23422340
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(ftn);
23432341
m_pLastNewIns->data[1] = handleData.dataItemIndex;
23442342

@@ -2383,7 +2381,7 @@ void InterpCompiler::EmitPushUnboxAnyNullable(const CORINFO_GENERICHANDLE_RESULT
23832381

23842382
if (handleData.argType == HelperArgType::GenericResolution)
23852383
{
2386-
AddIns(INTOP_CALL_HELPER_V_AGP);
2384+
AddIns(INTOP_CALL_HELPER_V_AGS);
23872385
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(CORINFO_HELP_UNBOX_NULLABLE);
23882386
m_pLastNewIns->data[1] = handleData.dataItemIndex;
23892387

@@ -2392,7 +2390,7 @@ void InterpCompiler::EmitPushUnboxAnyNullable(const CORINFO_GENERICHANDLE_RESULT
23922390
}
23932391
else
23942392
{
2395-
AddIns(INTOP_CALL_HELPER_V_APP);
2393+
AddIns(INTOP_CALL_HELPER_V_APS);
23962394
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(CORINFO_HELP_UNBOX_NULLABLE);
23972395
m_pLastNewIns->data[1] = handleData.dataItemIndex;
23982396

@@ -3079,6 +3077,13 @@ void InterpCompiler::EmitStaticFieldAddress(CORINFO_FIELD_INFO *pFieldInfo, CORI
30793077
case CORINFO_FIELD_STATIC_ADDRESS:
30803078
case CORINFO_FIELD_STATIC_RVA_ADDRESS:
30813079
{
3080+
if ((pFieldInfo->fieldFlags & CORINFO_FLG_FIELD_INITCLASS) != 0)
3081+
{
3082+
CORINFO_GENERICHANDLE_RESULT embedInfo;
3083+
m_compHnd->embedGenericHandle(pResolvedToken, true, m_methodInfo->ftn, &embedInfo);
3084+
EmitPushHelperCall(CORINFO_HELP_INITCLASS, embedInfo, StackTypeI, NULL);
3085+
m_pStackPointer--; // The InitClass helper doesn't actually return anything, so we pop the stack
3086+
}
30823087
// const field address
30833088
assert(pFieldInfo->fieldLookup.accessType == IAT_VALUE);
30843089
AddIns(INTOP_LDPTR);
@@ -3107,6 +3112,17 @@ void InterpCompiler::EmitStaticFieldAddress(CORINFO_FIELD_INFO *pFieldInfo, CORI
31073112
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE:
31083113
helperArg = (void*)m_compHnd->getClassThreadStaticDynamicInfo(pResolvedToken->hClass);
31093114
break;
3115+
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE:
3116+
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE:
3117+
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE:
3118+
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE:
3119+
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR:
3120+
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR:
3121+
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR:
3122+
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR:
3123+
helperArg = (void*)m_compHnd->getClassStaticDynamicInfo(pResolvedToken->hClass);
3124+
break;
3125+
31103126
default:
31113127
// TODO
31123128
assert(0);
@@ -3130,11 +3146,9 @@ void InterpCompiler::EmitStaticFieldAddress(CORINFO_FIELD_INFO *pFieldInfo, CORI
31303146
}
31313147
case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
31323148
{
3133-
AddIns(INTOP_CALL_HELPER_P_P);
3134-
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(pFieldInfo->helper);
3135-
m_pLastNewIns->data[1] = GetDataItemIndex(pResolvedToken->tokenContext);
3136-
PushInterpType(InterpTypeByRef, NULL);
3137-
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
3149+
CORINFO_GENERICHANDLE_RESULT embedInfo;
3150+
m_compHnd->embedGenericHandle(pResolvedToken, true, m_methodInfo->ftn, &embedInfo);
3151+
EmitPushHelperCall(pFieldInfo->helper, embedInfo, StackTypeByRef, NULL);
31383152

31393153
// Add field offset
31403154
m_pStackPointer--;
@@ -3299,6 +3313,73 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
32993313
// adding an opcode.
33003314
AddIns(INTOP_SAFEPOINT);
33013315

3316+
CorInfoInitClassResult initOnFunctionStart = m_compHnd->initClass(NULL, NULL, METHOD_BEING_COMPILED_CONTEXT());
3317+
if ((initOnFunctionStart & CORINFO_INITCLASS_USE_HELPER) == CORINFO_INITCLASS_USE_HELPER)
3318+
{
3319+
// This happens if the method is on a type which is not beforefieldinit,
3320+
// and the type is not initialized at the start of the method.
3321+
3322+
CORINFO_LOOKUP_KIND kind;
3323+
m_compHnd->getLocationOfThisType(m_methodHnd, &kind);
3324+
3325+
if (!kind.needsRuntimeLookup)
3326+
{
3327+
AddIns(INTOP_CALL_HELPER_P_P);
3328+
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(CORINFO_HELP_INITCLASS);
3329+
m_pLastNewIns->data[1] = GetDataItemIndex(m_classHnd);
3330+
PushInterpType(InterpTypeI, NULL);
3331+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
3332+
m_pStackPointer--;
3333+
}
3334+
else
3335+
{
3336+
switch (kind.runtimeLookupKind)
3337+
{
3338+
case CORINFO_LOOKUP_CLASSPARAM:
3339+
AddIns(INTOP_CALL_HELPER_P_S);
3340+
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(CORINFO_HELP_INITCLASS);
3341+
m_pLastNewIns->SetSVar(getParamArgIndex());
3342+
PushInterpType(InterpTypeI, NULL);
3343+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
3344+
m_pStackPointer--;
3345+
break;
3346+
case CORINFO_LOOKUP_THISOBJ:
3347+
{
3348+
AddIns(INTOP_LDIND_I);
3349+
m_pLastNewIns->data[0] = 0; // The offset is 0 for the this pointer
3350+
m_pLastNewIns->SetSVar(getParamArgIndex());
3351+
PushInterpType(InterpTypeI, NULL);
3352+
int thisObjMethodTablePtrVar = m_pStackPointer[-1].var;
3353+
m_pLastNewIns->SetDVar(thisObjMethodTablePtrVar);
3354+
m_pStackPointer--;
3355+
3356+
AddIns(INTOP_CALL_HELPER_P_SP);
3357+
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(CORINFO_HELP_INITINSTCLASS);
3358+
m_pLastNewIns->data[1] = GetDataItemIndex(m_methodHnd);
3359+
m_pLastNewIns->SetSVar(thisObjMethodTablePtrVar);
3360+
PushInterpType(InterpTypeI, NULL);
3361+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
3362+
m_pStackPointer--;
3363+
break;
3364+
}
3365+
case CORINFO_LOOKUP_METHODPARAM:
3366+
{
3367+
AddIns(INTOP_CALL_HELPER_P_PS);
3368+
m_pLastNewIns->data[0] = GetDataItemIndexForHelperFtn(CORINFO_HELP_INITINSTCLASS);
3369+
m_pLastNewIns->data[1] = GetDataItemIndex(0);
3370+
m_pLastNewIns->SetSVar(getParamArgIndex());
3371+
PushInterpType(InterpTypeI, NULL);
3372+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
3373+
m_pStackPointer--;
3374+
break;
3375+
}
3376+
default:
3377+
assert(0);
3378+
break;
3379+
}
3380+
}
3381+
}
3382+
33023383
linkBBlocks = true;
33033384
needsRetryEmit = false;
33043385

@@ -5926,6 +6007,11 @@ void InterpCompiler::PrintInsData(InterpInst *ins, int32_t insOffset, const int3
59266007
PrintClassName(ch);
59276008
break;
59286009
}
6010+
case InterpOpHelperFtnNoArgs:
6011+
{
6012+
PrintHelperFtn((void*)GetDataItemAtIndex(pData[0]));
6013+
break;
6014+
}
59296015
case InterpOpHelperFtn:
59306016
{
59316017
PrintHelperFtn((void*)GetDataItemAtIndex(pData[0]));

src/coreclr/interpreter/compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,8 @@ class InterpCompiler
528528
#endif // DEBUG
529529
}
530530

531-
#ifdef DEBUG
532531
CORINFO_CLASS_HANDLE m_classHnd;
532+
#ifdef DEBUG
533533
TArray<char> m_methodName;
534534
bool m_verbose = false;
535535

src/coreclr/interpreter/intops.def

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,19 +345,21 @@ OPDEF(INTOP_NEWOBJ_VT, "newobj.vt", 5, 1, 1, InterpOpMethodHandle)
345345

346346
// Call a helper function with a signature of PointerSizedDest helper(TypeOrGenericArg))
347347
OPDEF(INTOP_CALL_HELPER_P_P, "call.helper.p.p", 4, 1, 0, InterpOpHelperFtn)
348-
OPDEF(INTOP_CALL_HELPER_P_PP, "call.helper.p.pp", 5, 1, 1, InterpOpHelperFtn)
348+
OPDEF(INTOP_CALL_HELPER_P_G, "call.helper.p.g", 5, 1, 1, InterpOpGenericHelperFtn)
349+
OPDEF(INTOP_CALL_HELPER_P_S, "call.helper.p.s", 4, 1, 1, InterpOpHelperFtnNoArgs)
349350

350351
// Call a helper function with a signature of PointerSizedDest helper(TypeOrGenericArg, SVar))
351-
OPDEF(INTOP_CALL_HELPER_P_G, "call.helper.p.g", 5, 1, 1, InterpOpGenericHelperFtn)
352-
OPDEF(INTOP_CALL_HELPER_P_GP, "call.helper.p.gp", 6, 1, 2, InterpOpGenericHelperFtn)
352+
OPDEF(INTOP_CALL_HELPER_P_PS, "call.helper.p.ps", 5, 1, 1, InterpOpHelperFtn)
353+
OPDEF(INTOP_CALL_HELPER_P_GS, "call.helper.p.gs", 6, 1, 2, InterpOpGenericHelperFtn)
354+
OPDEF(INTOP_CALL_HELPER_P_SP, "call.helper.p.sp", 5, 1, 1, InterpOpHelperFtn)
353355

354356
// Call a helper function with a signature of PointerSizedDest helper(TypeOrGenericArg, AddrOfSVar))
355357
OPDEF(INTOP_CALL_HELPER_P_PA, "call.helper.p.pa", 5, 1, 1, InterpOpHelperFtn)
356358
OPDEF(INTOP_CALL_HELPER_P_GA, "call.helper.p.ga", 6, 1, 2, InterpOpGenericHelperFtn)
357359

358360
// Call a helper function with a signature of void helper(AddrOfDVar, TypeOrGenericArg, SVar))
359-
OPDEF(INTOP_CALL_HELPER_V_APP, "call.helper.v.app", 5, 1, 1, InterpOpHelperFtn)
360-
OPDEF(INTOP_CALL_HELPER_V_AGP, "call.helper.v.agp", 6, 1, 2, InterpOpGenericHelperFtn)
361+
OPDEF(INTOP_CALL_HELPER_V_APS, "call.helper.v.aps", 5, 1, 1, InterpOpHelperFtn)
362+
OPDEF(INTOP_CALL_HELPER_V_AGS, "call.helper.v.ags", 6, 1, 2, InterpOpGenericHelperFtn)
361363

362364
OPDEF(INTOP_GENERICLOOKUP, "generic", 4, 1, 1, InterpOpGenericLookup)
363365

src/coreclr/interpreter/intops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ typedef enum
2626
InterpOpGenericHelperFtn,
2727
InterpOpLdPtr,
2828
InterpOpHelperFtn,
29+
InterpOpHelperFtnNoArgs,
2930
InterpOpPointerHelperFtn,
3031
InterpOpPointerInt,
3132
InterpOpGenericLookupInt,

src/coreclr/vm/interpexec.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,7 +1592,18 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
15921592
ip += 4;
15931593
break;
15941594
}
1595-
case INTOP_CALL_HELPER_P_PP:
1595+
1596+
case INTOP_CALL_HELPER_P_S:
1597+
{
1598+
HELPER_FTN_P_P helperFtn = GetPossiblyIndirectHelper<HELPER_FTN_P_P>(pMethod->pDataItems[ip[2]]);
1599+
void* helperArg = LOCAL_VAR(ip[3], void*);
1600+
1601+
LOCAL_VAR(ip[1], void*) = helperFtn(helperArg);
1602+
ip += 4;
1603+
break;
1604+
}
1605+
1606+
case INTOP_CALL_HELPER_P_PS:
15961607
{
15971608
HELPER_FTN_P_PP helperFtn = GetPossiblyIndirectHelper<HELPER_FTN_P_PP>(pMethod->pDataItems[ip[3]]);
15981609
void* helperArg = pMethod->pDataItems[ip[4]];
@@ -1602,6 +1613,16 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
16021613
break;
16031614
}
16041615

1616+
case INTOP_CALL_HELPER_P_SP:
1617+
{
1618+
HELPER_FTN_P_PP helperFtn = GetPossiblyIndirectHelper<HELPER_FTN_P_PP>(pMethod->pDataItems[ip[3]]);
1619+
void* helperArg = pMethod->pDataItems[ip[4]];
1620+
1621+
LOCAL_VAR(ip[1], void*) = helperFtn(LOCAL_VAR(ip[2], void*), helperArg);
1622+
ip += 5;
1623+
break;
1624+
}
1625+
16051626
case INTOP_CALL_HELPER_P_G:
16061627
{
16071628
InterpGenericLookup *pLookup = (InterpGenericLookup*)&pMethod->pDataItems[ip[4]];
@@ -1614,7 +1635,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
16141635
break;
16151636
}
16161637

1617-
case INTOP_CALL_HELPER_P_GP:
1638+
case INTOP_CALL_HELPER_P_GS:
16181639
{
16191640
InterpGenericLookup *pLookup = (InterpGenericLookup*)&pMethod->pDataItems[ip[5]];
16201641
void* helperArg = DoGenericLookup(LOCAL_VAR(ip[2], void*), pLookup);
@@ -1646,7 +1667,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
16461667
break;
16471668
}
16481669

1649-
case INTOP_CALL_HELPER_V_AGP:
1670+
case INTOP_CALL_HELPER_V_AGS:
16501671
{
16511672
InterpGenericLookup *pLookup = (InterpGenericLookup*)&pMethod->pDataItems[ip[5]];
16521673
void* helperArg = DoGenericLookup(LOCAL_VAR(ip[2], void*), pLookup);
@@ -1657,7 +1678,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
16571678
break;
16581679
}
16591680

1660-
case INTOP_CALL_HELPER_V_APP:
1681+
case INTOP_CALL_HELPER_V_APS:
16611682
{
16621683
HELPER_FTN_V_PPP helperFtn = GetPossiblyIndirectHelper<HELPER_FTN_V_PPP>(pMethod->pDataItems[ip[3]]);
16631684
void* helperArg = pMethod->pDataItems[ip[4]];

0 commit comments

Comments
 (0)