Skip to content

[browser] upgrade wasm exceptions#129396

Draft
pavelsavara wants to merge 156 commits into
dotnet:mainfrom
pavelsavara:emsdk-upgrade-wasm_exceptions
Draft

[browser] upgrade wasm exceptions#129396
pavelsavara wants to merge 156 commits into
dotnet:mainfrom
pavelsavara:emsdk-upgrade-wasm_exceptions

Conversation

@pavelsavara

Copy link
Copy Markdown
Member

On top of #129299

akoeplinger and others added 30 commits June 11, 2026 18:44
(cherry picked from commit ea0ec7c)
When passing a negative C int to LLVMConstInt, the value is implicitly
converted to unsigned long long via sign-extension. In LLVM 23,
LLVMConstInt now retains those upper bits when SignExtend is FALSE,
which broke constant folding of subsequent ZExt instructions (e.g.
'zext i32 -1 to i64' produced i64 -1 instead of i64 4294967295).

This manifested as wrong results for decimal arithmetic in mono+LLVM
AOT, e.g. the inlined Decimal..ctor(uint) with a constant argument
sign-extending to _lo64. Many CoreLib tests (System.Tests.DecimalTests,
System.Text.Tests.RuneTests, Vector128.NarrowWithSaturation*) were
failing as a result.

Mask the value to the destination width before passing to LLVMConstInt.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Updated comments to clarify that OSX HFS driver format does not support millisecond granularity.
LLVMConstInt(IntTy, N, FALSE) requires N to fit in IntTy's unsigned width
(i.e. no bits set beyond IntTy's bit count). Passing -1 (= 0xFF..FF as
unsigned long long) to a sub-64-bit type violates this. Under LLVM 23
the resulting constant is wrong, which in emit_div_check caused the
rhs == -1 comparison to constant-fold to false and the OverflowException
check for INT_MIN / -1 and INT_MIN % -1 to be eliminated by the
optimizer.

Use LLVMConstAllOnes() which is the LLVM C API's idiomatic way to
build an all-ones constant of any integer width, sidestepping the issue.

Also fix the same pattern in emit_entry_bb where il_state->il_offset
is initialized to -1.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
for wasm-opt: --enable-reference-types --enable-multivalue
for runtime default build: new instructions -fwasm-exceptions -sWASM_LEGACY_EXCEPTIONS=0
for no-EH runtime:-fexceptions JS exceptions
- change jiterp to use new wasm exception instructions
Removing ResumeState.ex_obj shrinks MonoJitTlsData by one pointer (216->212 on wasm32) and shifts the fields after resume_state. Regenerated wasm32-unknown-none.h and wasm32-unknown-wasip2.h so the MonoAOTOffsets validation passes. (Android/Apple offset files have the same shift but require their cross toolchains to regenerate.)
Mechanical shift matching the wasm32 result: removing ResumeState.ex_obj reduces DECL_SIZE2(MonoJitTlsData) and every field after resume_state by the target pointer size (8 for aarch64/x86_64, 4 for armv7/i686). Applied manually because these targets need the Android NDK / macOS to regenerate; validated by the mobile/apple MonoAOTOffsets CI legs.
The ALC re-entrancy fix (dotnet#129693) addresses the full-AOT stack overflow tracked by dotnet#129508, so drop the IsMonoFULLAOT ActiveIssue. The separate IsWasm ActiveIssue (dotnet#124219) is kept.

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.

Pull request overview

Copilot reviewed 78 out of 81 changed files in this pull request and generated 3 comments.

Comment thread src/mono/mono/mini/mini-exceptions.c Outdated
Comment thread eng/Versions.props
Comment on lines +30 to +35
<!-- TEMPORARY: pinned to the staged emsdk 5.0.6 SDK build on the ci.dot.net/dev feed (only 11.0.100-preview.6.26314.102 is staged there).
WorkloadTesting.Core.targets installs the SDK at this version from ci.dot.net/dev; do NOT follow
$(MicrosoftNETWorkloadEmscriptenCurrentManifest110100TransportVersion): merges from main bump it past the staged build,
and that SDK exists on neither ci.dot.net/dev nor production (dotnet-install fails, MSB3073).
Repin to the production .NET 11 emsdk 5.0.6 manifest transport (and drop the ci.dot.net/dev wiring) before merge. See dotnet/runtime#113786. -->
<_DotnetSdkVersion>11.0.100-preview.6.26314.102</_DotnetSdkVersion>
Comment thread NuGet.config
Comment on lines 21 to 26
<add key="dotnet10-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json" />
<add key="dotnet11" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet11/nuget/v3/index.json" />
<add key="dotnet11-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet11-transport/nuget/v3/index.json" />
<add key="dotnet-diagnostics-tests" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-diagnostics-tests/nuget/v3/index.json" />
<add key="general-testing" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json" />
</packageSources>
…ine jmp comment, fix marshalable typo

Integrates the minor review follow-ups from dotnet#129708 and dotnet#129710.
Don't set llvm_inreg_straddle for pinvoke signatures (native ABI uses the byval/stack path), and guard mono_resume_unwind so it only consumes resume_state.ex_gchandle when set. Mirrors the fixes on the individual PRs.
Copilot AI review requested due to automatic review settings June 23, 2026 11:44

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.

Pull request overview

Copilot reviewed 79 out of 82 changed files in this pull request and generated 4 comments.

Comment on lines +2509 to 2511
mono_gchandle_free_internal (jit_tls->resume_state.ex_gchandle);
jit_tls->resume_state.ex_gchandle = mono_gchandle_new_internal ((MonoObject*)obj, TRUE);
jit_tls->resume_state.ji = ji;
Comment on lines +2577 to 2581
if (jit_tls->resume_state.ex_gchandle)
mono_gchandle_free_internal (jit_tls->resume_state.ex_gchandle);
jit_tls->resume_state.ex_gchandle = mono_gchandle_new_internal (obj, TRUE);
jit_tls->resume_state.ji = ji;
jit_tls->resume_state.clause_index = i + 1;
Comment on lines +2501 to +2507
/*
* resume_state.ex_gchandle is shared with the finally-resume path
* (mono_handle_exception_internal above). If a finally handler threw a
* superseding exception that is now being caught here, that path left a
* pinned handle behind that will never be resumed; free it instead of
* asserting, mirroring the finally path.
*/
Comment on lines +2571 to +2576
/*
* Keep the exception object alive across the (managed) finally
* handler using a pinned GC handle. The handler can reach a GC
* safepoint, and a moving GC would otherwise invalidate a raw
* pointer stored here (see mono_resume_unwind ()).
*/
@pavelsavara

Copy link
Copy Markdown
Member Author

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@pavelsavara

Copy link
Copy Markdown
Member Author

/azp run runtime-wasm

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-Build-mono os-browser Browser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants