Skip to content

Fix missing call to write barrier in static constructors of ref structs#125418

Open
janvorli wants to merge 6 commits intodotnet:mainfrom
janvorli:fix-refclass-contructor-codegen
Open

Fix missing call to write barrier in static constructors of ref structs#125418
janvorli wants to merge 6 commits intodotnet:mainfrom
janvorli:fix-refclass-contructor-codegen

Conversation

@janvorli
Copy link
Member

The JIT was incorrectly handling initialization of static fields of ref structs. It was not adding call to JIT_ByRefWriteBarrier when setting these fields even though these statics live in GC heap.

This issue was introduced in .NET 10 in #111733

This change fixes it and adds a regression test that causes fatal error when run with DOTNET_HeapVerify=1.

Close #125169

The JIT was incorrectly handling initialization of static fields of ref
structs. It was not adding call to JIT_ByRefWriteBarrier when setting
these fields even though these statics live in GC heap.

This change fixes it and adds a regression test that causes fatal error
when run with DOTNET_HeapVerify=1.

Close dotnet#125169
@janvorli janvorli added this to the 10.0.x milestone Mar 10, 2026
@janvorli janvorli requested review from AndyAyersMS and EgorBo March 10, 2026 22:27
@janvorli janvorli self-assigned this Mar 10, 2026
Copilot AI review requested due to automatic review settings March 10, 2026 22:27
@janvorli janvorli added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 10, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes CoreCLR JIT handling of addresses for fields whose owning type is byref-like (ref struct), ensuring static fields aren’t incorrectly treated as “not on heap” (which can suppress required write barriers). Adds a new JIT regression test covering the scenario.

Changes:

  • Update JIT importer logic to only mark byref-like instance field owners as GTF_IND_TGT_NOT_HEAP (exclude static fields).
  • Add a new JIT regression test intended to reproduce missing write-barrier behavior for ref struct statics.
  • Wire the new test into Regression_ro_2.csproj.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/tests/JIT/Regression/Regression_ro_2.csproj Adds the new regression test source file to the test project.
src/tests/JIT/Regression/JitBlue/Runtime_125169/Runtime_125169.cs New regression test exercising ref struct static initialization + GC.
src/coreclr/jit/importer.cpp Adjusts heap-ness classification so static fields on byref-like owners aren’t treated as not-heap.

You can also share your feedback on Copilot code review. Take the survey.

@AndyAyersMS
Copy link
Member

@EgorBo PTAL

@AndyAyersMS AndyAyersMS requested review from EgorBo and removed request for EgorBo March 10, 2026 22:38
Copy link
Member

@EgorBo EgorBo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! With a small nit to make it less conservative.

Copilot AI review requested due to automatic review settings March 11, 2026 12:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


You can also share your feedback on Copilot code review. Take the survey.

Copilot AI review requested due to automatic review settings March 12, 2026 12:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +36 to +41
ReadOnlySpan<byte> testSpan = new(RefWrapper._data._innerArray);
// Without the fix, the following GC.Collect call causes fatal error during heap verification with DOTNET_HeapVerify=1
GC.Collect(0);

// Prevent the compiler from optimizing out the loop above.
GC.KeepAlive(arr);
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testSpan is never used, so the JIT may dead-code-eliminate the ReadOnlySpan<byte> construction (and potentially the RefWrapper._data access), which can make the test non-deterministic or ineffective at triggering the ref-struct cctor path. Please make the access observably used (e.g., read a byte / assert a value, or GC.KeepAlive(testSpan) / GC.KeepAlive(RefWrapper._data._innerArray), or explicitly force the cctor via RuntimeHelpers.RunClassConstructor).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SIGSEGV in GC mark phase (gc_heap::mark_object_simple1) on .NET 10.0.3 — null object reference in heap slot during Server GC

4 participants