Repository navigation
Description
Summary
crossgen2 aborts with an unhandled NotImplementedException when compiling browser-wasm ReadyToRun images that combine embedded PGO instrumentation data (--embed-pgo-data) with cross-module optimization (--opt-cross-module:*).
This blocks per-app R2R publish on any build leg where EnableNgenOptimization=true (e.g. the checked CI legs), because eng/codeOptimization.targets then sets IncludeMibcFilesInReadyToRun=true, feeds StandardOptimizationData.mibc, and appends --embed-pgo-data to the crossgen2 command line.
Repro
- Build CoreCLR + libraries for
browser-wasmwithEnableNgenOptimization=true(thecheckedlibraries legs qualify). - Publish a
browser-wasmapp withPublishReadyToRun=trueso the crossgen2 command line includes both--embed-pgo-dataand--opt-cross-module:*.- In CI this is the
browser-wasm linux checked CoreCLR_ReleaseLibrariesandbrowser-wasm windows checked CoreCLR_ReleaseLibrarieslegs.
- In CI this is the
- crossgen2 crashes:
artifacts/bin/Crossgen2Tasks/Release/Microsoft.NET.CrossGen.targets(497,5): error MSB6006:
".../crossgen2" exited with code 134 (linux) / 57005 (windows)
Microsoft.NET.CrossGen.targets(377,5): error NETSDK1096: Optimizing assemblies for performance failed.
Underlying exception (captured from a checked crossgen2 run):
System.NotImplementedException: [System.Text.Json]System.Text.Json.JsonDocument+<ReadToEndAsync>d__85
at ...DependencyAnalysis.ReadyToRun.ModuleTokenResolver.GetModuleTokenForType(TypeDesc, bool, bool)
in ModuleTokenResolver.cs:line 92
at ...SignatureBuilder.EmitMethodSignature(...)
at ...InstanceEntryPointTableNode.BuildSignatureForMethodDefinedInModule(MethodDesc, NodeFactory)
at ...InstrumentationDataTableNode.GetData(NodeFactory, bool) in InstrumentationDataTableNode.cs:line 274
at ...ReadyToRunObjectWriter.EmitReadyToRunObjects(...)
Root cause
InstrumentationDataTableNode.GetData emits a method signature for every method carrying PGO data via InstanceEntryPointTableNode.BuildSignatureForMethodDefinedInModule (InstrumentationDataTableNode.cs#L274). Building that signature resolves module tokens for the types referenced in the method's signature through ModuleTokenResolver.GetModuleTokenForType(type, allowDynamicallyCreatedReference, throwIfNotFound: true).
For a cross-module method whose signature references a type that has no token in any module of the cross-module compile group (here the async state machine System.Text.Json...JsonDocument+<ReadToEndAsync>d__85), every reverse-lookup branch fails and the resolver throws NotImplementedException (ModuleTokenResolver.cs#L90-L92).
Notes:
- Specific to the
--embed-pgo-data+--opt-cross-modulecombination. TheReleaselegs don't setEnableNgenOptimization, so they don't embed PGO and don't crash. - Not a wasm-JIT NYI, so
JitWasm{,Simd}NyiToR2RUnsupporteddoes not help. - There is no wasm-specific PGO profile —
eng/codeOptimization.targetsfeeds the genericStandardOptimizationData.mibcfor all targets, so the mibc contents are not the trigger; the emission path is.
Fix proposal
Make the instrumentation-data signature emitter tolerate a method whose signature can't be tokenized in the current cross-module group instead of hard-crashing:
- In the
InstrumentationDataTableNodepath, resolve tokens withthrowIfNotFound: falseand skip (drop the PGO entry for) any method whose signature can't be fully resolved; or - Ensure the referenced types are added to the manifest / version-bubble module so a token exists; or
- Exclude such cross-module methods from the embedded PGO set up front.
Temporary workaround (applied on the wasm R2R branch)
Disable --embed-pgo-data / IncludeMibcFilesInReadyToRun for browser/wasi per-app R2R in eng/codeOptimization.targets (there is no wasm PGO profile to gain from), with a TODO linking to this issue. To be reverted once the crossgen2 fix above lands.
Note
This issue description was generated with the assistance of GitHub Copilot.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
dotnet-policy-service commentedon Aug 27, 2026
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.
pavelsavara commentedon Aug 27, 2026
@davidwrighton which fix proposal above looks best ?
[wasm] Small R2R bring-up prerequisites for browser/wasi
[wasm] Small R2R bring-up prerequisites for browser/wasi
[wasm] Small R2R bring-up prerequisites for browser/wasi
davidwrighton commentedon Sep 15, 2026
@pavelsavara, we should never be embedding pgo data when we build for wasm. It is a configuration that doesn't make sense since the interpreter can't use the data. The incompatibility with
--opt-cross-moduleis unfortunate though, and might have other impacts on other platforms if we ever get embedded pgo data to actually be particularly useful.Allow intrinsic roots in partial no-JIT compilations (#134030)
Allow intrinsic roots in partial no-JIT compilations (dotnet#134030)
Add method-list MIBC writer to dotnet-pgo (#134566)