Skip to content

macOS: JIT emits AVX on Macs without it, so a darwin-x64 baseline build SIGILLs once code tiers up #34215

Open

Description

@tobocop2

What version of Bun is running?

1.4.0-canary.1 (1e35118), built from main for darwin-x64 --baseline=true

What platform is your computer?

Darwin x86_64 — reproduced on two independent machines (see below)

What steps can reproduce the bug?

This is the second half of the pre-AVX2 Mac problem, and it is distinct from #32511.

#32511 / #32512 cover the startup crash: the shipped bun-darwin-x64-baseline links the Haswell macOS WebKit, whose bmalloc constructors use BMI2, so it SIGILLs before main(). oven-sh/WebKit#290 builds the missing Nehalem macOS WebKit and fixes that.

With that artifact in place, bun starts on a pre-AVX Mac — and then dies as soon as any code tiers up, because JavaScriptCore's JIT emits AVX regardless of the CPU:

./bun --version
# 1.4.0  -> rc=0, starts fine

./bun -e 'let s=0; for(let i=0;i<3e7;i++){s+=Math.sqrt(i)*1.000001;} console.log(s)'
# rc=132 -> SIGILL

BUN_JSC_useJIT=0 ./bun -e '...same loop...'
# rc=0   -> works

What is the expected behavior?

A --baseline darwin build should run on a CPU without AVX.

What do you see instead?

SIGILL once the JIT tiers up. The crash banner states the problem better than I can — bun's own CPU detection is correct, and JSC ignores it:

Bun Canary v1.4.0-canary.1 (1e3511800) macOS x64 (baseline)
macOS v14.6.1
CPU: sse42 popcnt                      <-- no AVX

Additional information

Root cause — Source/JavaScriptCore/assembler/MacroAssemblerX86_64.cpp hardcodes AVX as present on Darwin instead of asking the CPU:

#if OS(DARWIN)
        s_avxCheckState = CPUIDCheckState::Set;   // never checks the CPU
#else
        // CPUID.1:ECX.AVX[28] + OSXSAVE[27] + XCR0[2:1] == 11b
#endif

oven-sh/WebKit#198 fixed exactly this for Linux/Windows and guarded the new code with #if !OS(DARWIN), so Darwin kept the assumption. supportsAVX() then feeds ~10 VEX-emitting codegen sites. -march=nehalem cannot help, because the JIT decides at runtime.

Note AVX2 on Darwin is detected correctly, via sysctlbyname("hw.optional.avx2_0"). Only AVX is assumed — so Sandy/Ivy Bridge Macs (AVX, no AVX2) are unaffected by this one; it hits Macs with no AVX at all.

Reproduced on two independent machines:

test Mac Pro 5,1 — Xeon X5690, Westmere, macOS 14.7.8 Apple M1, x64 bun under Rosetta 2, macOS 14.6.1
bun --version rc=0 rc=0
JIT-heavy loop rc=132 rc=132
BUN_JSC_useJIT=0 rc=0 rc=0
opencode --version rc=132 rc=132

Rosetta 2 reports no AVX, so it reproduces the pre-AVX Mac case on rentable hardware.

Fix: oven-sh/WebKit#292 uses the same runtime check on Darwin that Linux/Windows already use. Verified: the preprocessed output for non-Darwin is byte-identical before/after (so Linux/Windows cannot regress); on AVX hardware the new check returns Set, matching the old hardcode exactly (so every real Mac is unchanged); and on Rosetta the JIT loop and opencode --version both go from rc=132 to rc=0.

Builds, if you have a pre-AVX Mac and want to try one now — a bun with this fix plus an opencode compiled against it: https://github.com/tobocop2/opencode-bun-pre-avx2-mac/releases/latest

Full chain for a working pre-Haswell Mac: oven-sh/WebKit#290 (build the baseline WebKit) → #34207 (add the darwin-x64-baseline lane) → oven-sh/WebKit#292 (this — stop the JIT emitting AVX).

Found by @WolfgangFahl on the X5690 in anomalyco/opencode#8345; @lumik0 flagged collectCPUFeatures() as the suspect area in #26872.

Activity

  1. github-actions commented on Jul 15, 2026

    @github-actions
    Contributor

    Found 2 possible duplicate issues:

    1. Illegal Instruction in macOS intel without AVX2 #26872
    2. Probabilistic SIGILL crash on no-AVX CPU with deep async recursion (baseline build) #27844

    This issue will be automatically closed as a duplicate in 3 days.

    • If your issue is a duplicate, please close it and 👍 the existing issue instead
    • To prevent auto-closure, add a comment or 👎 this comment

    🤖 Generated with Claude Code

  2. realityworks commented on Jul 16, 2026

    @realityworks

    @tobocop2 this wouldn't be a duplicate, as the source is different here right? You're referring to the 1.4.0 RUST version, the duplicates are in different variants of the codebase. I would expect the fix to be independent.

  3. tobocop2 commented on Jul 16, 2026

    @tobocop2
    Author

    @tobocop2 this wouldn't be a duplicate, as the source is different here right? You're referring to the 1.4.0 RUST version, the duplicates are in different variants of the codebase. I would expect the fix to be independent.

    Right that it's not a duplicate, but the reason isn't the Zig/Rust rewrite.

    The bug is in JavaScriptCore, which both variants link as the same prebuilt.

    #26872 is a different bug entirely (startup crash on AVX-capable Macs, fixed by oven-sh/WebKit#290 + #34207)

    #27844 is the Linux instance of this class already fixed by oven-sh/WebKit#198 I think

    This issue is the remaining Darwin case fixed by oven-sh/WebKit#292.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions