diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 07b08c3692a4e5..d5d6fe88300f6a 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -160,6 +160,10 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) GetEmitter()->emitDisableGC(); break; + case GT_STOP_NONGC: + GetEmitter()->emitEnableGC(); + break; + case GT_START_PREEMPTGC: // Kill callee saves GC registers, and create a label // so that information gets propagated to the emitter. diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index c7fa8df00c4bc0..cf2b5f7b869b8e 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -4210,6 +4210,10 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) GetEmitter()->emitDisableGC(); break; + case GT_STOP_NONGC: + GetEmitter()->emitEnableGC(); + break; + case GT_START_PREEMPTGC: // Kill callee saves GC registers, and create a label // so that information gets propagated to the emitter. diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 6c93a636e0062c..ae71b9c7a3ca92 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -4285,6 +4285,10 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) GetEmitter()->emitDisableGC(); break; + case GT_STOP_NONGC: + GetEmitter()->emitEnableGC(); + break; + case GT_START_PREEMPTGC: // Kill callee saves GC registers, and create a label // so that information gets propagated to the emitter. diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 6c23977f83a096..49d1106f7dba49 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -1869,6 +1869,10 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) case GT_START_NONGC: GetEmitter()->emitDisableGC(); break; + + case GT_STOP_NONGC: + GetEmitter()->emitEnableGC(); + break; #endif // !defined(JIT32_GCENCODER) case GT_START_PREEMPTGC: diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 26d421e79ba841..c5c422d47e01be 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -11849,6 +11849,7 @@ class GenTreeVisitor case GT_SETCC: case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: case GT_START_PREEMPTGC: case GT_PROF_HOOK: #if defined(FEATURE_EH_WINDOWS_X86) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 9b7628fe592144..30578c3597bc70 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -4377,6 +4377,7 @@ void GenTree::VisitOperands(TVisitor visitor) case GT_SETCC: case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: case GT_START_PREEMPTGC: case GT_PROF_HOOK: #if defined(FEATURE_EH_WINDOWS_X86) diff --git a/src/coreclr/jit/error.cpp b/src/coreclr/jit/error.cpp index 5ae6cea056efeb..0fd5a5c59f9b90 100644 --- a/src/coreclr/jit/error.cpp +++ b/src/coreclr/jit/error.cpp @@ -268,9 +268,10 @@ extern "C" void __cdecl assertAbort(const char* why, const char* file, unsigned { phaseName = PhaseNames[env->compiler->mostRecentlyActivePhase]; _snprintf_s(buff, BUFF_SIZE, _TRUNCATE, - "Assertion failed '%s' in '%s' during '%s' (IL size %d; hash 0x%08x; %s)\n", why, + "Assertion failed '%s' in '%s' during '%s' (IL size %d; BBs: %d; hash 0x%08x; %s)\n", why, env->compiler->info.compFullName, phaseName, env->compiler->info.compILCodeSize, - env->compiler->info.compMethodHash(), env->compiler->compGetTieringName(/* short name */ true)); + env->compiler->fgBBcount, env->compiler->info.compMethodHash(), + env->compiler->compGetTieringName(/* short name */ true)); msg = buff; } printf(""); // null string means flush diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index beb5007e1a7173..e0bd073aa92cc7 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -6669,6 +6669,7 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse) case GT_SETCC: case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: case GT_START_PREEMPTGC: case GT_PROF_HOOK: #if defined(FEATURE_EH_WINDOWS_X86) @@ -10243,6 +10244,7 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node) case GT_SETCC: case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: case GT_START_PREEMPTGC: case GT_PROF_HOOK: #if defined(FEATURE_EH_WINDOWS_X86) @@ -12398,6 +12400,7 @@ void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack) case GT_NOP: case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: case GT_START_PREEMPTGC: case GT_PROF_HOOK: case GT_CATCH_ARG: diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 8c6c67fd6a3273..99900f7a852e5f 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -279,6 +279,7 @@ GTNODE(SWITCH , GenTreeOp ,0,1,GTK_UNOP|GTK_NOVALUE) GTNODE(NO_OP , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE) // A NOP that cannot be deleted. GTNODE(START_NONGC , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group that will be non-gc interruptible. +GTNODE(STOP_NONGC , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Tries to end the non-gc interruptible instruction group GTNODE(START_PREEMPTGC , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group where preemptive GC is enabled. GTNODE(PROF_HOOK , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Profiler Enter/Leave/TailCall hook. diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp index b66da476b05c72..cf3ec6f2c4a45d 100644 --- a/src/coreclr/jit/liveness.cpp +++ b/src/coreclr/jit/liveness.cpp @@ -1457,6 +1457,7 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR case GT_SWITCH: case GT_RETFILT: case GT_START_NONGC: + case GT_STOP_NONGC: case GT_START_PREEMPTGC: case GT_PROF_HOOK: #if defined(FEATURE_EH_WINDOWS_X86) diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index ce829a0730db70..ff8092e81495f8 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -743,7 +743,6 @@ GenTree* Lowering::LowerArrLength(GenTreeArrCommon* node) // Create the expression `*(array_addr + lenOffset)` GenTree* addr; - noway_assert(arr->gtNext == node); if ((arr->gtOper == GT_CNS_INT) && (arr->AsIntCon()->gtIconVal == 0)) { @@ -2892,6 +2891,7 @@ GenTree* Lowering::LowerCall(GenTree* node) ContainCheckRange(controlExprRange); BlockRange().InsertBefore(call, std::move(controlExprRange)); + call->gtControlExpr = controlExpr; } @@ -2925,6 +2925,22 @@ GenTree* Lowering::LowerCall(GenTree* node) } ContainCheckCallOperands(call); + +#ifndef TARGET_X86 + if (call->IsDelegateInvoke() && !call->IsTailCall()) + { + // If the target's backend doesn't support indirect calls with immediate operands (contained) + // and the method is marked as interruptible, we need to insert a GT_START_NONGC before the call. + // to keep the delegate object alive while we're obtaining the function pointer. + GenTree* startNonGCNode = new (comp, GT_START_NONGC) GenTree(GT_START_NONGC, TYP_VOID); + BlockRange().InsertBefore(controlExpr, startNonGCNode); + + GenTree* stopNonGCNode = new (comp, GT_STOP_NONGC) GenTree(GT_STOP_NONGC, TYP_VOID); + BlockRange().InsertAfter(call, stopNonGCNode); + BlockRange().InsertAfter(stopNonGCNode, new (comp, GT_NO_OP) GenTree(GT_NO_OP, TYP_VOID)); + } +#endif + JITDUMP("lowering call (after):\n"); DISPTREERANGE(BlockRange(), call); JITDUMP("\n"); diff --git a/src/coreclr/jit/lsraarm.cpp b/src/coreclr/jit/lsraarm.cpp index 815f0149aede11..5af90aab2f303c 100644 --- a/src/coreclr/jit/lsraarm.cpp +++ b/src/coreclr/jit/lsraarm.cpp @@ -413,6 +413,7 @@ int LinearScan::BuildNode(GenTree* tree) case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: case GT_PROF_HOOK: srcCount = 0; assert(dstCount == 0); diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index fdde96ef3acdef..70df680892a241 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -674,6 +674,7 @@ int LinearScan::BuildNode(GenTree* tree) case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: srcCount = 0; assert(dstCount == 0); break; diff --git a/src/coreclr/jit/lsraloongarch64.cpp b/src/coreclr/jit/lsraloongarch64.cpp index 529e6d8127b670..3840a88e7ca12a 100644 --- a/src/coreclr/jit/lsraloongarch64.cpp +++ b/src/coreclr/jit/lsraloongarch64.cpp @@ -122,6 +122,7 @@ int LinearScan::BuildNode(GenTree* tree) case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: srcCount = 0; assert(dstCount == 0); break; diff --git a/src/coreclr/jit/lsrariscv64.cpp b/src/coreclr/jit/lsrariscv64.cpp index 1185eac4cea938..d167d00674c6bf 100644 --- a/src/coreclr/jit/lsrariscv64.cpp +++ b/src/coreclr/jit/lsrariscv64.cpp @@ -123,6 +123,7 @@ int LinearScan::BuildNode(GenTree* tree) case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: srcCount = 0; assert(dstCount == 0); break; diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 1197b17ef15f8b..41e90bee3f6139 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -130,6 +130,7 @@ int LinearScan::BuildNode(GenTree* tree) case GT_NO_OP: case GT_START_NONGC: + case GT_STOP_NONGC: srcCount = 0; assert(dstCount == 0); break;