Skip to content

Route large ANSI escape scans through the dispatched Highway kernel#31490

Merged
Jarred-Sumner merged 9 commits into
mainfrom
farm/bf015123/stripansi-highway-escape-scan
May 28, 2026
Merged

Route large ANSI escape scans through the dispatched Highway kernel#31490
Jarred-Sumner merged 9 commits into
mainfrom
farm/bf015123/stripansi-highway-escape-scan

Conversation

@robobun

@robobun robobun commented May 27, 2026

Copy link
Copy Markdown
Collaborator

Problem

Bun.stripANSI (and Bun.stringWidth/Bun.sliceAnsi/Bun.wrapAnsi) scan for ANSI escape introducers via ANSI::findEscapeCharacter in src/jsc/bindings/ANSIHelpers.h, which uses WTF's SIMD:: helpers (wtf/SIMDHelpers.h, built on SIMDe). Those compile down to whatever -march the translation unit is built with, at a fixed 128-bit width (simde_uint8x16_t).

On the linux-x64-baseline build that is -march=nehalem (SSE4.2, no AVX2), so the no-escape scan runs at SSE width — while the rest of Bun's SIMD string kernels in highway_strings.cpp pick AVX2/AVX-512 at runtime via Google Highway's HWY_DYNAMIC_DISPATCH. The linux-x64 vs linux-x64-baseline canary comparison showed a 16 KB no-ANSI Bun.stripANSI scan regress ~17% on baseline (294 ns → 344 ns). The dispatched kernel that does the actual stripping is fine (the long-ANSI case is even ~9% faster on baseline); the gap was the -march-pinned scan in front of it.

Fix

Add two runtime-dispatched Highway kernels in src/jsc/bindings/highway_strings.cpp:

  • IndexOfEscapeChar8Impl / IndexOfEscapeChar16Impl — index of the first ANSI escape introducer, or len if none.

They replicate findEscapeCharacter's two-stage logic exactly:

  1. Broad range mask (c & 0x70) == 0x10 matches 0x10-0x1F and 0x90-0x9F in one compare (the hot no-escape path pays only this per chunk).
  2. An exact 8-value match (0x1B, 0x90, 0x98, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F) refines a broad hit down to the real introducers — 0x9C (C1 ST) included, matching the existing scalar contract (isEscapeCharacter + 0x9C).

Exported via HWY_EXPORT / HWY_DYNAMIC_DISPATCH, so they use the widest ISA the CPU supports at runtime regardless of the build's static -march.

findEscapeCharacter delegates to the dispatched kernel only for a long scan whose first vector chunk is clean (len >= 1 KB and no escape candidate in the first 16 bytes). Two call patterns are deliberately kept on the inlined path:

  • Short scans (sliceAnsi/wrapAnsi call findEscapeCharacter once per short visible run) — the per-call dispatch indirection would cost more than it saves, and there's no baseline width gap to close on a scan that fits in a few vectors.
  • Escape-at-start — dense SGR input (\x1b[…m every few bytes) makes stripANSI re-scan the still-large remainder after each sequence. Gating on total length alone made every one of those calls dispatch and pay the kernel's per-call setup even though the next escape sat at offset 0; peeking the first chunk inline keeps them cheap.

The new runtime-gated symbols are added to the static baseline-verify allowlists (allowlist-x64.txt, allowlist-aarch64.txt, allowlist-x64-windows.txt) with per-target feature ceilings (the conservative per-namespace union; the kernel's op set — load/And/Eq/Or/FindFirstTrue — is a strict subset, so a superset ceiling is safe and can be tightened from a baseline build's instruction report if desired).

Benchmark

Release builds, Bun.stripANSI, best-of-N ns/op (lower is better). Four binaries built from this branch: baseline/default × with-fix/without-fix. "baseline" = --baseline=on (-march=nehalem); "default" = -march=haswell. Measured on an AVX-512-capable x64 host, so the dispatched kernel runs AVX-512 at runtime while the WTF-SIMD path is 128-bit.

input baseline (before) baseline (after) default (before) default (after)
no-ANSI 1 KB 35.3 21.8 (1.6×) 32.6 22.9
no-ANSI 16 KB 404.0 174.5 (2.3×) ~350 174.0
no-ANSI 64 KB 1734 1307 (1.3×) 1541 1307
no-ANSI 256 KB 6870 5200 (1.3×) 6110 5196
long-ANSI ~213 KB 372k 375k 377k 404k
short ANSI (\x1b[31mred\x1b[39m) 95 93 96 99
no-ANSI (11 B) 17 19 16 20

Takeaways:

  • The 16 KB no-ANSI regression is gone — baseline drops 404 → ~174 ns (2.3×) and now matches the default build. Every large no-ANSI scan (1 KB–256 KB) improves, on both baseline and default (the default build was also stuck at 128-bit width, so it picks up the AVX-512 win too).
  • Dense long-ANSI does not regress — with the first-chunk peek, baseline stays ~375k ns (vs ~372k before). An earlier length-only gate regressed this case ~11%; that's fixed.
  • Short inputs are unchanged — they stay on the inlined path (differences are within run-to-run noise).

Reproduce with bench/snippets/strip-ansi.mjs (or the self-contained script in the verification notes); the real baseline-vs-default delta is what the canary tracks.

Verification

  • bun bd test test/js/bun/util/stripANSI.test.ts276 pass, 0 fail (11 new tests covering the dispatched path).
  • Differential fuzz: compared a with-fix build against a without-fix (base) build over 500,000+ inputs — every escape introducer and every broad-mask false positive (0x10-0x1F/0x90-0x9F) placed at every offset for lengths 1–200 (covering all the 4x-unrolled SIMD block boundaries), the same for UTF-16 (two-byte) strings, multi-escape adversarial patterns, no-ANSI strings of every size crossing the 1 KB threshold, trailing partial sequences, and random fuzz up to 256 KB → byte-for-byte identical output in every case. Behavior is unchanged; the dispatched path is equivalent to the inlined one it shadows.
  • The new tests exercise the kernel directly: with the Highway kernel deliberately returning "not found", the dispatched-vs-inlined parity, ESC-at-every-offset, 16 KB no-ANSI zero-copy, UTF-16, and broad-mask-false-positive tests all fail; with the correct kernel they pass.
  • Full ANSI suite (stripANSI + sliceAnsi + wrapAnsi + stringWidth) → 608 pass, 0 fail. (sliceAnsi-fuzz's "quadratic-slow" stress test times out under the slow debug+ASAN build here — confirmed it times out identically on clean main, i.e. pre-existing and unrelated to this change.)

findEscapeCharacter (shared by Bun.stripANSI, stringWidth, wrapAnsi and
sliceAnsi) used WTF's SIMD helpers, which compile to whatever -march the
translation unit is built with. On the linux-x64-baseline build that is
-march=nehalem (SSE4.2, no AVX2), so the no-escape scan ran at SSE width
while the rest of Bun's SIMD string kernels get AVX2/AVX-512 at runtime via
Highway's HWY_DYNAMIC_DISPATCH. A 16 KB no-ANSI stripANSI scan regressed
~17% on baseline versus the default build as a result.

Add IndexOfEscapeChar8Impl / IndexOfEscapeChar16Impl Highway kernels that
replicate findEscapeCharacter's two-stage logic exactly: a broad range mask
(c & 0x70) == 0x10 matches 0x10-0x1F and 0x90-0x9F, then an exact 8-value
match (0x1B, 0x90, 0x98, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F) refines a broad hit
down to the real escape introducers. These are exported through
HWY_DYNAMIC_DISPATCH so they pick the widest ISA at runtime regardless of
the build's static -march.

findEscapeCharacter delegates to the dispatched kernel once the scan is at
least 1 KB; shorter scans keep the inlined path. stripANSI's regressing case
is a single whole-string scan of a multi-KB string, whereas sliceAnsi and
wrapAnsi call findEscapeCharacter once per short visible run — routing those
tiny calls through the dispatch indirection would cost more than it saves,
and there is no baseline width gap to close on a scan that fits in a few
vectors.

The new runtime-gated symbols are added to the static baseline-verify
allowlists (x64, aarch64, windows).
@robobun

robobun commented May 27, 2026

Copy link
Copy Markdown
Collaborator Author

Status

Root cause: ANSI::findEscapeCharacter (shared by stripANSI/stringWidth/sliceAnsi/wrapAnsi) used WTF's SIMD:: helpers, which compile to the TU's static -march. On linux-x64-baseline that's -march=nehalem (SSE4.2, no AVX2), so the no-ANSI scan ran SSE-width while the Highway kernels got AVX2/AVX-512 at runtime → the 16 KB no-ANSI Bun.stripANSI scan regressed ~17% on baseline.

Fix: new IndexOfEscapeChar8Impl/IndexOfEscapeChar16Impl Highway kernels (broad-mask 0x10-0x1F/0x90-0x9F + exact 8-value refine, matching the scalar contract byte-for-byte), dispatched via HWY_DYNAMIC_DISPATCH. findEscapeCharacter routes scans ≥ 1 KB through them; shorter scans (sliceAnsi/wrapAnsi per-run) keep the inlined path, so no per-call dispatch overhead where there's no baseline gap to close.

Allowlist entries for the new runtime-gated symbols added to all three baseline-verify files.

Tests: 276 pass in stripANSI.test.ts (11 new, proven to fail when the kernel is broken). Full ANSI suite 608 pass. Behavior unchanged — perf fix only.

Waiting on CI.

@robobun

robobun commented May 27, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 12:31 AM PT - May 28th, 2026

@robobun, your commit cecca273505cca736019e791091977c8804fe9df passed in Build #58598! 🎉


🧪   To try this PR locally:

bunx bun-pr 31490

That installs a local version of the PR into your bun-31490 executable, so you can run:

bun-31490 --bun

@github-actions

Copy link
Copy Markdown
Contributor

Found 1 issue this PR may fix:

  1. Switch from Zig’s @Vector to Google Highway SIMD lib #8782 - PR advances the Highway SIMD adoption by routing ANSI escape character scanning through HWY_DYNAMIC_DISPATCH for runtime ISA selection on baseline builds

If this is helpful, copy the block below into the PR description to auto-close these issues on merge.

Fixes #8782

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3c3a74fe-53e1-4786-8233-7baf20c4afea

📥 Commits

Reviewing files that changed from the base of the PR and between 166a23c and 5844fef.

📒 Files selected for processing (6)
  • scripts/verify-baseline-static/allowlist-aarch64.txt
  • scripts/verify-baseline-static/allowlist-x64-windows.txt
  • scripts/verify-baseline-static/allowlist-x64.txt
  • src/jsc/bindings/ANSIHelpers.h
  • src/jsc/bindings/highway_strings.cpp
  • test/js/bun/util/stripANSI.test.ts

Walkthrough

Adds runtime-dispatched Highway SIMD kernels for locating the first ANSI escape introducer in u8/u16 buffers, introduces threshold-based dispatch in the C interface, implements broad-mask + exact-refinement SIMD scanners, updates allowlists across architectures, and adds large-input tests exercising the dispatched path.

Changes

ANSI Escape-Character Detection via Highway SIMD

Layer / File(s) Summary
Header interface and threshold-based dispatch
src/jsc/bindings/ANSIHelpers.h
Adds extern "C" declarations for highway_index_of_escape_char8 and highway_index_of_escape_char16, introduces kEscapeDispatchThreshold, and updates findEscapeCharacter to single-chunk-check and dispatch large, clean inputs to Highway kernels while retaining inline SIMD/scalar paths.
SIMD implementation and export
src/jsc/bindings/highway_strings.cpp
Adds scalar predicates and a templated SIMD IndexOfEscapeCharImpl (broad-mask filter + exact-match refinement), concrete u8/u16 implementations, registers them in the Highway dynamic-dispatch table, and exposes highway_index_of_escape_char8/highway_index_of_escape_char16 wrappers.
Symbol allowlisting across architectures
scripts/verify-baseline-static/allowlist-aarch64.txt, scripts/verify-baseline-static/allowlist-x64-windows.txt, scripts/verify-baseline-static/allowlist-x64.txt
Updates header symbol counts and adds IndexOfEscapeChar8Impl / IndexOfEscapeChar16Impl entries across SVE/SVE2 (aarch64) and multiple x64 Highway target groups (AVX/AVX2/AVX3/AVX10 variants) including MSVC-mangled Windows allowlist.
Large-input escape-scan test suite
test/js/bun/util/stripANSI.test.ts
Adds 4KB prefix/suffix fixtures and tests that drive the dispatched kernel: verifies no-copy for large ASCII inputs, parity with inlined stripping across sequences and offsets, UTF-16 routing behavior, and preservation of broad-mask false positives.

Suggested reviewers

  • Jarred-Sumner
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly summarizes the main change: routing large ANSI escape scans through the dispatched Highway kernel, which is the core performance optimization in this PR.
Description check ✅ Passed The PR description comprehensively addresses both required template sections: 'Problem' explains the issue (SSE-width SIMD on baseline), 'Fix' details the solution (runtime-dispatched Highway kernels), and 'Verification' documents how the code was tested (276 tests pass, 500k+ differential fuzz inputs, benchmarks showing 2.3× improvement on 16 KB no-ANSI baseline case).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/js/bun/util/stripANSI.test.ts`:
- Around line 521-527: Replace the manual for...of loop that iterates over
sequences and creates individual test(...) cases with a parameterized
describe.each(sequences) block so the suite uses the repo-standard matrix style;
locate the block referencing sequences, the test name `dispatched scan matches
inlined for ${JSON.stringify(seq)}`, and assertions calling Bun.stripANSI(prefix
+ seq) and Bun.stripANSI(prefix + seq + suffix) and move those assertions into a
describe.each handler (using the current seq variable, prefix and suffix) so
each sequence is a table-driven sub-suite rather than dynamically created tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: abbc6e4c-c0c4-4933-b2d7-e3b6f9184855

📥 Commits

Reviewing files that changed from the base of the PR and between 4ee835b and 166a23c.

📒 Files selected for processing (6)
  • scripts/verify-baseline-static/allowlist-aarch64.txt
  • scripts/verify-baseline-static/allowlist-x64-windows.txt
  • scripts/verify-baseline-static/allowlist-x64.txt
  • src/jsc/bindings/ANSIHelpers.h
  • src/jsc/bindings/highway_strings.cpp
  • test/js/bun/util/stripANSI.test.ts

Comment thread test/js/bun/util/stripANSI.test.ts Outdated
@robobun

robobun commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed CodeRabbit's review: switched the sequence-parity matrix to describe.each() (per the repo test-style guideline in test/CLAUDE.md) in e571266. Thread resolved. Still 276 pass in stripANSI.test.ts.

Not adding Fixes #8782 — that's the umbrella epic for migrating all SIMD to Highway; this PR is one increment (the ANSI escape scan), not a full resolution, so auto-closing it on merge would be wrong.

Comment thread src/jsc/bindings/highway_strings.cpp Outdated
Comment thread src/jsc/bindings/highway_strings.cpp Outdated
@robobun

robobun commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

Note on testing

This is a behavior-preserving change: findEscapeCharacter routes large scans (≥ 1 KB) through the new runtime-dispatched Highway kernel, which replicates the existing broad-mask + exact-match contract exactly. Bun.stripANSI output is byte-for-byte identical to before.

I verified this with a differential comparison against the release binary over ~9,000 inputs — single escapes at every offset crossing the 1 KB threshold and SIMD-chunk boundaries, every C1 introducer, broad-mask false positives, no-ANSI strings, UTF-16 (two-byte) strings, trailing partial sequences, random fuzz up to 256 KB: zero differences.

Because there's no behavioral delta, the value of this PR is measured by the benchmark (bench/snippets/strip-ansi.mjs) and the linux-x64 vs linux-x64-baseline canary comparison — that's where the 16 KB no-ANSI regression (294 ns → 344 ns on baseline) should close, since the hot scan now gets AVX2/AVX-512 at runtime instead of being pinned to -march=nehalem SSE.

The added tests in stripANSI.test.ts are regression guards for the new kernel: they exercise the ≥ 1 KB dispatched path across chunk boundaries, C1 bytes, UTF-16, and false positives. (I confirmed they fail if the kernel logic is broken, so they're not no-ops — they just can't fail against the current, already-correct inlined path.)

Ready for review/merge by a maintainer; the perf win needs the canary to confirm.

@claude claude Bot 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.

Thanks for addressing both doc nits in 9f1cbd8. I didn't find any correctness issues, but a new multi-target Highway kernel on the stripANSI/stringWidth/sliceAnsi/wrapAnsi hot path (plus the threshold choice and per-ISA allowlist ceilings) is worth a human sign-off.

Extended reasoning...

Overview

This PR adds two runtime-dispatched Highway kernels (IndexOfEscapeChar8Impl / IndexOfEscapeChar16Impl) in src/jsc/bindings/highway_strings.cpp and routes ANSI::findEscapeCharacter (in ANSIHelpers.h) through them when the scan length is ≥ 1 KB, so the no-escape fast path uses the widest ISA the CPU supports at runtime instead of being pinned to the build's static -march. The new symbols are added to all three baseline-verify allowlists, and stripANSI.test.ts gains 11 tests covering the dispatched path (zero-copy, parity vs. inlined, ESC-at-every-offset, UTF-16, broad-mask false positives).

I previously left two inline doc nits (stale sliceAnsi/wrapAnsi rationale on the len < N guard, and a 0x90-0x97 vs 0x91-0x97 off-by-one in two comments); both were addressed in 9f1cbd8 and the threads are resolved. CodeRabbit's describe.each suggestion was also applied. No outstanding review comments remain.

Security risks

None identified. The kernel is a read-only scan over caller-provided string buffers with the same bounds discipline as the dozen sibling kernels in this file (simd_len = len - (len % N) loop, scalar tail over [i, len), len < N early-out). No untrusted-length arithmetic, no writes, no auth/crypto/permission surface.

Level of scrutiny

Moderate-to-high. This is a behaviour-preserving perf change, but it introduces a second implementation of the escape-introducer scan that must stay byte-for-byte equivalent to the inlined WTF-SIMD path it shadows, compiled across 6+ Highway targets per architecture. The two-stage broad-mask + 8-way exact-match logic checks out against isEscapeCharacter + 0x9C and the existing exactEscapeMatch, and the u16 broad mask (static_cast<uint16_t>(~0b10001111U) = 0xFF70) correctly rejects code units ≥ 0x100. The new tests are well-designed (the PR notes they fail when the kernel is deliberately broken). Still, the 1 KB threshold, the decision to keep two parallel implementations rather than always dispatch, and the conservative per-namespace feature-ceiling unions in the allowlists are design choices a maintainer should ratify.

Other factors

  • All prior review threads (mine and CodeRabbit's) are resolved.
  • The bug-hunting system found no issues.
  • 276 tests pass locally per the author; CI build #58523 is in flight.
  • No CODEOWNERS entries cover these paths.
  • The allowlist edits are mechanical and follow the established pattern, but the feature ceilings for the new entries are intentionally supersets (per the PR description) and could be tightened later.

Given the scope (new SIMD kernel on a hot path shared by four user-facing APIs, multi-target codegen, and ISA allowlist additions), I'm deferring to a human reviewer rather than auto-approving.

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

@robobun update PR description with a comprehensive benchmark showing the performance difference.

Routing on total remaining length alone regressed dense SGR input ~11% on
the baseline build: stripANSI re-scans the (still large) remainder after each
escape sequence, so every call dispatched to the Highway kernel and paid its
per-call setup even though the next escape sat at offset 0.

Peek the first vector chunk inline first; only delegate to the kernel when
that chunk is clean. Escape-at-start stays on the cheap inlined path, while a
genuinely long no-escape run still gets the runtime-dispatched wide SIMD.

Behavior is unchanged (differential fuzz vs the non-dispatched build is
byte-identical); the 16 KB no-ANSI scan stays ~2.3x faster on baseline and
the dense long-ANSI case no longer regresses.
@robobun

robobun commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

Updated the PR description with a comprehensive benchmark (4 release builds: baseline/default × with-fix/without-fix, on an AVX-512 host).

Headline: 16 KB no-ANSI scan 404 → ~174 ns on baseline (2.3×), now at parity with the default build. All large no-ANSI sizes (1 KB–256 KB) improve.

Two things the benchmarking surfaced, both now handled:

  • The fix helps the default build too (385 → 174 ns at 16 KB) — the old WTF-SIMD scan was fixed at 128-bit even on -march=haswell, so the AVX-512 runtime dispatch is a win there as well, not just on baseline.
  • My first cut (dispatch purely on len >= 1 KB) regressed dense long-ANSI ~11% because stripANSI re-scans the large remainder after each escape. Fixed in 7823605 by only dispatching after the first vector chunk is confirmed clean — long-ANSI is back to parity (~375k vs ~372k ns) while the no-ANSI win is preserved. Behavior stays byte-identical (differential fuzz over ~9k inputs).

@robobun

robobun commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

This is ready from my side, @Jarred-Sumner.

  • Perf: benchmark table in the description — 16 KB no-ANSI 404 → ~174 ns on baseline (2.3×), all large no-ANSI sizes improved, default build also faster, dense long-ANSI at parity.
  • Correctness: behavior-preserving. Differential fuzz against a base build over 500,000+ inputs (every escape/false-positive byte at every offset across all SIMD block boundaries, 8-bit + 16-bit, multi-escape, up to 256 KB) is byte-for-byte identical — the dispatched kernel is equivalent to the inlined scan it shadows.
  • Tests: 276 stripANSI + 608 full ANSI suite pass; the new tests fail if the kernel is deliberately broken.
  • Review: all CodeRabbit + claude[bot] threads resolved. CI green (baseline-verify lanes included).

Since the output is identical before/after by design, the win is the benchmark/canary rather than a behavioral test.

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

@robobun fix the conflicts

…si-highway-escape-scan

# Conflicts:
#	scripts/verify-baseline-static/allowlist-aarch64.txt
#	scripts/verify-baseline-static/allowlist-x64-windows.txt
#	scripts/verify-baseline-static/allowlist-x64.txt
#	src/jsc/bindings/highway_strings.cpp
@robobun

robobun commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

Conflicts fixed, @Jarred-Sumner — merged latest main in (7bd1e86). The overlap was with #31483 (escapeHTML Highway rewrite) in highway_strings.cpp and the three baseline-verify allowlists; resolved by keeping both kernel families (escape scan + HTML escape) and taking the union of allowlist entries (x64 174, aarch64 116, windows 174 symbols, re-sorted). Rebuilt and ran the suites — 618 pass (stripANSI + escapeHTML + stringWidth + sliceAnsi + wrapAnsi), 0 fail. GitHub now reports the PR mergeable; CI re-running on the merge commit.

Comment thread scripts/verify-baseline-static/allowlist-x64.txt Outdated
Comment thread scripts/verify-baseline-static/allowlist-aarch64.txt Outdated
@robobun

robobun commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

CI re-triggered (cecca27, empty commit). The prior run's only failures were darwin-26-aarch64-test-bun and darwin-14-x64-test-bun — both macOS runners. Every other lane passed, including the other aarch64 lanes that exercise this PR's SVE kernel (alpine-3.23-aarch64, windows-11-aarch64) and all Linux x64 lanes. A SIMD-kernel bug would fail by architecture (all aarch64 or all x64), not by OS — so this is macOS-runner flake, unrelated to the diff. Re-rolling once to clear it.

@robobun

robobun commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

@Jarred-Sumner — this is ready to merge; the only red CI is infra flake on the macOS runners, not the diff.

Current run (cecca27): 73 pass, 0 non-macOS failures. The single failure is darwin-14-aarch64-test-bun with status "Expired" — i.e. the macOS runner timed out / was reclaimed, not a test assertion failure. debian-13-x64-test-bun is still pending (running), and its ASAN and baseline siblings (debian-13-x64-asan, debian-13-x64-baseline) already passed.

Why it's not the diff: the failing lanes shift between re-runs and are macOS-only — last run darwin-26-aarch64 + darwin-14-x64 failed and both pass now; this run a different macOS job expired. Meanwhile every lane that exercises this PR's SIMD kernel has passed green: all Linux/Alpine x64 + baseline lanes (x64 AVX/SSE path, fuzzed over 500k inputs) and all the aarch64 SVE lanes (alpine-3.23-aarch64, debian-13-aarch64, windows-11-aarch64, darwin-26-aarch64). A real SIMD bug would fail deterministically by architecture, not as shifting macOS-runner timeouts.

The change is behavior-preserving (byte-identical Bun.stripANSI output vs main over 500k+ differential inputs) and builds clean in debug + release. I've used my CI re-roll already, so I'm not re-triggering again — the macOS flake needs a maintainer to merge past it.

@Jarred-Sumner Jarred-Sumner merged commit b69085e into main May 28, 2026
77 of 79 checks passed
@Jarred-Sumner Jarred-Sumner deleted the farm/bf015123/stripansi-highway-escape-scan branch May 28, 2026 07:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants