Repository navigation
Description
R2R composite for the startup set (follow-up to per-assembly)
Part of #130524.
Status: draft / issue candidate · Area: CoreCLR-on-WASM, precompilation/R2R · Related: #130522 (R2R over in-memory IL), #130523 (sharded IL), D4 · Builds on the upstream per-assembly R2R + webcil-in-wasm async-load foundation (#129634).
Goal
Combine the per-assembly startup R2R images into a single composite image, so the precompiled startup and hot code ships and loads as one unit rather than many per-assembly files. This is the follow-up to the first prototype's per-assembly R2R (D4).
Why
Per-assembly R2R is the simplest first step, but many small images mean more files, more per-image load/instantiate/fixup overhead, and cross-image calls that go through import indirection. A composite consolidates the startup set into one image with direct intra-composite calls and a single load — better code quality (fewer cross-image thunks) and more efficient startup load.
Direction
- One composite for the profile-selected startup + hot set, instead of one image per assembly.
- Direct intra-composite calls; calls out to code not in the composite fall back through the normal import/interpreter path.
- Browser-loadable packaging. The composite must be emitted in the loadable-on-WASM form, not a desktop-only shape.
- Coordinate with in-memory-IL reuse ([browser][coreCLR] R2R: R2R that loads against IL already in memory #130522) and sharded IL ([browser][coreCLR] R2R: IL splitter — shard trimmed assemblies by namespace #130523). The composite binds against the resident IL the same way the per-assembly images do, including when that IL is a facade plus shards.
Scope
In: producing a single startup composite from the profile; loadable-on-WASM packaging; direct intra-composite calls with coherent fallback.
Out: the per-assembly R2R baseline (the prototype path); lazily-streamed shard R2R; the IL splitter/consumer.
Success criteria
- The startup hot set ships and loads as one composite; behavior identical to the per-assembly set.
- Measurable reduction in cross-image thunking and/or load overhead versus per-assembly R2R.
Open questions
- Whether the composite container is fully browser-loadable today or needs work (the component-file form may be desktop-shaped).
- How the composite interacts with the in-memory-IL reuse ([browser][coreCLR] R2R: R2R that loads against IL already in memory #130522) and sharded-IL ([browser][coreCLR] R2R: IL splitter — shard trimmed assemblies by namespace #130523) layouts.
- Selection boundary: exactly which assemblies/methods go in the startup composite versus stay per-assembly or lazy.
Note
This issue was drafted with GitHub Copilot assistance.
Activity
dotnet-policy-service commentedon Jul 10, 2026
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.
[-][browser][coreCLR] R2R: X6 — R2R composite for the startup set[/-][+][browser][coreCLR] R2R: R2R composite for the startup set[/+]dotnet-policy-service commentedon Jul 15, 2026
Tagging subscribers to this area: @agocke, @elinor-fung
See info in area-owners.md if you want to be subscribed.
lewing commentedon Jul 18, 2026
Re: the open question "Whether the composite container is fully browser-loadable today or needs work (the component-file form may be desktop-shaped)" —
It loads today with a small, OS-neutral VM change (~30 lines,
TARGET_WASM). crossgen2 emits the startup composite as a flat webcil-in-wasm image, but the R2R/PE-decoder path assumes a mapped PE (a namedRTR_HEADERexport +IsMapped()RVA addressing), so out of the box it can't find the R2R header or address sections in a flat webcil composite. Four touch-points close that:vm/nativeimage.cppRTR_HEADERexport → fall back to the decoder's R2R headervm/readytoruninfo.cppIsWebcilFormat()alongsideIsMapped())vm/peimagelayout.inlIsComponentAssembly()through the webcil decoder (DECODER_DISPATCH)vm/peimagelayout.cppApplyBaseRelocationsover the same memory doubles the additive wasm table-index relocs)Notes:
TARGET_WASM/FEATURE_PORTABLE_ENTRYPOINTS, so the same code serves browser (this issue / [browser][coreCLR] R2R on WebAssembly (R1) — tracking #130524) and wasi from one path.peimagelayout.cppreloc-guard is only really exercised by the wasi single-shared-buffer host probe; on browser each probe open gets a fresh buffer, soApplyBaseRelocationsruns once per image and the guard is an inert no-op there.Validated on the prototype: a composite CoreLib R2R image (~49k R2R functions) loads and dispatches through these four changes. Happy to put up a small draft PR against
mainwith just these files if it's useful for the composite work.Note
Drafted with GitHub Copilot assistance.
[wasm][coreCLR] R2R: VM-side load of a flat webcil composite image
[wasm][coreCLR] R2R: VM-side load of a flat webcil composite image
[wasm][coreCLR] R2R: VM-side load of a flat webcil composite image
[wasm][coreCLR] R2R: VM-side load of a flat webcil composite image
[wasm][coreCLR] R2R: VM-side load of a flat webcil composite image (#…
[wasm][coreCLR] R2R: VM-side load of a flat webcil composite image (d…
[-][browser][coreCLR] R2R: R2R composite for the startup set[/-][+][browser][coreCLR] R2R: R2R single file composite for the startup set[/+]