Skip to content

Implement ReadyToRunGenericHelperNode for WASM - #134078

Open
jtschuster with Copilot wants to merge 4 commits into
mainfrom
copilot/implement-readytorungenerichelpernode-for-wasm
Open

jtschuster with Copilot wants to merge 4 commits into
mainfrom
copilot/implement-readytorungenerichelpernode-for-wasm

Conversation

Copilot AI commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

WASM compilation could not emit ReadyToRun generic helper stubs because their architecture-specific implementation was missing.

Changes

  • Define WASM signatures for generic lookup and delegate helpers.
  • Emit dictionary and type-context lookups.
  • Support static-base, thread-static, delegate, and handle helpers.
  • Route invalid dictionary entries to ThrowUnavailableType.

Note

This description was generated by GitHub Copilot.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
16 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 linked an issue Sep 16, 2026 that may be closed by this pull request
@github-actions github-actions Bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 16, 2026
@jtschuster jtschuster added arch-wasm WebAssembly architecture area-NativeAOT-coreclr labels Sep 16, 2026
@jtschuster
jtschuster deployed to copilot-pat-pool September 16, 2026 17:26 — with GitHub Actions Active
@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.

@jtschuster
jtschuster deployed to copilot-pat-pool September 16, 2026 17:26 — with GitHub Actions Active
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.

Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement ReadyToRunGenericHelperNode for WASM Implement ReadyToRunGenericHelperNode for WASM Sep 16, 2026
Copilot AI requested a review from jtschuster September 16, 2026 18:07
@jtschuster
jtschuster requested a lite review from Copilot September 18, 2026 16:12

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.

🟡 Changes recommended

Critical and moderate stack/dictionary-pointer issues remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds WASM ReadyToRun generic helper emission for dictionary, static-base, thread-static, delegate, type-context, and handle lookups.

Changes:

  • Defines WASM helper signatures and lookup emission.
  • Handles invalid dictionary entries via ThrowUnavailableType.
  • Supports generic static and delegate helpers.
File summaries
File Description
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunGenericHelperNode.cs Adds WASM generic helper code generation.
Review details

Suppressed comments (5)

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunGenericHelperNode.cs:125

  • ❌ The Tee preserves the index-cell value on the stack while the code also loads the type-manager pointer and thread-static index from it. Together with the initial Local.Get(0), the call stack becomes [SP, indexCell, manager, index], leaving an extra operand; the corresponding non-generic WASM helper passes only [SP, manager, index]. Consume the lookup result with Local.Set before reloading it for the two loads.

[!NOTE] This review comment was generated by GitHub Copilot.

                    expressions.Add(Local.Tee(resultLocalIndex));

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunGenericHelperNode.cs:199

  • The generic context is not at these local indices: the non-delegate signature has one parameter (so its context is local 0), and the delegate signature has three parameters (so its context is local 2). Local.Get(1)/Local.Get(3) therefore read the first uninitialized local, causing every lookup to use an invalid dictionary pointer. Load index 0 for regular helpers and index 2 for DelegateCtor, matching the argument layout used by the other target implementations.
        protected virtual void EmitLoadGenericContext(
            NodeFactory factory,
            List<WasmExpr> expressions,
            bool relocsOnly)
        {
            expressions.Add(Local.Get(Id == ReadyToRunHelperId.DelegateCtor ? 3 : 1));

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunGenericHelperNode.cs:154

  • For DelegateCtor, the third parameter is the generic context and is overwritten by EmitDictionaryLookup with the target method before invoking the constructor. Passing Local.Get(2) here also passes the unmodified generic context as a third constructor argument, shifting the lookup result and optional thunk to the wrong positions (the x64 implementation only forwards Arg0/Arg1 before replacing Arg2). Remove this expression so the constructor receives its expected arguments.
                    expressions.Add(Local.Get(0));
                    expressions.Add(Local.Get(1));
                    expressions.Add(Local.Get(2));
                    EmitDictionaryLookup(factory, expressions, contextLocalIndex, resultLocalIndex, LookupSignature, relocsOnly);

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunGenericHelperNode.cs:115

  • In the lazy-cctor GC-static path, this subtraction leaves the adjusted non-GC static-base pointer on the operand stack, but the next EmitDictionaryLookup reads contextLocalIndex, which still contains the original dictionary pointer. Store the adjusted pointer back to contextLocalIndex before the second lookup; otherwise the GC lookup is performed against the wrong dictionary.
                        GenericLookupResult nonGcRegionLookup =
                            factory.GenericLookup.TypeNonGCStaticBase((MetadataType)Target);
                        EmitDictionaryLookup(factory, expressions, contextLocalIndex, resultLocalIndex, nonGcRegionLookup, relocsOnly);
                        expressions.Add(I32.Const(NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)));
                        expressions.Add(I32.Sub);
                        EmitDictionaryLookup(factory, expressions, contextLocalIndex, resultLocalIndex, LookupSignature, relocsOnly);

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunGenericHelperNode.cs:69

  • This adds all of the WASM generic-helper code paths without a WASM regression test. The existing generic lookup R2R test is explicitly excluded on WASM (R2RTestSuites.cs:2168), and the current WASM tests only compile non-generic smoke cases, so failures in these stack layouts, helper signatures, or invalid-slot handling can regress unnoticed. Add a WASM-targeted R2R test that forces representative generic dictionary/type lookups (including a static or delegate helper) and validates that crossgen2 emits the module successfully.

[!NOTE] This review comment was generated by GitHub Copilot.

        protected sealed override void EmitCode(NodeFactory factory, ref WasmEmitter encoder, bool relocsOnly)
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

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

The lazy non-GC static-base path generates an invalid operand stack and class-constructor context.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@jtschuster
jtschuster requested a balanced review from Copilot September 24, 2026 23:40
@jtschuster jtschuster removed the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 24, 2026

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

The new code-generation paths lack targeted WASM regression coverage.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (1)

@jtschuster
jtschuster marked this pull request as ready for review September 25, 2026 00:00
@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.

This branch was successfully deployed

1 active (outdated) deployment
copilot-pat-pool — 1c9471ce Deployed Sep 16, 2026 by jtschuster via conclusion #8582
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-NativeAOT-coreclr

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Implement ReadyToRunGenericHelperNode for WASM

4 participants