Skip to content

Merge upstream dev3 (261 commits): #1271 audit fixes, init/subproc restructure - #15

Merged
Jarred-Sumner merged 334 commits into
bun-dev3-v2from
claude/sync-dev3
Aug 13, 2026
Merged

Merge upstream dev3 (261 commits): #1271 audit fixes, init/subproc restructure#15
Jarred-Sumner merged 334 commits into
bun-dev3-v2from
claude/sync-dev3

Conversation

@Jarred-Sumner

@Jarred-Sumner Jarred-Sumner commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Merges upstream dev3 (261 commits, through 6def7be) into bun-dev3-v2.

What comes in

Area
microsoft#1271 audit fixes Purge bits skipped when the minimal purge range is a non-power-of-two number of slices (not the case in our configuration — measured as neutral); use-after-free of meta stats in sub-processes; thread-locals release order at destroy; tld leak on theap alloc failure; heap merge subproc; singleton-page init failure path (matches the fix this fork carried); NUMA detection on Linux; random key zeroed after use
Restructure init.c split into subproc.c / prim-tls.c; the static main heap and tld become meta-data allocations; theap teardown redesigned around a detach protocol
New API Constant-size inline malloc/free entry points (not used by Bun yet)

Ported onto the new structure

Fork feature Change
fork() handlers Moved to subproc.c beside the registry they walk; cover every sub-process and the new meta lock; every registered tld is re-initialized in the child
Profiling Third page-flag bit (thread-id sentinels shift with it); the sample check now runs at both exits of the generic path, which upstream split
Hole sweep State packed into 64 bits since page->used is now 32-bit (test updated)
tld registry, per-theap prof init, atfork registration, exit hooks, exit-time opt-out Re-homed
_mi_theap_can_touch Accepts upstream's detached theaps
Zone enumerator Uses the page's start-offset field
Dropped Our try-acquire _mi_theap_free and the teardown re-collect — upstream's detach protocol covers both
Kept Thread-local slot zeroing (upstream's meta rezalloc still copies usable_size bytes of slack — to be reported), the Linux resident-size reading; upstream's version taken where it now covers the same bug (chunkmap, page free)
Public API Upstream moved mi_malloc_size / mi_malloc_usable_size into alloc-override.c, so MI_OVERRIDE=OFF builds (Bun's ASAN lanes) lost two exported functions — restored for that configuration (to be reported)
Build as C++ Upstream's new try in the new-handler path guarded like the throw above it (to be reported)

_mi_message was silently dropped by a clean merge of options.c; afterwards every fork-added symbol (155) was checked against the merged tree.

Validation

This repo Debug: 20/20. Release: 19/19
Bun See the measurements below; the startup-snapshot suite is green against this content

Bun measurements (macOS arm64, release builds of the same Bun commit; the pin is the only difference; paired rounds; memory = Bun.unsafe.memoryFootprint / phys_footprint, not RSS)

Old pin → this
Retained by size class, 1-in-64 survivors (purge machinery) Identical (256 B ≈ 6 MB both; 1 K–16 K ≈ 0 both)
Bare startup footprint 6.54 → 6.75 MB (+0.2 MB, 5/5 pairs; the meta-allocated per-thread structures)
Churn workload peak / final Peak: no consistent difference over 9 pairs. Final: consistently a little lower
express (bombardier, 300k requests) — settled footprint, read after a forced full GC 43.4 → 43.2 MB avg over 5 pairs (equal; an earlier unforced reading looked ~7 MB lower but that was JSC heap timing at the moment load stopped, not the allocator)
express peak footprint No consistent direction
express throughput 89.5k → 90.1k rps (parity)
Bun's startup-snapshot suite (with #16) 45/45 after two interactions were fixed: the build-marker presence check (in #16) and a snapshot-writer assumption that every owned mapping has something resident (fixed in Bun — this allocator's page-map tables can be entirely untouched at build time)

daanx added 30 commits July 30, 2026 21:24
daanx and others added 22 commits August 6, 2026 06:40
Takes upstream's microsoft#1271 audit fixes, the init/subproc/thread-local restructuring (static main heap and tld replaced by
meta-data allocations), the reworked theap teardown, and the constant-size inline allocation entry points.

Ported onto the new structure:
- fork() handlers move to subproc.c next to the registry they walk; they now cover every sub-process and the new
  meta-data lock, and re-initialize every registered tld in the child (the static main tld special case is gone)
- page flags gain a third bit for the profiling flag; the thread-id sentinels shift with it
- the hole-sweep state is packed into 64 bits now that page->used is 32-bit (test updated to match)
- the profiling sample check runs at both exits of the generic path (upstream split it; only the fallback had it)
- the tld registry, per-theap profiling init, atfork registration, exit hooks and the exit-time opt-out are re-homed
- _mi_theap_can_touch accepts detached theaps; the zone enumerator uses the page's start offset field
- our try-acquire _mi_theap_free and the teardown re-collect are dropped: upstream's detach protocol supersedes both
- kept: the thread-local slot zeroing (upstream's meta rezalloc still copies usable_size bytes of slack), the Linux
  resident-size reading, the chunkmap and page-free fixes where upstream's version now covers the same bug
- _mi_message had been silently dropped by a clean merge of options.c; every fork-added symbol was checked afterwards

Debug and Release: all tests pass.
…ove it (built as C++ without exceptions by embedders)
…en not overriding too (upstream moved them into alloc-override.c, which is compiled out with MI_OVERRIDE=OFF)
@Jarred-Sumner
Jarred-Sumner merged commit a0078e2 into bun-dev3-v2 Aug 13, 2026
Jarred-Sumner added a commit to oven-sh/bun that referenced this pull request Aug 13, 2026
…TLS crash (#37367)

Moves the mimalloc pin to oven-sh/mimalloc `bun-dev3-v2` @ `be7eb3ff1`,
which is:

- oven-sh/mimalloc#15 — the fork synced with upstream `dev3` (261
commits: the #1271 audit fixes, the init/sub-process restructure,
reworked theap teardown), fork features re-applied on top. Includes
upstream's `thread_locals_get` fix: on Linux/Windows a thread that had
used a non-main heap (JSC's structure heap, every `bun_alloc::Arena`)
could NULL-deref in `mi_free`/teardown after mimalloc's own thread-done
ran. Regression test added here (`worker_destruction.test.ts`, fails 4/4
on a debug build of main).
- oven-sh/mimalloc#17 — the idle sweep's state lives on the tld instead
of `__thread` variables. On emulated-TLS targets (our Android build, API
< 29) the first `__thread` access mallocs, so reading the sweep guard
from inside a page collect recursed until the stack was gone. Fixes
#38051.
- A rate-limited park (`purge_holes_min_interval`) is now swept when its
window ends instead of at the scavenger's next unrelated wake (up to its
30 s safety net) — the end-of-burst park is the one that used to be left
waiting.
- A `MI_DEBUG_FULL`-only assertion exemption for the detached meta theap
(aborted `test-heap-churn`/`test-heap-mt` in the fork's debug suite
after the sync).

Replaces #38168 and #38199 (both were `patches/mimalloc/*.patch`
stop-gaps against the old pin).

---


### Measured (macOS arm64, release builds of this same commit, old pin
vs new; paired rounds; memory is `Bun.unsafe.memoryFootprint`)

| | Old → new |
|---|---|
| Retained by size class, 1-in-64 survivors | Identical |
| Bare startup footprint | 6.54 → 6.75 MB (+0.2 MB, 5/5 pairs) |
| express settled footprint after 300k requests, read after a forced
full GC | 43.4 → 43.2 MB avg, 5 pairs (equal — the unforced reading that
looked ~7 MB lower was GC timing, not the allocator) |
| express peak footprint | No consistent direction |
| express throughput | 89.5k → 90.1k rps (parity) |

The startup-snapshot branch was also built against the equivalent (#16)
and its suite passes; that surfaced one snapshot-writer fix, landed on
that branch separately.

CI is the regression sweep for this change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants