Skip to content

[wasm][R2R] Create manifest token when type reference wasn't pre-registered - #131651

Open
pavelsavara wants to merge 1 commit into
dotnet:mainfrom
pavelsavara:wasm-r2r-manifest-token-fix
Open

[wasm][R2R] Create manifest token when type reference wasn't pre-registered#131651
pavelsavara wants to merge 1 commit into
dotnet:mainfrom
pavelsavara:wasm-r2r-manifest-token-fix

Conversation

@pavelsavara

Copy link
Copy Markdown
Member

Summary

Fixes a crossgen2 ReadyToRun compilation failure that is specific to the WebAssembly target.

Problem

When crossgen2 targets WebAssembly, a method that would normally register a type token during IL token resolution can be skipped by the JIT (JitWasmNyiToR2RUnsupported), while a TypeFixupSignature for that type is still emitted. At manifest emission time, ModuleTokenResolver.GetModuleTokenForType does a reverse lookup via _manifestMutableModule.TryGetExistingEntityHandle(type), which returns null because nothing pre-registered the reference. The resolver then falls through to throw new NotImplementedException(...), which aborts the R2R compile.

This was observed while R2R-compiling System.Runtime.InteropServices.JavaScript.dll for browser-wasm, where the reverse lookup fails for [S.P.CoreLib]System.Reflection.MemberInfo.

Fix

In the allowDynamicallyCreatedReference branch, when the existing-handle lookup returns null, create the manifest reference on demand via _manifestMutableModule.TryGetEntityHandle(type), guarded by !DisableNewTokens so it only runs while new tokens are still allowed (this path executes before ManifestMetadataTableNode sets DisableNewTokens). This mirrors how other manifest references are produced.

Notes

  • Scoped to a single method. The added code only runs when the pre-existing reverse lookup fails, so there is no behavior change for the PE/x64 path where the type is already registered.

Note

This change and description were prepared with the assistance of GitHub Copilot.

…stered

When crossgen2 targets WebAssembly, a method that would have registered a type token during IL token resolution can be skipped by the JIT (JitWasmNyiToR2RUnsupported) while a TypeFixupSignature for that type still exists. GetModuleTokenForType's reverse lookup (TryGetExistingEntityHandle) then returns null and the resolver throws NotImplementedException, failing the R2R compile.

Create the manifest reference on demand via TryGetEntityHandle while new tokens are still allowed (before ManifestMetadataTableNode sets DisableNewTokens), mirroring how other manifest references are produced.
Copilot AI review requested due to automatic review settings July 31, 2026 15:24
@github-actions github-actions Bot added the area-crossgen2-coreclr only use for closed issues label Jul 31, 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.

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

Fixes a crossgen2 ReadyToRun compilation failure path by allowing ModuleTokenResolver.GetModuleTokenForType to create a manifest metadata reference on-demand when the existing reverse lookup can’t find a pre-registered handle.

Changes:

  • Add a fallback in GetModuleTokenForType to call MutableModule.TryGetEntityHandle(type) when TryGetExistingEntityHandle(type) returns null.
  • Guard the fallback on DisableNewTokens to avoid creating new metadata tokens during the “no new tokens” phase.

// method that would have registered it was skipped by the JIT (JitWasmNyiToR2RUnsupported) yet a
// fixup for the type still exists. Dynamically create the manifest reference while new tokens are
// still allowed (this runs before ManifestMetadataTableNode sets DisableNewTokens).
if (!_manifestMutableModule.DisableNewTokens)
@pavelsavara pavelsavara added the arch-wasm WebAssembly architecture label Jul 31, 2026
@pavelsavara pavelsavara added this to the 11.0.0 milestone Jul 31, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

@adamperlin

Copy link
Copy Markdown
Contributor

This looks reasonable to me aside from the copilot feedback above about a possible synchronization issue. Can we open an issue to revisit this if possible? Hopefully JitNyiWasmToR2RUnsupported will be able to go away soon, in which case we should remember to remove this workaround.

@pavelsavara

Copy link
Copy Markdown
Member Author

possible synchronization issue

Is there better way how to do this ? This is a lookup with side-effects.
Could we for example insert such token as the time when we emit JitNyiWasmToR2RUnsupported ?

@AndyAyersMS

Copy link
Copy Markdown
Member

I think we will still need/want the ability for the JIT to fail to produce R2R even after we've removed the blanket NYI_WASM fail-over.

So crossgen needs to tolerate this failure cleanly. It feels to me like it is committing to emit some things too early, before we know for sure if the method is going to be R2R'd. And so we end up trying to emit something partial. This fix may be a reasonable workaround for now, but I think there may be a better approach out there.

@jkoritzinsky

Copy link
Copy Markdown
Member

I think this fixing a similar issue as #131610. Can we do a similar fix here as we have in that pr?

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

Labels

arch-wasm WebAssembly architecture area-crossgen2-coreclr only use for closed issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants