Disable poisoning for large structs (#61589)
authorJakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
Mon, 15 Nov 2021 15:28:07 +0000 (16:28 +0100)
committerGitHub <noreply@github.com>
Mon, 15 Nov 2021 15:28:07 +0000 (16:28 +0100)
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

index a33b4b9..8585bab 100644 (file)
@@ -12461,6 +12461,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
@@ -12478,8 +12489,7 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn)
 #else
         int addr = 0;
 #endif
-        int size = (int)compiler->lvaLclSize(varNum);
-        int end  = addr + size;
+        int end = addr + size;
         for (int offs = addr; offs < end;)
         {
 #ifdef TARGET_64BIT