Skip to content

v9.4.2 released

Choose a tag to compare

@funlang funlang released this 18 Oct 09:07
· 43 commits to main since this release
Fun 9.4.2

Regex matching and variable assignment stop repeating work on every run.

Highlights since v9.4.1:

- Regex patterns are compiled once. Compiled PCRE code is shared through a small
  LRU cache keyed by pattern text and options, with reference counting so a lazy
  match object always keeps its code alive; each regex literal holds its own
  reference, so the hot path skips the cache lookup. A pattern used a second
  time is upgraded to PCRE's JIT engine, with the upgrade deferred so a one-shot
  toRegex() pays no JIT cost.

- Global match/replace write into one growable buffer instead of splicing the
  subject once per match, turning the former O(n^2) replacement loop into a
  single pass. On the bundled Linux x86_64 build, 200 global replacements over
  a ~100 KB subject drop from ~7.3 s to ~0.24 s, repeated literal matching
  improves by ~1.4-1.5x, and a global match by ~3x. Literal replacements
  without $ or \ references skip the per-match replacement scan, making them
  another 25-40% faster.

- Global replacement computes $_ (and the other subject references) from the
  original subject. The old in-place loop rewrote the subject between matches,
  so 'abcabc'.replace(/b/g, '[$_]') produced a[abcabc]ca[a[abcabc]cabc]c; it
  now yields a[abcabc]ca[abcabc]c.

- Plain variable assignments are specialized at parse time. The first run
  resolves the target slot once; later runs read simple CId sources and write
  the scalar slot directly instead of repeating the virtual assign and scope
  push. On the bundled Linux x86_64 build, x = i drops from ~56 to ~38 ns/iter
  and a global gx = i from ~52 to ~33 ns/iter. Fields, indices,
  self-assignments and scope entries that still need a push keep the generic
  path.

Full list: CHANGELOG.md / CHANGELOG.zh.md.