FreeList::forEach: bound the interval assert by MarkedBlock::blockSize - #247
Conversation
The assert hardcoded 16 KB, but MarkedBlock::blockSize is max(16 KB, CeilingOnPageSize), which is 64 KB on Linux ARM64 (PageBlock.h: the page size there is unknowable at compile time, e.g. RHEL uses 64 KiB pages). On that platform a freshly swept empty block has a single free interval spanning the whole ~63 KB payload, so any ASSERT_ENABLED build (debug, debug-asan, asan) fails at the first MarkedBlock::Handle::stopAllocating: ASSERTION FAILED: intervalEnd - intervalStart < (ptrdiff_t)(16 * KB) JavaScriptCore/heap/FreeListInlines.h(63) On every platform where blockSize is 16 KB the check is unchanged.
|
Warning Review limit reached
More reviews will be available in 21 minutes and 24 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
Comment |
Preview Builds
|
Picks up oven-sh/WebKit#247: FreeList::forEach asserted a hardcoded 16 KB interval bound, but MarkedBlock::blockSize is 64 KB on Linux ARM64 (CeilingOnPageSize), so every ASSERT_ENABLED arm64-linux artifact (-asan, -debug, -debug-asan) crashed at the first GC stop. The new linux-aarch64-asan lane needs the fixed -asan prebuilt. Also picks up from oven-sh/WebKit main: xwin 0.9.0, UB fix in double-to-int conversions, JIT disassembler compiled out of release, windows amd64-baseline ThinLTO variant.
Picks up oven-sh/WebKit#247: FreeList::forEach asserted a hardcoded 16 KB interval bound, but MarkedBlock::blockSize is 64 KB on Linux ARM64 (CeilingOnPageSize), so every ASSERT_ENABLED arm64-linux artifact (-asan, -debug, -debug-asan) crashed at the first GC stop. The new linux-aarch64-asan lane needs the fixed -asan prebuilt. Also picks up from oven-sh/WebKit main: xwin 0.9.0, UB fix in double-to-int conversions, JIT disassembler compiled out of release, windows amd64-baseline ThinLTO variant.
Bumps `WEBKIT_VERSION` from `963f8758` to [`6d586e29`](oven-sh/WebKit@6d586e2), the current head of oven-sh/WebKit main. The prebuilt release [`autobuild-6d586e293f008f0e74e5697611a379b1b24815c9`](https://github.com/oven-sh/WebKit/releases/tag/autobuild-6d586e293f008f0e74e5697611a379b1b24815c9) is published with all platform tarballs. This range is a fast-forward of 6 fork-local commits — no upstream WebKit merge: - [`27f4e7a9`](oven-sh/WebKit@27f4e7a) Fix UB in double-to-int conversions across JSC (oven-sh/WebKit#244) - [`f18cf9c2`](oven-sh/WebKit@f18cf9c) FreeList::forEach: bound the interval assert by MarkedBlock::blockSize (oven-sh/WebKit#247) - [`48460d87`](oven-sh/WebKit@48460d8) Compile out the JIT disassembler in release builds (oven-sh/WebKit#241) - [`6d586e29`](oven-sh/WebKit@6d586e2) windows cross: add the bun-webkit-windows-amd64-asan variant (oven-sh/WebKit#240) - [`c787a5a7`](oven-sh/WebKit@c787a5a) windows cross: add the amd64-baseline ThinLTO variant - [`c591a185`](oven-sh/WebKit@c591a18) windows: update xwin to 0.9.0 (oven-sh/WebKit#242) Checks: - No `Source/JavaScriptCore/runtime/JSType.h` changes in the range, so no `src/jsc/JSType.rs` update needed. - The workflow change (#240) only adds a new `bun-webkit-windows-amd64-asan.tar.gz` asset; all tarball names `prebuiltSuffix()` produces are present in the release.
Bumps `WEBKIT_VERSION` from `963f8758` to [`6d586e29`](oven-sh/WebKit@6d586e2), the current head of oven-sh/WebKit main. The prebuilt release [`autobuild-6d586e293f008f0e74e5697611a379b1b24815c9`](https://github.com/oven-sh/WebKit/releases/tag/autobuild-6d586e293f008f0e74e5697611a379b1b24815c9) is published with all platform tarballs. This range is a fast-forward of 6 fork-local commits — no upstream WebKit merge: - [`27f4e7a9`](oven-sh/WebKit@27f4e7a) Fix UB in double-to-int conversions across JSC (oven-sh/WebKit#244) - [`f18cf9c2`](oven-sh/WebKit@f18cf9c) FreeList::forEach: bound the interval assert by MarkedBlock::blockSize (oven-sh/WebKit#247) - [`48460d87`](oven-sh/WebKit@48460d8) Compile out the JIT disassembler in release builds (oven-sh/WebKit#241) - [`6d586e29`](oven-sh/WebKit@6d586e2) windows cross: add the bun-webkit-windows-amd64-asan variant (oven-sh/WebKit#240) - [`c787a5a7`](oven-sh/WebKit@c787a5a) windows cross: add the amd64-baseline ThinLTO variant - [`c591a185`](oven-sh/WebKit@c591a18) windows: update xwin to 0.9.0 (oven-sh/WebKit#242) Checks: - No `Source/JavaScriptCore/runtime/JSType.h` changes in the range, so no `src/jsc/JSType.rs` update needed. - The workflow change (#240) only adds a new `bun-webkit-windows-amd64-asan.tar.gz` asset; all tarball names `prebuiltSuffix()` produces are present in the release.
Problem
FreeList::forEachasserts that a free-list interval is smaller than a hardcoded 16 KB:But the real invariant is "an interval never spans more than one MarkedBlock payload", and
MarkedBlock::blockSizeisstd::max(16 * KB, CeilingOnPageSize)— which is 64 KB on Linux ARM64 (PageBlock.h: the page size there is unknowable at compile time; e.g. RHEL uses 64 KiB pages). On that platform,specializedSweepof an empty block creates a single interval spanning the whole ~63 KB payload, so the assert fires at the firstMarkedBlock::Handle::stopAllocatingin anyASSERT_ENABLEDbuild:This makes every assert-enabled linux-arm64 artifact from this repo (
-debug,-debug-asan,-asan) crash as soon as it runs JavaScript that triggers a GC stop. It went unnoticed because nothing consumed those artifacts until now: oven-sh/bun#31699 adds a linux-aarch64 ASAN lane to Bun's CI, and its first run died on exactly this assertion while generatingfeatures.json(build: https://buildkite.com/bun/bun/builds/59814). macOS arm64 is unaffected (Darwin'sCeilingOnPageSizeis 16 KB), as is linux x64 (4 KB pages → 16 KB blocks, payload < 16 KB so the assert could mathematically never fire).Fix
Bound the assert by
MarkedBlock::blockSize(already in scope —FreeListInlines.hincludesMarkedBlock.h). On every platform whereblockSizeis 16 KB this compiles to the identical check; on linux-arm64 it becomes the correct 64 KB bound.The same stale bound exists in upstream WebKit (
Source/JavaScriptCore/heap/FreeListInlines.h:63), so this is a candidate to carry upstream on the next rebase.Verification
Analysis path:
PageBlock.hCeilingOnPageSize = 64 * KBforOS(LINUX) && CPU(ARM64)→MarkedBlock.hblockSize = std::max(16 * KB, CeilingOnPageSize)→MarkedBlockInlines.hspecializedSweepbuilds one interval ofpayloadEnd - payloadBegin(bounded bypayloadSize<blockSize) →MarkedBlock.cpp:231freeList.forEachhits the assert. Once an autobuild release exists, Bun's PR-only linux-aarch64 ASAN lane (oven-sh/bun#31699) will exercise the-asanarm64 artifact end-to-end against Bun's full test suite.