Skip to content

[browser][coreclr] WASM-specific GC OS layer; no mmap/decommit#127328

Open
pavelsavara wants to merge 38 commits intodotnet:mainfrom
pavelsavara:browser_no_mmap
Open

[browser][coreclr] WASM-specific GC OS layer; no mmap/decommit#127328
pavelsavara wants to merge 38 commits intodotnet:mainfrom
pavelsavara:browser_no_mmap

Conversation

@pavelsavara
Copy link
Copy Markdown
Member

@pavelsavara pavelsavara commented Apr 23, 2026

Fixes #121036
Fixes #117813
Fixes #118943

Summary

This PR adds a dedicated WASM implementation of the GC's OS abstraction layer
(GCToOSInterface) and updates the GC and PAL to handle the fact that on WASM
there is no virtual memory: pages cannot be reserved without committing,
partial unmaps don't return memory to the engine, and MAP_FIXED / madvise
are not supported.

The previous approach reused gcenv.unix.cpp with #ifdef TARGET_WASM patches
and overloaded use_large_pages_p to mean "decommit is a no-op". This change
splits those concerns:

  • A new gc/wasm/gcenv.cpp replaces gc/unix/gcenv.unix.cpp on WASM and
    implements VirtualReserve / VirtualCommit / VirtualDecommit /
    VirtualRelease on top of posix_memalign / free. WASM-specific patches
    in gcenv.unix.cpp are removed.
  • A new GC flag never_decommit_p replaces every "is decommit a no-op" check
    that was previously expressed as use_large_pages_p. It is set on WASM
    unconditionally and on other platforms whenever use_large_pages_p is set.
  • gc/CMakeLists.txt now selects gc/wasm for WASM targets while still
    including unix/configure.cmake to generate config.gc.h.
  • The PAL's virtual.cpp is similarly cleaned up to use posix_memalign /
    free on WASM and to zero memory on MEM_DECOMMIT, so the next
    VirtualCommit (a no-op on WASM) sees zeroed memory.
  • A new minipal_getpagesize abstraction is introduced. On WASM it returns a
    compile-time constant of 16 KB (the GC's page granularity, distinct from the
    64 KB memory.grow granularity that getpagesize() reports). On Windows it
    returns the 4 KB constant inline. On other POSIX systems it caches
    getpagesize() once per process. CoreCLR PAL callers are updated to use it.

Why a separate never_decommit_p

On large pages, decommit is a no-op because the OS pre-commits the entire
range. On WASM, decommit is a no-op because there is no way to give linear
memory back to the engine. The two cases share the same set of GC code paths
that must be skipped or modified (decommit_ephemeral_segment_pages,
decommit_step, decommit_region, decommit_heap_segment_pages,
decommit_heap_segment, distribute_free_regions tail-decommit,
reset_memory, virtual_commit, virtual_decommit assert), but they have
nothing else in common. Reusing use_large_pages_p on WASM was misleading and
made it easy to forget large-pages-only behavior (e.g., pre-touch). The new
flag captures only the "decommit is a no-op" semantics; non-WASM behavior is
unchanged because never_decommit_p == use_large_pages_p everywhere except
WASM.

Why minipal_getpagesize

The GC needs the OS page size to be a compile-time constant on WASM (16 KB)
so that alignment math folds. getpagesize() on emscripten returns 64 KB
(the memory.grow granularity), which is too coarse for GC alignment and
thresholds. Centralizing this in minipal lets PAL and GC agree on a single
value and avoids #ifdefs at every call site.

Notes

  • VirtualReserveAndCommitLargePages on WASM falls through to the regular
    reserve/commit path; the GC does not request large pages on WASM.
  • posix_memalign may return either freshly grown linear memory (zeroed by
    the WASM spec) or a recycled block from emscripten's allocator free list.
    We always memset to zero on reserve and on decommit so callers can rely
    on the standard "memory starts zeroed" contract.
  • VirtualReset returns false on WASM, forcing the GC to use the
    decommit+commit fallback (memset to zero) rather than relying on
    madvise, which is a no-op on emscripten.

@pavelsavara pavelsavara added this to the 11.0.0 milestone Apr 23, 2026
@pavelsavara pavelsavara self-assigned this Apr 23, 2026
Copilot AI review requested due to automatic review settings April 23, 2026 16:55
@pavelsavara pavelsavara added arch-wasm WebAssembly architecture area-GC-coreclr labels Apr 23, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR separates WebAssembly-specific GC OS interface behavior from the shared Unix implementation by introducing a dedicated gcenv.wasm.cpp, and adjusts the PAL virtual memory implementation on WASM to avoid relying on Emscripten’s incomplete mmap/munmap support.

Changes:

  • Added a dedicated WASM GCToOSInterface implementation (gcenv.wasm.cpp) and CMake wiring for building it.
  • Routed WASM GC builds to the new gc/wasm directory and removed WASM-specific #ifdef paths from gcenv.unix.cpp.
  • Updated PAL virtual memory reserve/release on WASM to use posix_memalign/free instead of mmap/munmap.

Reviewed changes

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

Show a summary per file
File Description
src/coreclr/pal/src/map/virtual.cpp Switches WASM reserve/release behavior to posix_memalign/free and adjusts related error/cleanup paths.
src/coreclr/gc/wasm/gcenv.wasm.cpp New WASM-specific GC OS interface implementation (virtual memory, CPU/NUMA stubs, memory stats).
src/coreclr/gc/wasm/CMakeLists.txt Adds build definition for the WASM GC PAL object library.
src/coreclr/gc/unix/gcenv.unix.cpp Removes WASM-specific branches and fixes nanosleep EINTR retry logic.
src/coreclr/gc/CMakeLists.txt Routes WASM builds to gc/wasm instead of gc/unix.

Comment thread src/coreclr/pal/src/map/virtual.cpp
Comment thread src/coreclr/pal/src/map/virtual.cpp Outdated
Comment thread src/coreclr/gc/wasm/gcenv.wasm.cpp Outdated
Comment thread src/coreclr/gc/wasm/gcenv.wasm.cpp Outdated
@pavelsavara pavelsavara changed the title [wasm][coreclr] Extract WASM-specific GC memory management into dedicated file [browser/wasi] Dedicated WASM GC PAL — replace mmap with posix_memalign and optimize memory operations Apr 23, 2026
@pavelsavara pavelsavara changed the title [browser/wasi] Dedicated WASM GC PAL — replace mmap with posix_memalign and optimize memory operations [browser/wasi][coreCLR] Dedicated WASM GC PAL — replace mmap with posix_memalign and optimize memory operations Apr 24, 2026
Copilot AI review requested due to automatic review settings April 24, 2026 08:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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

Comment thread src/coreclr/gc/wasm/gcenv.wasm.cpp Outdated
Comment thread src/coreclr/gc/wasm/gcenv.wasm.cpp Outdated
Comment thread src/coreclr/gc/wasm/gcenv.wasm.cpp Outdated
Comment thread src/coreclr/gc/wasm/gcenv.wasm.cpp Outdated
Comment thread src/coreclr/pal/src/map/virtual.cpp Outdated
Comment thread src/coreclr/pal/src/map/virtual.cpp Outdated
Comment thread src/coreclr/pal/src/map/virtual.cpp Outdated
Copilot AI review requested due to automatic review settings April 24, 2026 11:37
@pavelsavara pavelsavara marked this pull request as ready for review April 24, 2026 11:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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

Comment thread src/coreclr/gc/wasm/gcenv.cpp
Comment thread src/coreclr/gc/wasm/CMakeLists.txt
Comment thread src/coreclr/gc/wasm/gcenv.cpp
Comment thread src/coreclr/pal/src/map/virtual.cpp
Comment thread src/coreclr/gc/wasm/gcenv.wasm.cpp Outdated
Comment thread src/coreclr/gc/wasm/gcenv.cpp
Comment thread src/coreclr/gc/wasm/gcenv.cpp
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread src/coreclr/gc/wasm/gcenv.cpp
Comment thread src/native/minipal/wasm.h Outdated
pavelsavara and others added 3 commits May 1, 2026 09:10
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 15 out of 15 changed files in this pull request and generated 1 comment.

Comment thread src/coreclr/pal/src/map/virtual.cpp
Copilot AI review requested due to automatic review settings May 1, 2026 08:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 15 out of 15 changed files in this pull request and generated 1 comment.

Comment thread src/coreclr/gc/wasm/gcenv.cpp Outdated
Comment thread src/coreclr/gc/wasm/gcenv.cpp Outdated
Comment thread src/coreclr/gc/wasm/gcenv.cpp Outdated
Copy link
Copy Markdown
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

LGTM otherwise

@janvorli Could you please signoff as well?

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Copilot AI review requested due to automatic review settings May 1, 2026 19:09
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 17 out of 17 changed files in this pull request and generated no new comments.

Comment thread src/native/minipal/ospagesize.h Outdated
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 2, 2026 07:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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

{
(void)configAffinityMask;
(void)configAffinitySet;
return nullptr; // only for multiple heaps
Comment on lines +413 to +417
uint32_t GCToOSInterface::GetTotalProcessorCount()
{
return 1;
}

Comment on lines +63 to +65
#else // TARGET_WASI
// WASI doesn't have an API to query max memory.
g_totalPhysicalMemSize = 2LL * 1024 * 1024 * 1024; // 2GB
Comment thread src/coreclr/gc/memory.cpp
Comment on lines +101 to +104
// In addition if never-decommit is enabled (which is implied by large pages), we
// set commit_succeeded_p to true because memory is already committed (and
// VirtualCommit would be a no-op).
bool commit_succeeded_p = ((h_number >= 0) ? (never_decommit_p ? true :
Comment on lines +129 to +131

while (nanosleep(&requested, &requested) != 0 && errno == EINTR)
{
//
// On other platforms the value is queried from the OS once and cached; the
// definition lives in ospagesize.c so there is exactly one cache per process.
#if defined(TARGET_WASM)
Copy link
Copy Markdown
Member

@jkotas jkotas May 2, 2026

Choose a reason for hiding this comment

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

Suggested change
#if defined(TARGET_WASM)
#if defined(HOST_WASM)

minipal should use HOST_... everywhere. It is not concerned about the target platform. Ifdefs that use TARGET_... in minipal are not quite right.

For example, if you use TARGET_WASM here, RyuJIT running on Windows or Linux that produces code for wasm may pickup the custom wasm page size for its allocators. It can lead to interesting bugs.

Comment on lines +24 to +26
// The OS page size used by CoreCLR on WASM (16KB).
// WASM has no hardware pages; getpagesize() returns the 64KB memory.grow granularity,
// which is too coarse for GC alignment and thresholds.
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.

Suggested change
// The OS page size used by CoreCLR on WASM (16KB).
// WASM has no hardware pages; getpagesize() returns the 64KB memory.grow granularity,
// which is too coarse for GC alignment and thresholds.
// WASM has no hardware pages; getpagesize() returns the 64KB memory.grow granularity,
// which is too coarse for GC alignment and thresholds. Reduce the OS page size used
// by the runtime on WASM to 16KB.

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

Labels

arch-wasm WebAssembly architecture area-GC-coreclr

Projects

None yet

6 participants