mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-02 07:43:42 +08:00
libregexp compiles every non-sticky pattern with a `.*?` search prefix and interprets its bytecode one opcode at a time, so an unanchored search pays a backtrack push/pop and ~7 dispatches per subject position, and each `x+` iteration pushes a backtrack state. Profiles of regex-logs and template-render showed 65-85% of samples inside lre_exec. scr_regex_native.h translates the compiled bytecode body (the bytecode stays the source of truth for parsing, flags, case folding and capture numbering) into a small program for one-byte subjects: - single-character opcodes become 128-entry tables computed by evaluating the interpreter's own predicate (lre_canonicalize, lre_is_space, range pairs) for each ASCII code unit, so /i and /u are exact on these subjects; - quantifiers over one character become counted loops that backtrack by count; greedy loops whose continuation cannot start with a byte of the loop's class (or is just saves + match) are possessive; - runs of literal bytes become one memcmp; - splits, gotos, saves, capture resets, counted group loops and empty-check registers keep libregexp's exact backtracking order and undo semantics; - unanchored searches start only at bytes that can begin a match (memchr for a single byte) and only at 0 for non-multiline `^` patterns. Lookaround and back references, and all non-ASCII subjects, keep lre_exec. scr_exec is the single dispatch point, so every match loop is shared. The program is built with the bytecode and cached on ScrRegex (new `native` slot; the emitter's %ScrRegex type and literal initializer gain one null pointer). Tests: packages/runtime/test/test_regex_native.c fuzzes the matcher against lre_exec (random patterns over the subset and its bail-outs, every start index, all capture slots; ASan+UBSan), wired into regex.test.ts; a sweep of 8 seeds x 100k patterns (~575k translated, ~70.7M checks) found no mismatch. tests/corpus/regex-native-matcher.ts pins each construct through the public APIs on ASCII subjects and non-ASCII twins. Squashes 1d210a03: build the fuzz test with -D_GNU_SOURCE on Linux; the vendored cutils.h needs CLOCK_MONOTONIC, which strict -std=c11 hides on glibc.