Skip to content

Arm64-SVE: Fixes for passing Vector<T> by reference in reflection calls - #131745

Open
snickolls-arm wants to merge 8 commits into
dotnet:mainfrom
snickolls-arm:reflection-fixes
Open

Arm64-SVE: Fixes for passing Vector<T> by reference in reflection calls#131745
snickolls-arm wants to merge 8 commits into
dotnet:mainfrom
snickolls-arm:reflection-fixes

Conversation

@snickolls-arm

Copy link
Copy Markdown
Contributor

Some reflection calls are triggering segmentation faults in testing due to missing some areas of support in the ArgIteratorTemplate.

Some reflection calls are triggering segmentation faults in testing due to
missing some areas of support in the ArgIteratorTemplate.
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Aug 3, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@jkotas jkotas added the arm-sve Work related to arm64 SVE/SVE2 support label Aug 3, 2026
@snickolls-arm

Copy link
Copy Markdown
Contributor Author

@dotnet/arm64-contrib Please could I have a review for this patch? There is a single test failure in some filesystem test. It seems unlikely this would trigger that, but not impossible.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates CoreCLR’s ARM64 calling convention argument/return classification to correctly treat certain value types (notably scalable Vector<T> under SVE) as passed/returned by reference when used via reflection, preventing mis-marshalling that can lead to crashes.

Changes:

  • In ArgIteratorTemplate::GetNextOffset, uses IsArgPassedByRef() (instead of a raw size check) to decide when to treat non-HFA valuetypes as byref (pointer-sized) arguments.
  • In ArgIteratorTemplate::ComputeReturnFlags, adds an ARM64-specific check based on IsArgPassedByRef(TypeHandle) to decide whether a valuetype return should use a return buffer (covers the scalable Vector<T> special-case).

Comment thread src/coreclr/vm/callingconvention.h
Comment thread src/coreclr/vm/callingconvention.h
Comment thread src/coreclr/vm/callingconvention.h
Comment thread src/coreclr/vm/callingconvention.h

@jkotas jkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let me know if you would like to make any additional changes based on my comments.

I am ok with merging the PR as is.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 1 out of 1 changed files in this pull request and generated 1 comment.

Comment on lines 1704 to 1708
else
{
// Composite greater than 16bytes should be passed by reference
if (argSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
if (IsArgPassedByRef())
{
argSize = sizeof(TADDR);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this is suggesting there is an existing bug with varargs calling convention. The block above should not identify parameters as HFA if they are varargs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, there seems to be a discrepancy. It would be best to confirm by a test that hits the problematic case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have added a test that should fail on Windows-Arm64. N.B. I have used an LLM to produce this and am using the PR to validate that it reproduces the error. We should see the varargs function call attempt to pass a struct larger than 16 bytes by value as HFA, and therefore have some information loss on that value.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The fix should be to just add the varargs check to the block above the one I've changed, but I will wait for the CI to verify the error is actually reproducible.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The repro for the problem can a lot simpler: trigger GC (via GC stress) during JITing of vararg method that's called with the problematic argument and some GC references.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just for my understanding, why is this area reachable by GC code? Does the GC walk the transition block to look for GC references?

I've added this GC test now, and will wait for the repro again before pushing the fix. The previous test also seems to reproduce the bug, so I think it's worth keeping, unless you think otherwise?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does the GC walk the transition block to look for GC references?

Yes. It typically happens when GC is triggered while the method is being JITed. The method arguments are pushed as transition block by prestub and they need to be reported to the GC.

The previous test also seems to reproduce the bug, so I think it's worth keeping, unless you think otherwise?

The profiler tests are complicated and expensive to run. They are not the best way to build regressions for corner-case VM issues.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The GC test reproduces with
Assert failure(PID 9132 [0x000023ac], Thread: 2460 [0x099c]): !CREATE_CHECK_STRING(!"Detected use of a corrupted OBJECTREF. Possible GC hole.").

So I've reverted the profiler test, and pushed 01e6544 to try and fix this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-VM-coreclr arm-sve Work related to arm64 SVE/SVE2 support community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants