Skip to content

Fix crossgen2 OverflowException emitting inlining info for runtime-async inliners - #134697

Open
lewing wants to merge 4 commits into
mainfrom
lewing-investigate-r2r-inlining-overflow
Open

lewing wants to merge 4 commits into
mainfrom
lewing-investigate-r2r-inlining-overflow

Conversation

@lewing

@lewing lewing commented Sep 26, 2026 •

Copy link
Copy Markdown
Member

With cross-module inlining enabled (--opt-cross-module), crossgen2 can fail while emitting the cross-module inlining info table:

System.OverflowException: Arithmetic operation resulted in an overflow.
   at ILCompiler.DependencyAnalysis.ReadyToRun.InliningInfoNode.GetData(...)

Debug builds assert _index != InvalidOffset at the same place.

Root cause

When the runtime-async variant of a cross-module generic method is compiled into the image and inlines another method, CompileMethod records a Check_IL_Body fixup for the method's typical definition, which is the AsyncMethodVariant. InliningInfoNode reduced every inliner to its primary EcmaMethod and looked up that method's Check_IL_Body import instead. Nothing ever marked that import, so it was never placed, its index stayed at int.MinValue, and the checked (uint) cast threw. For an async method the EcmaMethod is the compiler-generated thunk, so debug builds instead assert while creating the signature.

In the reported app, the failing inliner was the async variant of Task<Completion<...>>.WaitAsync(CancellationToken) (a CoreLib generic over an app type) inlining TimeProvider.get_System().

The cause is the async inlining change in #125472. #133146 probably just changed codegen enough to produce this case in the reported app. The bug isn't Wasm-specific: the new test reproduces it on osx-arm64. Browser CoreCLR R2R hits it first because its targets pass --opt-cross-module:* by default.

Fix

CompileMethod and InliningInfoNode now share ILBodyFixupSignature.GetSignatureMethodForCompiledMethod, which returns the typical EcmaMethod or AsyncMethodVariant that gets a compiled method's own Check_IL_Body fixup, or null if it can't have one. InliningInfoNode keeps one inliner entry per EcmaMethod, but stores that identity for cross-module inliners. Cross-module inliners with no such identity (async resumption stubs, return-dropping thunks, and other wrappers) or whose identity is a compiler-generated async thunk are not reported, since no Check_IL_Body import describes them. Inliners inside the version bubble are still encoded by EcmaMethod RID. When both variants inline the same method, the entry chosen doesn't depend on enumeration order. The runtime reader (inlinetracking.cpp, GetILBodyTokenInfo) uses only the module and token from these imports, so the output means the same thing. The image format is unchanged.

Validation

  • Added AsyncCrossModuleGenericInliner to the R2R test suite. It fails without the fix (on osx-arm64) and passes with it. It also covers a method whose task-returning and async variants both inline the same cross-module inlinee. The full ILCompiler.ReadyToRun.Tests suite passes locally: 35 passed, 13 skipped for platform.
  • The skip for stubs and thunks has no test. I couldn't get crossgen2 to produce a return-dropping thunk that inlines something.
  • Replayed the crossgen2 command line from the failing dotnet-inspect browser CoreCLR R2R publish (12.0.100-alpha.1.26472.116) with a Debug crossgen2 built from this branch. It now emits DotnetInspect.Web.Core.dll without asserts.

Resolves #134015

Note

This PR description was generated with GitHub Copilot.

lewing and others added 2 commits September 25, 2026 21:38
When a runtime-async variant of a cross-module generic method is compiled
into an image with --opt-cross-module and inlines another method,
CompileMethod records a Check_IL_Body fixup for the AsyncMethodVariant.
InliningInfoNode collapsed every inliner to its EcmaMethod and looked up
that method's Check_IL_Body import instead, which was never marked, so its
index was unset and the checked cast threw OverflowException (or asserted
in debug builds).

Keep the identity whose IL body fixup was recorded for cross-module
inliners while still deduplicating by EcmaMethod, and use the primary
EcmaMethod when encoding RIDs.

Fixes #134015

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

lewing commented Sep 26, 2026

Copy link
Copy Markdown
Member Author

cc @richlander

@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: @dotnet/crossgen-contrib
See info in area-owners.md if you want to be subscribed.

@lewing
lewing requested review from jtschuster and a lite review from Copilot September 26, 2026 02:53

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.

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Review effort: Lite
Findings: 1 High severity · 1 Low severity

Open (2)
What changed in this PR

Fixes crossgen2 overflow/assert failures when emitting ReadyToRun cross-module inlining information for runtime-async generic methods.

Changes:

  • Preserves the AsyncMethodVariant identity used by Check_IL_Body fixups.
  • Retains metadata-based RID encoding for stable image format compatibility.
  • Adds a regression test covering cross-module generic async inlining.
File Description
src/​coreclr/​tools/​aot/​ILCompiler.ReadyToRun/​Compiler/​DependencyAnalysis/​ReadyToRun/​InliningInfoNode.cs Updated as part of this pull request.
src/​coreclr/​tools/​aot/​ILCompiler.ReadyToRun.Tests/​TestCases/​R2RTestSuites.cs Updated as part of this pull request.
src/​coreclr/​tools/​aot/​ILCompiler.ReadyToRun.Tests/​TestCases/​CrossModuleInlining/​Dependencies/​AsyncCrossModuleGenericLib.cs Updated as part of this pull request.
src/​coreclr/​tools/​aot/​ILCompiler.ReadyToRun.Tests/​TestCases/​CrossModuleInlining/​AsyncGenericInlinerConsumer.cs Updated as part of this pull request.

Compiler-generated async thunks cannot carry a Check_IL_Body fixup, so
don't report them as cross-module inliners. Extend the regression test so
both the task-returning method and its async variant inline the same
cross-module inlinee.

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

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.

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (2)

…foNode

Only report a cross-module inliner when it has its own Check_IL_Body
fixup, using the same identity CompileMethod creates the fixup for.
Return-dropping thunks, resumption stubs, and other wrappers that
unwrap to an EcmaMethod no longer borrow that method's import.

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

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.

Copilot review overview

🔵 Needs a closer look

The changes require final human review because they are too complex or risky for automated approval.

Review effort: Lite
Findings: None

Resolved since last review (1)

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET 12 wasm: System.OverflowException: Arithmetic operation resulted in an overflow

2 participants