Skip to content

Fix Wasm R2R exceptions escaping filters - #133932

Merged
lewing merged 10 commits into
dotnet:mainfrom
lewing:lewing-fix-issue-133468
Sep 17, 2026
Merged

lewing merged 10 commits into
dotnet:mainfrom
lewing:lewing-fix-issue-133468

Conversation

@lewing

@lewing lewing commented Sep 15, 2026

Copy link
Copy Markdown
Member

Summary

  • fix WASM ReadyToRun filter-funclet classification by mapping the executable filter entry to its containing funclet
  • use the existing cross-platform native-marker path to propagate exceptions thrown from filters
  • preserve executable FilterOffset values and the existing collided-unwind fail-fast invariant
  • re-enable all three runtime tests quarantined under [wasm][R2R] b68872 collides with first-pass ExInfo #133468

Testing

  • ./build.sh clr+libs+host
  • ./build.sh clr
  • ./build.sh clr -os browser -arch wasm -c Checked /p:HostConfiguration=Release
  • browser WASM R2R b68872: exit 100
  • browser WASM R2R throwinfilter_d: exit 100
  • browser WASM R2R GitHub_4044: exit 100
  • browser WASM R2R Runtime_88168: exit 100
  • browser WASM R2R GitHub_22820: exit 100
  • browser WASM diagnostic-ip-stacktrace, with and without a test R2R component: exit 100
  • native osx-arm64 Debug b68872: exit 100
  • native collided-unwind regression GitHub_121578: passed

Resolves #133468

Note

This pull request description was authored with GitHub Copilot.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 15, 2026 06:07
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Sep 15, 2026
@lewing
lewing requested a review from janvorli September 15, 2026 06:08
@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 added the arch-wasm WebAssembly architecture label Sep 15, 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.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
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

The exception-handling condition must be restricted to filter funclets to preserve collided-unwind fail-fast behavior.

Get a fresh assessment by requesting another Copilot review.

Review tier: Lite
Findings: 1 High severity

Open (1)
What changed in this PR

Fixes WASM ReadyToRun exception-filter propagation and re-enables three quarantined tests.

Changes:

  • Adds WASM R2R filter-boundary handling.
  • Removes obsolete quarantines and an unused test dependency.
File Description
src/​tests/​JIT/​Regression/​CLR-x86-JIT/​V1-M12-Beta2/​b68872/​b68872.ilproj Removes an obsolete test-library reference.
src/​tests/​JIT/​Regression/​CLR-x86-JIT/​V1-M12-Beta2/​b68872/​b68872.il Removes WASM R2R quarantine metadata.
src/​tests/​JIT/​Regression_3/​GitHub_4044/​GitHub_4044.cs Removes the WASM R2R quarantine.
src/​tests/​JIT/​Methodical/​eh/​basics/​throwinfilter.il Removes the WASM R2R quarantine.
src/​coreclr/​vm/​exceptionhandling.cpp Adjusts WASM R2R filter-boundary exception handling.

Comment thread src/coreclr/vm/exceptionhandling.cpp Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 15, 2026 06:54

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

🔵 Needs a closer look

The exception-handling changes require final human review.

Review tier: Lite
Findings: None

Resolved since last review (1)

@AndyAyersMS AndyAyersMS added area-VM-coreclr and removed area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Sep 15, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Comment thread src/coreclr/vm/exceptionhandling.cpp Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 15, 2026 15:26
@lewing lewing changed the title Fix WASM R2R exceptions escaping filters Fix Wasm R2R exceptions escaping filters Sep 15, 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

🔵 Needs a closer look

The cDAC WASM filter-offset handling remains inconsistent and needs to be fixed with coverage.

Review tier: Lite
Findings: None

@janvorli

Copy link
Copy Markdown
Member

The existing check failed because ReadyToRunJitManager::IsFilterFunclet fell back to offset arithmetic on WASM: the R2R funclet starts at relative offset 0xc, while the EH filter entry is at 0xe after the synthetic funclet prolog, so it returned false.

I wonder if this offset discrepancy isn't actually what should be fixed. Why are those two offsets different?

@lewing

lewing commented Sep 15, 2026

Copy link
Copy Markdown
Member Author

I think that is the design? cc @AndyAyersMS @davidwrighton

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@lewing

lewing commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

I don't understand what went wrong with the offset change; it doesn't strike me as something that should have caused more problems. All the VIP ranges for funclets should be disjoint, so changing the notion of start to the funclet begin virtual IP should not have led to confusion.

Agreed, I think the failure analysis was wrong and the revert is probably wrong, digging into the details now.

@lewing

lewing commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

It looks like the filter fix uncovered a different issue in the GC-filter. Looking into that now.

lewing and others added 2 commits September 16, 2026 11:42
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 16, 2026 16:58
@lewing

lewing commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

@AndyAyersMS @janvorli the offset change is restored and the GC change fixes the test that regressed as a result. I am not sure if there is a better approach there too?

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

🔵 Needs a closer look

CoreCLR exception handling and WASM R2R changes warrant final human review.

Review effort: Lite
Findings: None

@AndyAyersMS

Copy link
Copy Markdown
Member

That change seems a bit odd too, I don't think the filter funclet parent frame should ever be at a non-interruptible location (they should all be sitting at a call).

Maybe there is something else inhibiting parent frame reporting?

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 16, 2026 20:03
@lewing

lewing commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

You are right that conceptually the filter parent should be sitting at a call. I traced why it is still treated as non-reportable on Wasm.

The recovered parent context is the original exception context and carries ExecutionAborted. For partially interruptible GC info, the decoder intentionally ignores ordinary safe-point live states for an aborted frame and will only report from an interruptible range. More importantly, the current Wasm JIT does not emit either form for this method:

NumSafePoints: 0
NumInterruptibleRanges: 0
NumUntracked: 5

This is not just the usual optimization that drops a boring call site late in encoding. The Wasm emitter does not call emitRecordGCcall, so there is no call descriptor to retain. This matches the current Wasm GC-info model from #126932 and #129100: tracked lifetimes/call-site GC states were deferred, all stack GC variables are emitted as zero-initialized untracked slots, and no tracked GC slots are encoded.

I mutation-tested two deeper alternatives:

  1. Clearing ExecutionAborted for the known filter parent makes the failing merged runners pass, and the parent reports the expected exception and disposable-object slots. But it cannot be made safe generally because hardware-fault filters may have a genuinely non-safe parent PC.
  2. Retaining otherwise-empty call sites in gcencode.cpp had no effect: the emitted method still had zero safe points because Wasm never creates the call descriptors upstream.

So the current scoped behavior is intentional: for an R2R filter, report the always-live, zero-initialized untracked slots from the filter frame rather than suppressing them in expectation that the aborted parent will report. Implementing the normal parent-reporting model would require broader Wasm GC-info work to emit precise call-site metadata.

The exact A/B matrix was:

  • filter classification + standard suppression: Runtime_88168, GitHub_22820, and nested Methodical filter runners fail with missing-root corruption
  • classification disabled: those pass, but throwinfilter hits the original first-pass collision assertion
  • approved fgwasm classification + filter untracked reporting: all exact merged runners, focused filter tests, async R2R/non-R2R, and native collided-unwind regression pass

I updated the code comment to describe the missing call-site GC metadata rather than merely saying the parent is non-interruptible.

Note

This response was authored with GitHub Copilot.

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

🔵 Needs a closer look

Low-level WASM JIT, exception-unwind, and GC handling changes warrant final human review.

Review effort: Lite
Findings: None

@AndyAyersMS

AndyAyersMS commented Sep 16, 2026

Copy link
Copy Markdown
Member

an R2R filter, report the always-live, zero-initialized untracked slots from the filter frame rather than suppressing them in expectation that the aborted parent will report.

Ok, that makes more sense. Since Wasm only has untracked lifetimes there is no per-call site info to report. I suppose we could still report all the call sites to make the main method look like it is in fact interruptible (not sure how much this costs). We have the same (only untracked lifetime) setup for Tier0 and perhaps we've avoided this problem there by reporting call sites.

Also note the filter proper doesn't have any untracked GC slots to report, they are all shared with the parent frame (which is why duplication is possible).

@AndyAyersMS

Copy link
Copy Markdown
Member

Ah apparently for native targets we force methods with EH to be fully interruptible, and hence the parent frame does the untracked reporting and we suppress reporting in the filter.

But for Wasm we don't do this forcing, fully interruptible makes no sense... so then the parent doesn't report, and we have to report in the filter.

So from what I can tell your fix looks good.

@AndyAyersMS AndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM w/comment nit...

Comment thread src/coreclr/vm/eetwain.cpp Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 16, 2026 22:17
@lewing

lewing commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

@AndyAyersMS comment fixed, please reapprove when you have a chance

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

🔵 Needs a closer look

WASM exception handling and runtime GC reporting changes warrant final human review.

Review effort: Lite
Findings: None

@lewing
lewing merged commit d642f9c into dotnet:main Sep 17, 2026
140 of 143 checks passed
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Sep 18, 2026
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 18, 2026
## Summary

- recognize the implicit WASM R2R boundary between a filter funclet and
its VM caller
- propagate exceptions thrown by filters back to the caller that applies
filter exception semantics
- preserve the existing collided-unwind fail-fast invariant for
non-WASM-R2R cases
- re-enable all three runtime tests quarantined under dotnet#133468

## Testing

- `./build.sh clr+libs+host`
- `./build.sh clr`
- `./build.sh clr -os browser -arch wasm -c Checked
/p:HostConfiguration=Release`
- browser WASM R2R `b68872`: exit 100
- browser WASM R2R `throwinfilter_d`: exit 100
- browser WASM R2R `GitHub_4044`: exit 100
- native osx-arm64 Debug `b68872`: exit 100
- native collided-unwind regression `GitHub_121578`: passed

Resolves dotnet#133468

> [!NOTE]
> This pull request description was authored 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-VM-coreclr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm][R2R] b68872 collides with first-pass ExInfo

4 participants