From 89d1adca4c4def26a43e1eeaee2c6b9ba039cfd6 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 20 May 2025 11:27:27 +0200 Subject: [PATCH] JIT: Spill value before byref address in stsfld MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We could end up producing trees like ``` ▌ STOREIND ref ├──▌ ADD byref │ ├──▌ CALL help byref CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR │ │ └──▌ CNS_INT long 0x7ff84228d6b8 │ └──▌ CNS_INT long 0 Fseq[s_3] └──▌ CALL ref Program:M2():int[] (async) └──▌ CNS_INT ref null ``` where a byref is live across a suspension point. --- src/coreclr/jit/gentree.cpp | 5 +++++ src/coreclr/jit/importer.cpp | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index a49f98a296427a..24c85a77a0ae05 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -12975,6 +12975,11 @@ void Compiler::gtDispTree(GenTree* tree, disp(); } + if (call->IsAsync()) + { + printf(" (async)"); + } + if ((call->gtFlags & GTF_CALL_UNMANAGED) && (call->gtCallMoreFlags & GTF_CALL_M_FRAME_VAR_DEATH)) { printf(" (FramesRoot last use)"); diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index af6fa9769a4551..8d9d6ef7fc0ced 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -9592,8 +9592,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) { bool isHoistable = info.compCompHnd->getClassAttribs(resolvedToken.hClass) & CORINFO_FLG_BEFOREFIELDINIT; - unsigned check_spill = isHoistable ? CHECK_SPILL_NONE : CHECK_SPILL_ALL; - impAppendTree(helperNode, check_spill, impCurStmtDI); + unsigned checkSpill = isHoistable ? CHECK_SPILL_NONE : CHECK_SPILL_ALL; + impAppendTree(helperNode, checkSpill, impCurStmtDI); } } @@ -9627,6 +9627,12 @@ void Compiler::impImportBlockCode(BasicBlock* block) { impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("value for stsfld with typeinit")); } + else if (compIsAsync() && op1->TypeIs(TYP_BYREF)) + { + // TODO-Async: We really only need to spill if + // there is a possibility of an async call in op2. + impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("byref address in async method")); + } break; default: