Skip to content

Commit 504fb7d

Browse files
authored
Add constrained support for calls (#116702)
* Add full constructor to StackInfo To prevent having uninitialized fields * Add constrained support for calls Rename constrainedClass to pConstrainedToken for clarity. Extract box code emit into separate method. * Get rid of StackInfo.size It doesn't seem like we will be needing it. Use constructor in more places
1 parent 0d628da commit 504fb7d

File tree

4 files changed

+72
-54
lines changed

4 files changed

+72
-54
lines changed

src/coreclr/interpreter/compiler.cpp

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -581,11 +581,8 @@ bool InterpCompiler::CheckStackHelper(int n)
581581
void InterpCompiler::PushTypeExplicit(StackType stackType, CORINFO_CLASS_HANDLE clsHnd, int size)
582582
{
583583
EnsureStack(1);
584-
m_pStackPointer->type = stackType;
585-
m_pStackPointer->clsHnd = clsHnd;
586-
m_pStackPointer->size = ALIGN_UP_TO(size, INTERP_STACK_SLOT_SIZE);
587-
int var = CreateVarExplicit(g_interpTypeFromStackType[stackType], clsHnd, size);
588-
m_pStackPointer->var = var;
584+
int32_t var = CreateVarExplicit(g_interpTypeFromStackType[stackType], clsHnd, size);
585+
new (m_pStackPointer) StackInfo(stackType, clsHnd, var);
589586
m_pStackPointer++;
590587
}
591588

@@ -1288,9 +1285,8 @@ void InterpCompiler::EmitConv(StackInfo *sp, StackType type, InterpOpcode convOp
12881285
InterpInst *newInst = AddIns(convOp);
12891286

12901287
newInst->SetSVar(sp->var);
1291-
new (sp) StackInfo(type);
12921288
int32_t var = CreateVarExplicit(g_interpTypeFromStackType[type], NULL, INTERP_STACK_SLOT_SIZE);
1293-
sp->var = var;
1289+
new (sp) StackInfo(type, NULL, var);
12941290
newInst->SetDVar(var);
12951291

12961292
// NOTE: We rely on m_pLastNewIns == newInst upon return from this function. Make sure you preserve that if you change anything.
@@ -1708,10 +1704,7 @@ bool InterpCompiler::InitializeClauseBuildingBlocks(CORINFO_METHOD_INFO* methodI
17081704
// Initialize the filter stack state. It initially contains the exception object.
17091705
pFilterBB->stackHeight = 1;
17101706
pFilterBB->pStackState = (StackInfo*)AllocMemPool(sizeof (StackInfo));
1711-
pFilterBB->pStackState[0].type = StackTypeO;
1712-
pFilterBB->pStackState[0].size = INTERP_STACK_SLOT_SIZE;
1713-
pFilterBB->pStackState[0].clsHnd = NULL;
1714-
pFilterBB->pStackState[0].var = pFilterBB->clauseVarIndex;
1707+
new (pFilterBB->pStackState) StackInfo(StackTypeO, NULL, pFilterBB->clauseVarIndex);
17151708

17161709
// Find and mark all basic blocks that are part of the filter region.
17171710
for (uint32_t j = clause.FilterOffset; j < clause.HandlerOffset; j++)
@@ -1740,10 +1733,7 @@ bool InterpCompiler::InitializeClauseBuildingBlocks(CORINFO_METHOD_INFO* methodI
17401733
// Initialize the catch / filtered handler stack state. It initially contains the exception object.
17411734
pCatchBB->stackHeight = 1;
17421735
pCatchBB->pStackState = (StackInfo*)AllocMemPool(sizeof (StackInfo));
1743-
pCatchBB->pStackState[0].type = StackTypeO;
1744-
pCatchBB->pStackState[0].size = INTERP_STACK_SLOT_SIZE;
1745-
pCatchBB->pStackState[0].var = pCatchBB->clauseVarIndex;
1746-
pCatchBB->pStackState[0].clsHnd = NULL;
1736+
new (pCatchBB->pStackState) StackInfo(StackTypeO, NULL, pCatchBB->clauseVarIndex);
17471737
}
17481738
}
17491739

@@ -2315,7 +2305,7 @@ int InterpCompiler::EmitGenericHandleAsVar(const CORINFO_GENERICHANDLE_RESULT &e
23152305
return resultVar;
23162306
}
23172307

2318-
void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* constrainedClass, bool readonly, bool tailcall, bool newObj, bool isCalli)
2308+
void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool readonly, bool tailcall, bool newObj, bool isCalli)
23192309
{
23202310
uint32_t token = getU4LittleEndian(m_ip + 1);
23212311
bool isVirtual = (*m_ip == CEE_CALLVIRT);
@@ -2345,19 +2335,38 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* constrainedClass, bool rea
23452335
}
23462336
else
23472337
{
2348-
23492338
ResolveToken(token, newObj ? CORINFO_TOKENKIND_NewObj : CORINFO_TOKENKIND_Method, &resolvedCallToken);
2350-
2339+
23512340
CORINFO_CALLINFO_FLAGS flags = (CORINFO_CALLINFO_FLAGS)(CORINFO_CALLINFO_ALLOWINSTPARAM | CORINFO_CALLINFO_SECURITYCHECKS | CORINFO_CALLINFO_DISALLOW_STUB);
23522341
if (isVirtual)
23532342
flags = (CORINFO_CALLINFO_FLAGS)(flags | CORINFO_CALLINFO_CALLVIRT);
23542343

2355-
m_compHnd->getCallInfo(&resolvedCallToken, constrainedClass, m_methodInfo->ftn, flags, &callInfo);
2344+
m_compHnd->getCallInfo(&resolvedCallToken, pConstrainedToken, m_methodInfo->ftn, flags, &callInfo);
23562345
if (EmitCallIntrinsics(callInfo.hMethod, callInfo.sig))
23572346
{
23582347
m_ip += 5;
23592348
return;
23602349
}
2350+
2351+
if (callInfo.thisTransform != CORINFO_NO_THIS_TRANSFORM)
2352+
{
2353+
assert(pConstrainedToken != NULL);
2354+
StackInfo *pThisStackInfo = m_pStackPointer - callInfo.sig.numArgs - 1;
2355+
if (callInfo.thisTransform == CORINFO_BOX_THIS)
2356+
{
2357+
EmitBox(pThisStackInfo, pConstrainedToken->hClass, true);
2358+
}
2359+
else
2360+
{
2361+
assert(callInfo.thisTransform == CORINFO_DEREF_THIS);
2362+
AddIns(INTOP_LDIND_I);
2363+
m_pLastNewIns->SetSVar(pThisStackInfo->var);
2364+
m_pLastNewIns->data[0] = 0;
2365+
int32_t var = CreateVarExplicit(InterpTypeO, pConstrainedToken->hClass, INTERP_STACK_SLOT_SIZE);
2366+
new (pThisStackInfo) StackInfo(StackTypeO, pConstrainedToken->hClass, var);
2367+
m_pLastNewIns->SetDVar(pThisStackInfo->var);
2368+
}
2369+
}
23612370
}
23622371

23632372
if (newObj && (callInfo.classFlags & CORINFO_FLG_VAROBJSIZE))
@@ -2889,12 +2898,27 @@ void InterpCompiler::EmitLdLocA(int32_t var)
28892898
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
28902899
}
28912900

2901+
void InterpCompiler::EmitBox(StackInfo* pStackInfo, CORINFO_CLASS_HANDLE clsHnd, bool argByRef)
2902+
{
2903+
CORINFO_CLASS_HANDLE boxedClsHnd = m_compHnd->getTypeForBox(clsHnd);
2904+
CorInfoHelpFunc helpFunc = m_compHnd->getBoxHelper(clsHnd);
2905+
AddIns(argByRef ? INTOP_BOX_PTR : INTOP_BOX);
2906+
m_pLastNewIns->SetSVar(pStackInfo->var);
2907+
2908+
int32_t var = CreateVarExplicit(InterpTypeO, boxedClsHnd, INTERP_STACK_SLOT_SIZE);
2909+
new (pStackInfo) StackInfo(StackTypeO, boxedClsHnd, var);
2910+
2911+
m_pLastNewIns->SetDVar(pStackInfo->var);
2912+
m_pLastNewIns->data[0] = GetDataItemIndex(clsHnd);
2913+
m_pLastNewIns->data[1] = GetDataItemIndexForHelperFtn(helpFunc);
2914+
}
2915+
28922916
int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
28932917
{
28942918
bool readonly = false;
28952919
bool tailcall = false;
28962920
bool volatile_ = false;
2897-
CORINFO_RESOLVED_TOKEN* constrainedClass = NULL;
2921+
CORINFO_RESOLVED_TOKEN* pConstrainedToken = NULL;
28982922
CORINFO_RESOLVED_TOKEN constrainedToken;
28992923
uint8_t *codeEnd;
29002924
int numArgs = m_methodInfo->args.hasThis() + m_methodInfo->args.numArgs;
@@ -4057,21 +4081,21 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
40574081
break;
40584082
case CEE_CALLVIRT:
40594083
case CEE_CALL:
4060-
EmitCall(constrainedClass, readonly, tailcall, false /*newObj*/, false /*isCalli*/);
4061-
constrainedClass = NULL;
4084+
EmitCall(pConstrainedToken, readonly, tailcall, false /*newObj*/, false /*isCalli*/);
4085+
pConstrainedToken = NULL;
40624086
readonly = false;
40634087
tailcall = false;
40644088
break;
40654089
case CEE_CALLI:
4066-
EmitCall(NULL /*constrainedClass*/, false /* readonly*/, false /* tailcall*/, false /*newObj*/, true /*isCalli*/);
4067-
constrainedClass = NULL;
4090+
EmitCall(NULL /*pConstrainedToken*/, false /* readonly*/, false /* tailcall*/, false /*newObj*/, true /*isCalli*/);
4091+
pConstrainedToken = NULL;
40684092
readonly = false;
40694093
tailcall = false;
40704094
break;
40714095
case CEE_NEWOBJ:
40724096
{
4073-
EmitCall(NULL /*constrainedClass*/, false /* readonly*/, false /* tailcall*/, true /*newObj*/, false /*isCalli*/);
4074-
constrainedClass = NULL;
4097+
EmitCall(NULL /*pConstrainedToken*/, false /* readonly*/, false /* tailcall*/, true /*newObj*/, false /*isCalli*/);
4098+
pConstrainedToken = NULL;
40754099
readonly = false;
40764100
tailcall = false;
40774101
break;
@@ -4448,12 +4472,9 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
44484472
{
44494473
uint32_t token = getU4LittleEndian(m_ip + 1);
44504474

4451-
constrainedToken.tokenScope = m_compScopeHnd;
4452-
constrainedToken.tokenContext = METHOD_BEING_COMPILED_CONTEXT();
4453-
constrainedToken.token = token;
4454-
constrainedToken.tokenType = CORINFO_TOKENKIND_Constrained;
4455-
m_compHnd->resolveToken(&constrainedToken);
4456-
constrainedClass = &constrainedToken;
4475+
ResolveToken(token, CORINFO_TOKENKIND_Constrained, &constrainedToken);
4476+
4477+
pConstrainedToken = &constrainedToken;
44574478
m_ip += 5;
44584479
break;
44594480
}
@@ -4546,8 +4567,8 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
45464567
ResolveToken(token, CORINFO_TOKENKIND_Method, &resolvedToken);
45474568

45484569
CORINFO_CALL_INFO callInfo;
4549-
m_compHnd->getCallInfo(&resolvedToken, constrainedClass, m_methodInfo->ftn, (CORINFO_CALLINFO_FLAGS)(CORINFO_CALLINFO_SECURITYCHECKS| CORINFO_CALLINFO_LDFTN), &callInfo);
4550-
constrainedClass = NULL;
4570+
m_compHnd->getCallInfo(&resolvedToken, pConstrainedToken, m_methodInfo->ftn, (CORINFO_CALLINFO_FLAGS)(CORINFO_CALLINFO_SECURITYCHECKS| CORINFO_CALLINFO_LDFTN), &callInfo);
4571+
pConstrainedToken = NULL;
45514572

45524573
if (callInfo.kind == CORINFO_CALL)
45534574
{
@@ -4650,17 +4671,11 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
46504671

46514672
case CEE_BOX:
46524673
{
4674+
CORINFO_CLASS_HANDLE clsHnd = ResolveClassToken(getU4LittleEndian(m_ip + 1));
46534675
CHECK_STACK(1);
46544676
m_pStackPointer -= 1;
4655-
CORINFO_CLASS_HANDLE clsHnd = ResolveClassToken(getU4LittleEndian(m_ip + 1));
4656-
CORINFO_CLASS_HANDLE boxedClsHnd = m_compHnd->getTypeForBox(clsHnd);
4657-
CorInfoHelpFunc helpFunc = m_compHnd->getBoxHelper(clsHnd);
4658-
AddIns(INTOP_BOX);
4659-
m_pLastNewIns->SetSVar(m_pStackPointer[0].var);
4660-
PushStackType(StackTypeO, boxedClsHnd);
4661-
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
4662-
m_pLastNewIns->data[0] = GetDataItemIndex(clsHnd);
4663-
m_pLastNewIns->data[1] = GetDataItemIndexForHelperFtn(helpFunc);
4677+
EmitBox(m_pStackPointer, clsHnd, false);
4678+
m_pStackPointer++;
46644679
m_ip += 5;
46654680
break;
46664681
}

src/coreclr/interpreter/compiler.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -266,20 +266,16 @@ struct StackInfo
266266
{
267267
StackType type;
268268
CORINFO_CLASS_HANDLE clsHnd;
269-
// Size that this value will occupy on the interpreter stack. It is a multiple
270-
// of INTERP_STACK_SLOT_SIZE
271-
int size;
272269

273270
// The var associated with the value of this stack entry. Every time we push on
274271
// the stack a new var is created.
275272
int var;
276273

277-
StackInfo(StackType type)
274+
StackInfo(StackType type, CORINFO_CLASS_HANDLE clsHnd, int var)
278275
{
279276
this->type = type;
280-
clsHnd = NULL;
281-
size = 0;
282-
var = -1;
277+
this->clsHnd = clsHnd;
278+
this->var = var;
283279
}
284280
};
285281

@@ -491,7 +487,7 @@ class InterpCompiler
491487
void EmitUnaryArithmeticOp(int32_t opBase);
492488
void EmitShiftOp(int32_t opBase);
493489
void EmitCompareOp(int32_t opBase);
494-
void EmitCall(CORINFO_RESOLVED_TOKEN* constrainedClass, bool readonly, bool tailcall, bool newObj, bool isCalli);
490+
void EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool readonly, bool tailcall, bool newObj, bool isCalli);
495491
bool EmitCallIntrinsics(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO sig);
496492
void EmitLdind(InterpType type, CORINFO_CLASS_HANDLE clsHnd, int32_t offset);
497493
void EmitStind(InterpType type, CORINFO_CLASS_HANDLE clsHnd, int32_t offset, bool reverseSVarOrder);
@@ -500,6 +496,7 @@ class InterpCompiler
500496
void EmitStaticFieldAddress(CORINFO_FIELD_INFO *pFieldInfo, CORINFO_RESOLVED_TOKEN *pResolvedToken);
501497
void EmitStaticFieldAccess(InterpType interpFieldType, CORINFO_FIELD_INFO *pFieldInfo, CORINFO_RESOLVED_TOKEN *pResolvedToken, bool isLoad);
502498
void EmitLdLocA(int32_t var);
499+
void EmitBox(StackInfo* pStackInfo, CORINFO_CLASS_HANDLE clsHnd, bool argByRef);
503500

504501
// Var Offset allocator
505502
TArray<InterpInst*> *m_pActiveCalls;

src/coreclr/interpreter/intops.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ OPDEF(INTOP_CONV_OVF_U8_R4, "conv.ovf.u8.r4", 3, 1, 1, InterpOpNoArgs)
207207
OPDEF(INTOP_CONV_OVF_U8_R8, "conv.ovf.u8.r8", 3, 1, 1, InterpOpNoArgs)
208208

209209
OPDEF(INTOP_BOX, "box", 5, 1, 1, InterpOpClassHandle) // [class handle data item] [helper data item]
210+
OPDEF(INTOP_BOX_PTR, "box.ptr", 5, 1, 1, InterpOpClassHandle) // [class handle data item] [helper data item]
210211
OPDEF(INTOP_UNBOX, "unbox", 5, 1, 1, InterpOpClassHandle) // [class handle data item] [helper data item]
211212
OPDEF(INTOP_UNBOX_ANY, "unbox.any", 5, 1, 1, InterpOpClassHandle) // [class handle data item] [helper data item]
212213
// Unary operations end

src/coreclr/vm/interpexec.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
17581758
ip += 2;
17591759
break;
17601760
case INTOP_BOX:
1761+
case INTOP_BOX_PTR:
17611762
case INTOP_UNBOX:
17621763
case INTOP_UNBOX_ANY:
17631764
{
@@ -1767,10 +1768,14 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
17671768
MethodTable *pMT = (MethodTable*)pMethod->pDataItems[ip[3]];
17681769
HELPER_FTN_BOX_UNBOX helper = GetPossiblyIndirectHelper<HELPER_FTN_BOX_UNBOX>(pMethod->pDataItems[ip[4]]);
17691770

1770-
if (opcode == INTOP_BOX) {
1771+
if (opcode == INTOP_BOX || opcode == INTOP_BOX_PTR) {
17711772
// internal static object Box(MethodTable* typeMT, ref byte unboxedData)
1772-
void *unboxedData = LOCAL_VAR_ADDR(sreg, void);
1773-
LOCAL_VAR(dreg, Object*) = (Object*)helper(pMT, unboxedData);
1773+
void *unboxedData;
1774+
if (opcode == INTOP_BOX)
1775+
unboxedData = LOCAL_VAR_ADDR(sreg, void);
1776+
else
1777+
unboxedData = LOCAL_VAR(sreg, void*);
1778+
LOCAL_VAR(dreg, OBJECTREF) = ObjectToOBJECTREF((Object*)helper(pMT, unboxedData));
17741779
} else {
17751780
// private static ref byte Unbox(MethodTable* toTypeHnd, object obj)
17761781
Object *src = LOCAL_VAR(sreg, Object*);

0 commit comments

Comments
 (0)