Skip to content

[browser] upgrade wasm exceptions#129396

Closed
pavelsavara wants to merge 176 commits into
dotnet:mainfrom
pavelsavara:emsdk-upgrade-wasm_exceptions
Closed

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

Conversation

@pavelsavara

@pavelsavara pavelsavara commented Jun 14, 2026

Copy link
Copy Markdown
Member

On top of #129299

TODO: https://gist.github.com/pavelsavara/f43aa98501c64bede3d031a3ce88a3cf,
depends on docker image with the new V8 - #129396

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
pavelsavara and others added 9 commits June 24, 2026 18:36
# Conflicts:
#	src/tests/JIT/Regression/CLR-x86-JIT/V1.1-M1-Beta1/b143840/b143840.il
# Conflicts:
#	eng/pipelines/runtime-llvm.yml
#	src/mono/mono/metadata/assembly-load-context.c
Classify managed (<=16 byte, non-pinvoke) value types whose fields straddle the 8-byte eightbyte boundary as ArgValuetypeInReg instead of forcing them onto the stack. This makes a partially-shared (gshared) caller -- which sees the value as an opaque type parameter with one straddling field -- agree with a concrete callee that sees the flattened layout, in both the JIT and the LLVM backend, fixing the miscompile recent LLVM exposed under Mono LLVM full-AOT. Replaces the LLVM-only llvm_inreg_straddle approach with a layout-independent classification and removes the bitfield and its get_llvm_call_info special-case. Adds a StructABI regression test covering the gshared box/unbox, all-integer and float straddlers, direct by-value pass, and register GC-safety.
…_exceptions

# Conflicts:
#	eng/pipelines/runtime-llvm.yml
#	src/mono/mono/mini/mini-amd64.c
Copilot AI review requested due to automatic review settings June 24, 2026 18: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.

Pull request overview

Copilot reviewed 64 out of 66 changed files in this pull request and generated 4 comments.

Comment thread eng/Versions.props
Comment on lines +30 to 36
<!-- 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>
<SdkVersionForWorkloadTesting Condition="$([System.String]::Compare('$(_GlobalJsonSdkVersion)', '$(_DotnetSdkVersion)')) &lt;= 0">$(_DotnetSdkVersion)</SdkVersionForWorkloadTesting>
Comment thread eng/Versions.props
Comment on lines +174 to +188
<!-- TEMPORARY: pinned to the staged emsdk 5.0.6 workload manifest in the general-testing feed.
NOTE: this is the emscripten workload MANIFEST version and uses the sdk feature-band format (11.0.100-preview.6.*),
NOT the runtime format (11.0.0-preview.6.*) used by EmsdkPackageVersion below; both share the 26314.102 build stamp.
Do NOT restore to $(MicrosoftDotNetApiCompatTaskPackageVersion): merges from main bump it past the staged manifest
and break the workload install (NU1102 on Microsoft.NET.Workload.Emscripten.Current.Manifest-11.0.100-preview.6).
Repin to the production .NET 11 emsdk 5.0.6 version (and drop the general-testing feed) before merge. See dotnet/runtime#113786. -->
<MicrosoftNETRuntimeEmscriptenVersion>11.0.100-preview.6.26314.102</MicrosoftNETRuntimeEmscriptenVersion>
<!-- we're using MicrosoftNETCoreAppRefPackageVersion since the emsdk package ID contains a changing version. This one uses runtime version numbers. -->
<EmsdkPackageVersion>$(MicrosoftNETCoreAppRefPackageVersion)</EmsdkPackageVersion>
<!-- TEMPORARY: pinned to the staged emsdk 5.0.6 packages (Microsoft.NET.Runtime.Emscripten.5.0.6.Cache/Sdk.*) in the general-testing feed, which only
exist at 11.0.0-preview.6.26314.102. Do NOT restore to $(MicrosoftNETCoreAppRefPackageVersion): merges from main bump it past the staged build
and break native build restore (NU1102). Repin to the production .NET 11 emsdk 5.0.6 transport (and drop the general-testing feed) before merge. -->
<EmsdkPackageVersion>11.0.0-preview.6.26314.102</EmsdkPackageVersion>
<NodePackageVersion>$(runtimewinx64MicrosoftNETCoreRuntimeWasmNodeTransportPackageVersion)</NodePackageVersion>
<!-- The package path for python in src/mono/mono.proj needs to be updated if this changes-->
<EmsdkVersion>3.1.56</EmsdkVersion>
<EmsdkVersion>5.0.6</EmsdkVersion>
Comment on lines +87 to +99
<!-- Replace ci.dot.net/public with ci.dot.net/dev in the script using the platform's native tools.
This avoids MSBuild's string/item-list parsing pitfalls (e.g. ';' splitting in WriteLinesToFile,
line-ending and escaping issues) when round-tripping an entire shell/PowerShell script through
MSBuild properties. We're already invoking these shells right after, so leverage them directly. -->
<Message Text="** Replacing ci.dot.net/public with ci.dot.net/dev in $(_DotNetInstallScriptPath)" Importance="High" />

<Exec Condition="!$([MSBuild]::IsOSPlatform('windows'))"
IgnoreStandardErrorWarningFormat="true"
Command="sed -i.bak 's|ci\.dot\.net/public|ci.dot.net/dev|g' &quot;$(_DotNetInstallScriptPath)&quot; &amp;&amp; rm -f &quot;$(_DotNetInstallScriptPath).bak&quot;" />
<Exec Condition="$([MSBuild]::IsOSPlatform('windows'))"
IgnoreStandardErrorWarningFormat="true"
Command='powershell -ExecutionPolicy ByPass -NoProfile -Command "(Get-Content -Raw -LiteralPath &apos;$(_DotNetInstallScriptPath)&apos;).Replace(&apos;ci.dot.net/public&apos;, &apos;ci.dot.net/dev&apos;) | Set-Content -NoNewline -LiteralPath &apos;$(_DotNetInstallScriptPath)&apos;"' />

Comment thread NuGet.config
Comment on lines 22 to 26
<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>
@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).

@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-extra-platforms

@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).

1 similar comment
@azure-pipelines

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

lock_free_mempool_chunk_new sized each chunk by reserving
sizeof(LockFreeMempoolChunk) (24 bytes on 64-bit), but chunk->mem is then
aligned up to 16 bytes, so the usable region starts at offset 32 and a
single-page chunk only has pagesize-32 usable bytes. A request whose length
is congruent to -24 (mod pagesize) - e.g. 4072 on 4 KB pages, 16360 on 16 KB
pages - produced a freshly allocated chunk whose size (pagesize-32) is smaller
than the requested length, tripping

  g_assert (chunk->pos + size <= GINT_TO_UINT(chunk->size));

in lock_free_mempool_alloc0 and aborting the runtime.

This pool is used on the async AOT unwind/exception-info decode path
(mono_aot_get_unwind_info / decode_exception_debug_info with async==TRUE),
which is driven by the EventPipe SampleProfiler stack walk, so the crash
showed up intermittently as a SIGABRT during eventpipe tracing tests under
Mono LLVM full-AOT on x64.

Fix: reserve the 16-byte-aligned header size in the sizing loop so the chunk
always has room for the request.
Copilot AI review requested due to automatic review settings June 25, 2026 10:45

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 65 out of 67 changed files in this pull request and generated 2 comments.

prepareAssetsWorker();
const promises = importModules();
const es6Modules = await Promise.all(promises);
(globalThis as any).name = "em-pthread";
Comment thread eng/Versions.props
Comment on lines +30 to 36
<!-- 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>
<SdkVersionForWorkloadTesting Condition="$([System.String]::Compare('$(_GlobalJsonSdkVersion)', '$(_DotnetSdkVersion)')) &lt;= 0">$(_DotnetSdkVersion)</SdkVersionForWorkloadTesting>
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