Skip to content

optRemoveRedundantZeroInits doesn't know about some safe points #102577

@SingleAccretion

Description

@SingleAccretion

Looking at #102531, I realized the logic will miss implicit safe points created by the somewhat recent block store lowering changes.

Reproduction:

object x = null;
byte* p = stackalloc byte[1000];
Random.Shared.NextBytes(new Span<byte>(p, 1000));
Problem(p, p, &x);

[MethodImpl(MethodImplOptions.NoInlining)]
static void Problem(void* pDst, void* pSrc, object* pObj)
{
    Unsafe.CopyBlock(pDst, pSrc, 1000);
    StructWithManyObjs x = default;
    if (pDst != null)
    {
        x.ObjFour = *pObj;
        *(StructWithManyObjs*)pDst = x;
    }
}

struct StructWithManyObjs
{
    public object ObjOne;
    public object ObjTwo;
    public object ObjThree;
    public object ObjFour;
    public object ObjFive;
}

DOTNET_TieredCompilation=0, DOTNET_GCStress=0xC, DOTNET_ReadyToRun=0 (it looks like GC stress doesn't apply to precompiled code).

Expected result: nothing happens.
Actual result:

Assert failure(PID 17360 [0x000043d0], Thread: 14716 [0x397c]): !CREATE_CHECK_STRING(!"Detected use of a corrupted OBJECTREF. Possible GC hole.")

Cause: optRemoveRedundantZeroInits doesn't know that the block copy may become a safe point. Zero-init and future calls introduced late suffer from the same problem.

The most robust fix for this would probably be to move optRemoveRedundantZeroInits later (make it part of late liveness, say).

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIbug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions