From 4aa8253cedbd3c35d7edb32344f99901c5725059 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 15 Nov 2021 09:39:03 +0100 Subject: [PATCH] Disable poisoning for large structs For very large structs (> 64K in size) poisoning could end up generating instructions requiring larger local var offsets than we can handle. This hits IMPL_LIMIT that throws InvalidProgramException. Turn off poisoning for larger structs that require more than 16 movs to also avoid the significant code bloat by the singular movs. This is a less risky version of #61521 for backporting to .NET 6. Fix #60852 --- src/coreclr/jit/codegencommon.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index dcf1768c60a7d..f415b15ef8d58 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -12551,6 +12551,17 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn) assert(varDsc->lvOnFrame); + int size = (int)compiler->lvaLclSize(varNum); + + if (size / TARGET_POINTER_SIZE > 16) + { + // For very large structs the offsets in the movs we emit below can + // grow too large to be handled properly by JIT. Furthermore, while + // this is only debug code, for very large structs this can bloat + // the code too much due to the singular movs used. + continue; + } + if (!hasPoisonImm) { #ifdef TARGET_64BIT @@ -12568,7 +12579,6 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn) #else int addr = 0; #endif - int size = (int)compiler->lvaLclSize(varNum); int end = addr + size; for (int offs = addr; offs < end;) {