[Wasm RyuJIT] Wire up GC info encoding/decoding for Wasm#126932
[Wasm RyuJIT] Wire up GC info encoding/decoding for Wasm#126932kg wants to merge 16 commits intodotnet:mainfrom
Conversation
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
There was a problem hiding this comment.
Pull request overview
This PR enables GC info encoding/decoding support for the CoreCLR WASM RyuJIT backend by turning on GCInfo generation, adding the necessary encoder/decoder sources to the WASM JIT build, and introducing a WASM-specific GC info encoding definition.
Changes:
- Enable
EMIT_GENERATE_GCINFOfor WASM and wire upCodeGen::genCreateAndStoreGCInfoto useGcInfoEncoder. - Add/adjust conditional compilation to skip register-GC-tracking paths on WASM while still enabling GC info generation.
- Update CMake wiring to link WASM standalone JITs against the appropriate
gcinfo_*library and add a universal wasm gcinfo target.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/jit/targetwasm.h | Enables GC info generation for WASM (but comment needs updating). |
| src/coreclr/jit/gcinfo.cpp | Disables register pointer marking path for WASM. |
| src/coreclr/jit/gcencode.cpp | Disables register-state-change recording for WASM. |
| src/coreclr/jit/emit.cpp | Disables register-GC live update emission for WASM. |
| src/coreclr/jit/codegenwasm.cpp | Implements GCInfo creation/emission via GcInfoEncoder for WASM. |
| src/coreclr/jit/codegenlinear.cpp | Skips GC register update/debug validation paths for WASM. |
| src/coreclr/jit/codegencommon.cpp | Skips register-based GC liveness updates/validation for WASM. |
| src/coreclr/jit/CMakeLists.txt | Ensures standalone JIT links a gcinfo lib and builds gcencode/gcdecode for WASM JIT. |
| src/coreclr/inc/gcinfotypes.h | Adds Wasm32GcInfoEncoding and sets it as the WASM target encoding. |
| src/coreclr/gcinfo/CMakeLists.txt | Adds gcinfo_universal_wasm target (currently under the wrong build condition for the failing scenario). |
|
Latest problem: with We call genEmitUnwindDebugGCandEH multiple times on some methods, and the second call attempts to overwrite existing debug information and (rightly, as far as I can tell) fails. I can't figure out why we're doing this, maybe something to do with funclets? |
This was intentional behavior - we were failing the compilation of a method as R2R unsupported late enough in compilation that debug info had already been generated, then hit an assertion the second time we tried to generate debug info (on the retried compilation). I think the asserts are just wrong in this case. Now failing with block(s) missing a bbEmitCookie in particular methods, i.e.: |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/coreclr/jit/codegencommon.cpp:1081
- This TARGET_WASM guard skips all handling of locals going live in registers. If GC-tracked locals can be assigned to Wasm locals (lvIsInReg()==true), they will bypass both the register path and the stack path here, so their liveness may never be reflected in GC info. Either ensure GC refs are never enregistered for Wasm, or add a Wasm-specific strategy to report/enforce where GC refs live at safe points (stack home or encoded register slots).
if (varDsc->lvIsInReg())
{
#ifndef TARGET_WASM
// If this variable is going live in a register, it is no longer live on the stack,
// unless it is an EH/"spill at single-def" var, which always remains live on the stack.
if (!varDsc->IsAlwaysAliveInMemory())
{
If we don't enregister a GC param then we need to add code to the prolog (or just aftert it) to spill the param to the proper stack slot. That should happen in |
OK, I managed to fix this so that we can disable enregistration for all GC values including parameters and temps. I had to collect references for orphan GT_NULLCHECKs left behind by dead block stores, because the block store was turning the address into a multiply-used temp and nothing was left to collect it. Next I need to generate the spills in the right places around calls. Do you have thoughts on where/how I should do that? Do I want to do it in lowering? |
|
After discussion with Andy we won't do spilling of temps in this PR because it's too complex, we'll do that in a follow-up PR. |
Checkpoint Checkpoint Comment out some overly sensitive asserts that can be hit when things are working as designed Funclet start blocks need labels on Wasm for some reason. Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Cleanup jit-format Compile the gc info decoder too, since we'll need it Add comment
…lready enregistered implicitly due to being params; add todo comment
…K nodes with multiply-used operands we need to collect
This set of changes is sufficient to R2R release S.P.CoreLib like before but with gc info encoding wired up and working. Still figuring out how to clean some of it up, feedback welcome.