FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[wasm] Ensure R2R entry-point PEP is callable in RunMain by lewing · Pull Request #131217 · dotnet/runtime · GitHub

Repository navigation

[wasm] Ensure R2R entry-point PEP is callable in RunMain - #131217

Merged
lewing merged 1 commit into
dotnet:mainfrom
lewing:wasm-r2r-runmain-pep
Jul 22, 2026
Merged

lewing merged 1 commit into
dotnet:mainfrom
lewing:wasm-r2r-runmain-pep

Conversation

lewing commented Jul 22, 2026

Copy link
Copy Markdown
Member

[wasm] Ensure R2R entry-point PEP is callable in RunMain

Summary

On WebAssembly, the managed program entry point is invoked from R2R-compiled code:
System.Environment.CallEntryPoint performs an indirect call through the entry
point's address. When the entry point resolves to a PortableEntryPoint (PEP) whose
actualCode slot has not yet been populated, that indirect call_indirect targets an
uninitialized table slot and the module traps (uninitialized element) — or, when the
condition arises on a cold path, the runtime falls back to interpreter execution for
the entire process instead of running R2R code.

This adds the missing call to MethodDesc::EnsurePortableEntryPointIsCallableFromR2R
in RunMainInternal (right after the entry-point address is materialized via
GetSingleCallableAddrOfCode()), so the entry-point PEP is published to real code
(native R2R body or a correctly-typed interpreter thunk) before it is invoked.

    pParam->pFD->EnsureActive();
    PCODE entryPoint = pParam->pFD->GetSingleCallableAddrOfCode();
#ifdef FEATURE_PORTABLE_ENTRYPOINTS
    // The entry point is invoked from R2R-compiled code (Environment.CallEntryPoint performs an
    // indirect call through this address), so it must resolve to real code (native R2R or a
    // correctly-typed interpreter thunk) rather than an uninitialized portable entry point.
    MethodDesc::EnsurePortableEntryPointIsCallableFromR2R(entryPoint);
#endif // FEATURE_PORTABLE_ENTRYPOINTS

Motivation

The helper MethodDesc::EnsurePortableEntryPointIsCallableFromR2R and its sibling
call-sites are already on main (introduced by #130386 and #130841). Those PRs cover
finalizer slots, FCall/PInvoke helpers, class constructors, string constructors, and
prestub paths — but not the program entry point invoked by RunMain. As a result,
a ReadyToRun WASM image that dispatches its Main through Environment.CallEntryPoint
can hit an uninitialized PEP and either trap or degrade to whole-program interpreter
execution.

This is the last uncovered publication site on the hello-world startup path. It is a
6-line addition scoped entirely under #ifdef FEATURE_PORTABLE_ENTRYPOINTS, which is
set only for CLR_CMAKE_TARGET_ARCH_WASM (see src/coreclr/clrfeatures.cmake), so it
has zero effect on non-wasm targets.

Validation

Measured on a composite R2R WASI "Hello world" (CoreLib + System.Runtime +
System.Console, crossgen'd --composite --targetos:wasi --targetarch:wasm, run under
wasmtime).

A robust health signal for "R2R actually executes" (as opposed to the program merely
surviving via interpreter fallback) is whether two guaranteed-reached corelib bodies —
System.String..ctor and System.SpanHelpers.Memmove — execute as R2R, together with
the absence of TryPublishR2R FAILED diagnostics.

Build String..ctor R2R hits Memmove R2R hits TryPublishR2R FAILED
Without this fix (entry-point PEP uninitialized) 0 0 5
With this fix 7 8 0

With the fix, the two guaranteed-reached bodies run as native R2R, the reverse-thunk
fallback diagnostics disappear entirely, and the app prints its output and exits 42.
Result independently reproduced across three builds (identical 7 / 8 / 0 counts).

Note: exit code alone is not a sufficient signal — an image with the entry-point
PEP uninitialized can still print and exit 42 while executing zero R2R bodies (pure
interpreter fallback). The String..ctor + Memmove execution check is the meaningful
gate.

Risk

  • Scoped to wasm only via FEATURE_PORTABLE_ENTRYPOINTS.
  • Uses an existing, already-merged helper; no new API surface.
  • Mirrors the established pattern of the other EnsurePortableEntryPointIsCallableFromR2R
    call-sites already on main.

Original prototype commit: wasm: ensure R2R entry-point PEP is callable in RunMain
(authored by Andy Ayers).

Note

This PR description was drafted with GitHub Copilot.

The managed entry point is invoked from R2R-compiled code
(System.Environment.CallEntryPoint performs an indirect call through this
address), so it must resolve to real code (native R2R or a correctly-typed
interpreter thunk) rather than an uninitialized portable entry point.

Adds the missing MethodDesc::EnsurePortableEntryPointIsCallableFromR2R
publication in RunMainInternal, scoped under FEATURE_PORTABLE_ENTRYPOINTS
(wasm-only). The helper and its sibling call-sites are already on main
(dotnet#130386, dotnet#130841); this covers the program entry-point path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2902374a-f352-4c46-bcec-8a35c97733ae
Copilot AI review requested due to automatic review settings July 22, 2026 14:02

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.

Copy link
Copy Markdown
Contributor

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

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Pull request overview

Ensures that on FEATURE_PORTABLE_ENTRYPOINTS targets (Wasm), the managed program entry point returned from MethodDesc::GetSingleCallableAddrOfCode() is made callable from R2R code before it’s passed to Environment.CallEntryPoint, preventing indirect-call traps / interpreter fallback when the entry point is a cold PortableEntryPoint.

Changes:

  • Add a #ifdef FEATURE_PORTABLE_ENTRYPOINTS call to MethodDesc::EnsurePortableEntryPointIsCallableFromR2R(entryPoint) in RunMainInternal, immediately after materializing the entry point address.

lewing marked this pull request as ready for review July 22, 2026 14:43

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.

lewing commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

/ba-g this is a wasm only change and the failing mac pipelines are overloaded

lewing merged commit 78fd36e into dotnet:main Jul 22, 2026
108 of 112 checks passed
lewing deleted the wasm-r2r-runmain-pep branch July 22, 2026 20:24
dotnet-milestone-bot Bot added this to the 11.0-rc1 milestone Jul 24, 2026
github-actions Bot locked and limited conversation to collaborators Aug 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants


Back | FazBrowse Home | New Git URL