Skip to content

Commit

Permalink
[release/6.0] Disable poisoning for large structs (#61601)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
3 people authored Dec 15, 2021
1 parent b2f42fa commit 923ec4d
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
14 changes: 12 additions & 2 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -12568,8 +12579,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
Expand Down
25 changes: 24 additions & 1 deletion src/tests/JIT/Directed/debugging/poison.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,24 @@ public static unsafe int Main()
WithoutGCRef poisoned2;
Unsafe.SkipInit(out poisoned2);
result &= VerifyPoison(&poisoned2, sizeof(WithoutGCRef));

Massive notPoisoned;
Unsafe.SkipInit(out notPoisoned);
// too large to be poisoned, just expose it but don't check return value
VerifyPoison(&notPoisoned, sizeof(Massive));

WithoutGCRef poisoned4;
Unsafe.SkipInit(out poisoned4);
result &= VerifyPoison(&poisoned4, sizeof(WithoutGCRef));

Massive notPoisoned2;
Unsafe.SkipInit(out notPoisoned2);
// too large to be poisoned, just expose it but don't check return value
VerifyPoison(&notPoisoned2, sizeof(Massive));

GCRef zeroed2;
Unsafe.SkipInit(out zeroed2);
result &= VerifyZero(Unsafe.AsPointer(ref zeroed2), Unsafe.SizeOf<GCRef>());

return result ? 100 : 101;
}
Expand Down Expand Up @@ -53,4 +71,9 @@ private struct WithoutGCRef
public int ANumber;
public float AFloat;
}
}

private unsafe struct Massive
{
public fixed byte Bytes[0x10008];
}
}

0 comments on commit 923ec4d

Please sign in to comment.