Skip to content

Fix NativeAOT RVA field handle scanning - #132439

Open
jkoritzinsky wants to merge 3 commits into
dotnet:mainfrom
jkoritzinsky:nativeaot-directed
Open

Fix NativeAOT RVA field handle scanning#132439
jkoritzinsky wants to merge 3 commits into
dotnet:mainfrom
jkoritzinsky:nativeaot-directed

Conversation

@jkoritzinsky

@jkoritzinsky jkoritzinsky commented Aug 17, 2026

Copy link
Copy Markdown
Member

NativeAOT's IL scanner historically skipped reflection dependencies for every RVA field token because most are consumed by RuntimeHelpers.InitializeArray or CreateSpan<T>. After runtime field handles switched to reflection metadata records, an RVA ldtoken that survives code generation can therefore reach GetMetadataHandleForField without a corresponding map entry and crash the compiler.

Restore normal metadata dependencies for RVA field handles, and suppress them only when a dedicated RvaIntrinsicPatternAnalyzer proves that RyuJIT will expand the intrinsic. The analyzer follows the same state-machine pattern as the existing type-equality and isinst analyzers and mirrors RyuJIT's IL shape, type, size, overflow, and RVA-data checks for both InitializeArray and CreateSpan<T>.

Validation:

  • .\build.cmd clr.aot -c Debug
  • src\tests\build.cmd -Rebuild -Test JIT\Directed\Directed_r.csproj -Test JIT\Directed\Directed_d.csproj -Test JIT\Intrinsics\CreateSpan_il.ilproj x64 Debug -Priority 1 -NativeAOT -SkipNative /p:LibrariesConfiguration=Debug
  • Optimized scanner metadata inspection confirmed that the bare catch2 field handle is retained while valid InitializeArray and CreateSpan<T> RVA blobs are not retained as reflection metadata.

Fixes #132266

Note

This pull request description was generated by GitHub Copilot.

Populate field metadata handles from the field handle nodes that survive final dependency analysis instead of reflection runtime mappings. Keep scanner-only RVA handles from retaining metadata and include owning type metadata for materialized handles.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ec90a5ea-59c4-419e-90e5-b6590ef37c11
@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.

@jkoritzinsky

Copy link
Copy Markdown
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

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 NativeAOT metadata generation so RuntimeFieldHandle-backed fields (including RVA-backed fields) have consistent, dependency-graph-local metadata handle mappings, avoiding KeyNotFoundException during compilation when a field handle is materialized without a reflection runtime mapping.

Changes:

  • Track field/type definitions referenced by RuntimeFieldHandle nodes in the final dependency graph.
  • Populate the field-handle metadata mapping from the same tracked set that drives metadata emission.
  • Extend metadata policies (usage-based and analysis-based) to consider runtime-field-handle-driven metadata requirements.

Reviewed changes

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

Show a summary per file
File Description
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs Ensures fields/types referenced via runtime field handles are treated as metadata-generating in the usage-based policy.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs Tracks runtime field-handle fields/types during graph marking and uses that set to drive metadata emission and handle lookup.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs Exposes the target field for graph-level tracking.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs Exposes the field for generic-dictionary ldtoken field-handle slot tracking.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs Ensures fields/types referenced via runtime field handles are treated as metadata-generating in the analysis-based policy.

Comment thread src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs Outdated
@MichalStrehovsky

Copy link
Copy Markdown
Member

On the phone now, but I think it would be better to do #86373 differently: undo the md manager change from that PR, restore the scanner code, and tighten the rules in the scanner so that it matches intrinsic expansion rules in RyuJIT (the problem with previous code was that it was not tight enough and sometimes declared we're going to intrinsically expand when RyuJIT didn't and that's a crash).

Another alternative would be to always emit RuntimeFieldHandle for RVA fields with a zero token (with a comment pointing to the MD manager code that skips dependency analysis).

What this PR is doing touches too many components for what is essentially a workaround for the md manager hack added in #86373.

The hack stopped being valid after #113413: before that PR in a situation like this we would emit a RuntimeFieldHandle that doesn't resolve; after that PR, we get a crash.

Mirror RyuJIT's InitializeArray and CreateSpan expansion rules in a dedicated IL scanner pattern analyzer. Restore normal reflection metadata dependencies for RVA field handles that are not consumed by expanded intrinsics.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ec90a5ea-59c4-419e-90e5-b6590ef37c11
Copilot AI review requested due to automatic review settings August 19, 2026 20:56
@jkoritzinsky jkoritzinsky changed the title Fix NativeAOT runtime field handle metadata Fix NativeAOT RVA field handle scanning Aug 19, 2026
@jkoritzinsky

Copy link
Copy Markdown
Member Author

I've reverted the workaround of the hack and instead implemented the intrinsic expansion to match RyuJIT directly.

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 5 out of 5 changed files in this pull request and generated no new comments.

@MichalStrehovsky

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@MichalStrehovsky MichalStrehovsky 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.

Thank you!

@jkoritzinsky
jkoritzinsky enabled auto-merge (squash) August 20, 2026 05:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

ILC KeyNotFoundException in RuntimeFieldHandleNode.GetDehydratableData compiling NativeAOT tests

3 participants