Skip to content

Commit 923ec4d

Browse files
github-actions[bot]jakobbotschAndyAyersMS
authored
[release/6.0] Disable poisoning for large structs (#61601)
* 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 * Run jit-format * Add regression test * Update src/coreclr/jit/codegencommon.cpp Co-authored-by: Andy Ayers <[email protected]> * Don't check poisoning for large struct in test Since it's disabled, there is nothing to check. Co-authored-by: Jakob Botsch Nielsen <[email protected]> Co-authored-by: Andy Ayers <[email protected]>
1 parent b2f42fa commit 923ec4d

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/coreclr/jit/codegencommon.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12551,6 +12551,17 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn)
1255112551

1255212552
assert(varDsc->lvOnFrame);
1255312553

12554+
int size = (int)compiler->lvaLclSize(varNum);
12555+
12556+
if ((size / TARGET_POINTER_SIZE) > 16)
12557+
{
12558+
// For very large structs the offsets in the movs we emit below can
12559+
// grow too large to be handled properly by JIT. Furthermore, while
12560+
// this is only debug code, for very large structs this can bloat
12561+
// the code too much due to the singular movs used.
12562+
continue;
12563+
}
12564+
1255412565
if (!hasPoisonImm)
1255512566
{
1255612567
#ifdef TARGET_64BIT
@@ -12568,8 +12579,7 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn)
1256812579
#else
1256912580
int addr = 0;
1257012581
#endif
12571-
int size = (int)compiler->lvaLclSize(varNum);
12572-
int end = addr + size;
12582+
int end = addr + size;
1257312583
for (int offs = addr; offs < end;)
1257412584
{
1257512585
#ifdef TARGET_64BIT

src/tests/JIT/Directed/debugging/poison.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,24 @@ public static unsafe int Main()
1919
WithoutGCRef poisoned2;
2020
Unsafe.SkipInit(out poisoned2);
2121
result &= VerifyPoison(&poisoned2, sizeof(WithoutGCRef));
22+
23+
Massive notPoisoned;
24+
Unsafe.SkipInit(out notPoisoned);
25+
// too large to be poisoned, just expose it but don't check return value
26+
VerifyPoison(&notPoisoned, sizeof(Massive));
27+
28+
WithoutGCRef poisoned4;
29+
Unsafe.SkipInit(out poisoned4);
30+
result &= VerifyPoison(&poisoned4, sizeof(WithoutGCRef));
31+
32+
Massive notPoisoned2;
33+
Unsafe.SkipInit(out notPoisoned2);
34+
// too large to be poisoned, just expose it but don't check return value
35+
VerifyPoison(&notPoisoned2, sizeof(Massive));
36+
37+
GCRef zeroed2;
38+
Unsafe.SkipInit(out zeroed2);
39+
result &= VerifyZero(Unsafe.AsPointer(ref zeroed2), Unsafe.SizeOf<GCRef>());
2240

2341
return result ? 100 : 101;
2442
}
@@ -53,4 +71,9 @@ private struct WithoutGCRef
5371
public int ANumber;
5472
public float AFloat;
5573
}
56-
}
74+
75+
private unsafe struct Massive
76+
{
77+
public fixed byte Bytes[0x10008];
78+
}
79+
}

0 commit comments

Comments
 (0)