Skip to content

[browser][CoreCLR] Resolve ReadyToRun addresses for EventPipe - #134026

Merged
lewing merged 3 commits into
dotnet:mainfrom
lewing:lewing-fix-wasm-r2r-addresses
Sep 16, 2026
Merged

lewing merged 3 commits into
dotnet:mainfrom
lewing:lewing-fix-wasm-r2r-addresses

Conversation

@lewing

@lewing lewing commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

Summary

Fix EventPipe method load, rundown, and IL-to-native-map resolution for ReadyToRun methods on CoreCLR browser-Wasm.

On TARGET_WASM with FEATURE_PORTABLE_ENTRYPOINTS, ReadyToRunInfo::GetEntryPoint publishes a callable PortableEntryPoint whose actual code is a global Wasm function-table index. The corresponding MethodDesc and ReadyToRunJitManager range are registered under a synthetic virtual IP. EventPipe previously passed the portable-entrypoint address to EECodeInfo, which could not resolve it through ExecutionManager; the existing EECodeInfo::IsValid guard then omitted the R2R method event.

MethodAndStartAddressToEECodeInfoPointer now preserves interpreter resolution first, then translates a native Wasm portable entrypoint's function-table index through ExecutionManager::GetWasmVirtualIPFromFunctionTableIndex. Keeping the conversion in the shared EventPipe helper covers both method events and IL-to-native-map events. The existing mapping also preserves controlling-method behavior for funclet indices.

Non-Wasm behavior, explicit JIT code addresses, interpreter bytecode addresses, generic method handling, and the EECodeInfo::IsValid defense remain unchanged.

The browser CPU-sampling test is re-enabled for CoreCLR and now verifies both:

  • the sampled application frame for Counter.IncrementCount; and
  • on CoreCLR, rundown resolution for the ReadyToRun System.Buffer.Memmove framework method.

Validation

  • ./build.sh clr+libs+host
  • ./build.sh clr
  • PATH="/opt/homebrew/bin:$PATH" ./build.sh -os browser -arch wasm -c Release -subset clr+libs -cmakeargs "-DCMAKE_CXX_FLAGS=-Wno-error=unguarded-availability-new"
    • The warning suppression is limited to an unrelated Xcode pipe2 availability diagnostic in the host-side universal-Wasm JIT build.
  • Wasm.Build.Tests.Blazor.EventPipeDiagnosticsTests on CoreCLR browser-Wasm, workload lane: 4 passed, 0 failed, 0 skipped (metrics, heap dump, and CPU samples in Debug and Release).

A mutation attempt that removed only the address conversion could not provide trustworthy red evidence because the local workload installation cached a runtime pack with the same package version. The final fixed browser runtime and strengthened end-to-end tests were rebuilt and rerun successfully.

Resolves #132410

Note

This pull request description was generated with the assistance of GitHub Copilot.

lewing and others added 2 commits September 15, 2026 22:41
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@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.

@lewing
lewing requested a review from radekdoulik September 16, 2026 04:16
@lewing lewing added the arch-wasm WebAssembly architecture label Sep 16, 2026
@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.

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

Fix the EventPipe contract boundary and guard the ReadyToRun assertion for CoreCLR-only runs.

Get a fresh assessment by requesting another Copilot review.

Review tier: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Fixes WASM EventPipe ReadyToRun address and symbol resolution.

Changes:

  • Maps R2R function-table indices to synthetic virtual IPs.
  • Extends diagnostics coverage for System.Buffer.Memmove.
  • Removes the prior CoreCLR issue suppression.
File Summary
src/​mono/​wasm/​Wasm.Build.Tests/​Blazor/​EventPipeDiagnosticsTests.cs Adds ReadyToRun symbol validation.
src/​coreclr/​vm/​eventtrace.cpp Resolves WASM R2R entry points for EventPipe.

Comment thread src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 16, 2026 04:34
@lewing lewing changed the title [wasm] fix eventtrace r2r addresses [browser][CoreCLR] Resolve ReadyToRun addresses for EventPipe Sep 16, 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

🟢 Approval recommended

No unresolved blocking issues were identified.

Review tier: Lite
Findings: None

Resolved since last review (1)

@pavelsavara

Copy link
Copy Markdown
Member

This is failing on CI. The problem is that this sampling profiler. You are not guaranteed to hit the method always.

image
        <failure exception-type="Xunit.Sdk.TrueException">
          <message><![CDATA[The cpuprofile.nettrace should contain rundown information for the ReadyToRun 'System.Buffer.Memmove' method]]></message>
          <stack-trace><![CDATA[   at Wasm.Build.Tests.Blazor.EventPipeDiagnosticsTests.BlazorEventPipeTestWithCpuSamples(Configuration config, Boolean aot) in /_/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs:line 97
--- End of stack trace from previous location ---]]></stack-trace>
        </failure>

@lewing

jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 18, 2026
…#134026)

## Summary

Fix EventPipe method load, rundown, and IL-to-native-map resolution for
ReadyToRun methods on CoreCLR browser-Wasm.

On `TARGET_WASM` with `FEATURE_PORTABLE_ENTRYPOINTS`,
`ReadyToRunInfo::GetEntryPoint` publishes a callable
`PortableEntryPoint` whose actual code is a global Wasm function-table
index. The corresponding `MethodDesc` and `ReadyToRunJitManager` range
are registered under a synthetic virtual IP. EventPipe previously passed
the portable-entrypoint address to `EECodeInfo`, which could not resolve
it through `ExecutionManager`; the existing `EECodeInfo::IsValid` guard
then omitted the R2R method event.

`MethodAndStartAddressToEECodeInfoPointer` now preserves interpreter
resolution first, then translates a native Wasm portable entrypoint's
function-table index through
`ExecutionManager::GetWasmVirtualIPFromFunctionTableIndex`. Keeping the
conversion in the shared EventPipe helper covers both method events and
IL-to-native-map events. The existing mapping also preserves
controlling-method behavior for funclet indices.

Non-Wasm behavior, explicit JIT code addresses, interpreter bytecode
addresses, generic method handling, and the `EECodeInfo::IsValid`
defense remain unchanged.

The browser CPU-sampling test is re-enabled for CoreCLR and now verifies
both:

- the sampled application frame for `Counter.IncrementCount`; and
- on CoreCLR, rundown resolution for the ReadyToRun
`System.Buffer.Memmove` framework method.

## Validation

- `./build.sh clr+libs+host`
- `./build.sh clr`
- `PATH="/opt/homebrew/bin:$PATH" ./build.sh -os browser -arch wasm -c
Release -subset clr+libs -cmakeargs
"-DCMAKE_CXX_FLAGS=-Wno-error=unguarded-availability-new"`
- The warning suppression is limited to an unrelated Xcode `pipe2`
availability diagnostic in the host-side universal-Wasm JIT build.
- `Wasm.Build.Tests.Blazor.EventPipeDiagnosticsTests` on CoreCLR
browser-Wasm, workload lane: **4 passed, 0 failed, 0 skipped** (metrics,
heap dump, and CPU samples in Debug and Release).

A mutation attempt that removed only the address conversion could not
provide trustworthy red evidence because the local workload installation
cached a runtime pack with the same package version. The final fixed
browser runtime and strengthened end-to-end tests were rebuilt and rerun
successfully.

Resolves dotnet#132410

> [!NOTE]
> This pull request description was generated with the assistance of
GitHub Copilot.

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
lewing added a commit that referenced this pull request Sep 29, 2026
…4754)

## Summary

State-machine (V1) async profiler callstack frames identify methods by
`AsyncStateMachineDiagnostics<T>.MethodId`, which comes from
`RuntimeMethodHandle_GetNativeCode` on `MoveNext`. On Wasm ReadyToRun, a
method's entry point is a `PortableEntryPoint` whose actual code is a
function-table index. `EECodeInfo` can't resolve that index, so
`StackFrame.GetMethodFromNativeIP` returned nothing and the frame names
were lost.

EventPipe method events already mapped these entry points to the
synthetic virtual IP registered through
`ExecutionManager::AddVirtualIPRange` (#134026). This PR moves that
mapping into a shared `GetDiagnosticCodeStartFromEntryPoint` helper in
`precode.cpp`, used by both EventPipe and
`RuntimeMethodHandle_GetNativeCode`. The only managed caller of that
QCall is `AsyncStateMachineDiagnostics`.

- The mapping is gated on both `TARGET_WASM` and
`FEATURE_PORTABLE_ENTRYPOINTS`. Treating the actual code as a
function-table index is a Wasm fact, and
`GetWasmVirtualIPFromFunctionTableIndex` is declared only under
`TARGET_WASM`. Other portable-entrypoint targets would store a real code
address that `EECodeInfo` already resolves.
- `PortableEntryPoint::GetActualCode` goes from `STANDARD_VM_CONTRACT`
to `LIMITED_METHOD_CONTRACT`. It only reads a field, and its callers
include this `NOTHROW`/`GC_NOTRIGGER` helper and the cooperative-mode
interpreter. That matches its siblings `HasNativeEntryPoint` and
`SetActualCode`.
- The three `ActiveIssue` annotations for #134145 are removed.

## Validation

Browser CoreCLR, Release, `TestWasmReadyToRun=true`,
`EnableAggressiveTrimming=true`, Chrome:

- The three re-enabled `StateMachineAsync_*_ChainEventsAndCallstack`
tests: **3/3 pass**. With only the `runtimehandles.cpp` change reverted
and the runtime rebuilt: **0/3**.
- Whole `AsyncProfilerTests` class: 136 run, **61 passed, 0 failed**, 75
skipped by existing platform conditions.

Not validated: a Debug/Checked browser build, where contracts are
enforced. Non-Wasm builds compile the new mapping out.

## Follow-up

The cDAC has the same gap for SOS native code addresses on
portable-entrypoint targets: #134753.

Resolves #134145

> [!NOTE]
> This pull request description was generated with GitHub Copilot.

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-Tracing-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] R2R: EventPipe rundown traps with null function and omits precompiled method events

3 participants