@@ -1024,8 +1024,20 @@ GenTree* Compiler::impStoreStructPtr(GenTree* destAddr, GenTree* value, unsigned
1024
1024
{
1025
1025
var_types type = value->TypeGet();
1026
1026
ClassLayout* layout = (type == TYP_STRUCT) ? value->GetLayout(this) : nullptr;
1027
- GenTree* store = gtNewStoreValueNode(type, layout, destAddr, value);
1028
- store = impStoreStruct(store, curLevel);
1027
+
1028
+ bool isRetBuffer = false;
1029
+ if (!compIsForInlining() && destAddr->OperIs(GT_LCL_VAR))
1030
+ {
1031
+ isRetBuffer = destAddr->AsLclVar()->GetLclNum() == info.compRetBuffArg;
1032
+ }
1033
+
1034
+ GenTree* store = gtNewStoreValueNode(type, layout, destAddr, value);
1035
+ if (isRetBuffer)
1036
+ {
1037
+ store->gtFlags |= GTF_IND_TGT_NOT_HEAP;
1038
+ }
1039
+
1040
+ store = impStoreStruct(store, curLevel);
1029
1041
1030
1042
return store;
1031
1043
}
@@ -3333,6 +3345,16 @@ void Compiler::impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken)
3333
3345
StackEntry se = impPopStack();
3334
3346
GenTree* exprToBox = se.val;
3335
3347
3348
+ if (varTypeIsStruct(exprToBox) && (exprToBox->IsCall() || exprToBox->OperIs(GT_RET_EXPR)))
3349
+ {
3350
+ unsigned callTmp = lvaGrabTemp(true DEBUGARG("spill struct call to tmp"));
3351
+ CORINFO_CLASS_HANDLE cls = exprToBox->IsCall() ? exprToBox->AsCall()->gtRetClsHnd
3352
+ : exprToBox->AsRetExpr()->gtInlineCandidate->gtRetClsHnd;
3353
+ lvaSetStruct(callTmp, cls, false);
3354
+ impStoreToTemp(callTmp, exprToBox, CHECK_SPILL_ALL);
3355
+ exprToBox = gtNewLclVarNode(callTmp);
3356
+ }
3357
+
3336
3358
// Look at what helper we should use.
3337
3359
CorInfoHelpFunc boxHelper = info.compCompHnd->getBoxHelper(pResolvedToken->hClass);
3338
3360
@@ -6429,6 +6451,17 @@ void Compiler::impImportBlockCode(BasicBlock* block)
6429
6451
JITDUMP("\n [%2u] %3u (0x%03x) ", stackState.esStackDepth, impCurOpcOffs, impCurOpcOffs);
6430
6452
#endif
6431
6453
6454
+ // CI testing. To be enabled only for jitstress
6455
+ if (!opts.IsReadyToRun() && !compIsForInlining() && (info.compRetBuffArg != BAD_VAR_NUM) &&
6456
+ (block == fgFirstBB))
6457
+ {
6458
+ // Write something into the buffer to make sure it's not on the gc heap.
6459
+ // We write the value already in the buffer, so that we don't have to worry about
6460
+ GenTree* retBuffAddr = gtNewLclvNode(info.compRetBuffArg, TYP_BYREF);
6461
+ GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_ENSURE_NONHEAP, TYP_VOID, retBuffAddr);
6462
+ impAppendTree(call, CHECK_SPILL_NONE, impCurStmtDI);
6463
+ }
6464
+
6432
6465
DECODE_OPCODE:
6433
6466
6434
6467
// Return if any previous code has caused inline to fail.
@@ -9416,6 +9449,15 @@ void Compiler::impImportBlockCode(BasicBlock* block)
9416
9449
// Pull the value from the stack.
9417
9450
op2 = impPopStack().val;
9418
9451
9452
+ // For STFLD(CALL) we need to spill the call, as the JIT
9453
+ if (varTypeIsStruct(op2) && (op2->IsCall() || op2->OperIs(GT_RET_EXPR)))
9454
+ {
9455
+ unsigned callTmp = lvaGrabTemp(true DEBUGARG("spill struct call to tmp"));
9456
+ lvaSetStruct(callTmp, fieldInfo.structType, false);
9457
+ impStoreToTemp(callTmp, op2, CHECK_SPILL_ALL);
9458
+ op2 = gtNewLclVarNode(callTmp);
9459
+ }
9460
+
9419
9461
if (opcode == CEE_STFLD)
9420
9462
{
9421
9463
obj = impPopStack().val;
0 commit comments