Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: f4f06bc1151fe9f14da9f05774162f39351ed537
https://github.com/WebKit/WebKit/commit/f4f06bc1151fe9f14da9f05774162f39351ed537
Author: Sosuke Suzuki <[email protected]>
Date: 2026-08-12 (Wed, 12 Aug 2026)
Changed paths:
A JSTests/microbenchmarks/regexp-lookbehind-fixed.js
A JSTests/microbenchmarks/regexp-lookbehind-negative-alternation.js
A JSTests/microbenchmarks/regexp-lookbehind-replace.js
A JSTests/microbenchmarks/regexp-lookbehind-variable.js
A JSTests/stress/regexp-lookbehind-jit-alternatives.js
A JSTests/stress/regexp-lookbehind-jit-captures.js
A JSTests/stress/regexp-lookbehind-jit-hot-loop.js
A JSTests/stress/regexp-lookbehind-jit-large-offset.js
A JSTests/stress/regexp-lookbehind-jit.js
M Source/JavaScriptCore/runtime/RegExp.cpp
M Source/JavaScriptCore/yarr/YarrJIT.cpp
Log Message:
-----------
[YARR] Compile lookbehinds
in the JIT
https://bugs.webkit.org/show_bug.cgi?id=321496
Reviewed by Daniel Liu.
A pattern containing a lookbehind never reached YarrJIT: RegExp::compile did
not call
jitCompile for it and YarrGenerator::compile bailed out on
m_containsLookbehinds, so a single
lookbehind sent the whole pattern, including everything around it, to the
interpreter.
A lookbehind matches its disjunction backward, ending at the current position,
which is the
same as matching the reversed sequence of its terms while consuming input
downward. This patch
makes opCompileParentheticalAssertion compile a Backward assertion from a copy
of its
disjunction in which each alternative has its terms reversed and its input
positions reassigned
the way setupAlternativeOffsets() does (reverseDisjunctionForBackward), so the
existing op
compilation, code generation and backtracking are reused as they are. The
YarrPattern is left
untouched for the interpreter fallback.
The ops compiled from it are marked
Backward, and only the primitives that touch the index
register look at the direction: index is the start of the input consumed so
far, so claiming
input subtracts and checks index >= 0, the character `offset` before index is
read from
input[index + offset - 1], the end of input is index == 0, greedy terms consume
with index -= 1
and give back with index += 1, a capture stores its end when the parenthesis
begins and its
start when it ends, and ^ $ \b test the start / end of input and read the
surrounding
characters through canBeAtStartOfInput() and friends. The machine code
generated for Forward
ops is unchanged.
Unicode patterns with a lookbehind, and lookbehinds containing a backreference,
a lookahead,
or a quantified parenthesis still fall back to the interpreter, and Backward
ops do not combine
adjacent characters into a wider load yet.
Follow-up patches are planned to (1) JIT the remaining lookbehind shapes above
and optimize
Backward ops further, (2) make the
interpreter match lookbehinds from a reversed disjunction
in the same way instead of its own backward bookkeeping, and then (3) have
YarrPatternConstructor
build the disjunction of a lookbehind in reversed form from the start, so that
both tiers share
one representation and this copy goes away.
Baseline
Patched
regexp-lookbehind-variable 167.9369+-2.1830 ^
34.5673+-0.2600 ^ definitely 4.8583x faster
regexp-lookbehind-negative-alternation 470.5741+-1.4593 ^
48.5470+-0.2605 ^ definitely 9.6932x faster
regexp-lookbehind-fixed 233.4527+-4.8987 ^
44.8282+-0.4900 ^ definitely 5.2077x faster
regexp-lookbehind-replace 651.3264+-5.8342 ^
61.1449+-1.7254 ^ definitely 10.6522x faster
regexp-exec 14.5383+-0.1674 ?
14.6957+-0.2200 ? might be 1.0108x
slower
Tests: JSTests/microbenchmarks/regexp-lookbehind-fixed.js
JSTests/microbenchmarks/regexp-lookbehind-negative-alternation.js
JSTests/microbenchmarks/regexp-lookbehind-replace.js
JSTests/microbenchmarks/regexp-lookbehind-variable.js
JSTests/stress/regexp-lookbehind-jit-alternatives.js
JSTests/stress/regexp-lookbehind-jit-captures.js
JSTests/stress/regexp-lookbehind-jit-hot-loop.js
JSTests/stress/regexp-lookbehind-jit-large-offset.js
JSTests/stress/regexp-lookbehind-jit.js
* JSTests/microbenchmarks/regexp-lookbehind-fixed.js: Added.
* JSTests/microbenchmarks/regexp-lookbehind-negative-alternation.js: Added.
* JSTests/microbenchmarks/regexp-lookbehind-replace.js: Added.
* JSTests/microbenchmarks/regexp-lookbehind-variable.js: Added.
* JSTests/stress/regexp-lookbehind-jit-alternatives.js: Added.
(shouldBe):
(matchOf):
(shouldBe.matchOf):
(shouldBe.matchOf.b):
*
JSTests/stress/regexp-lookbehind-jit-captures.js: Added.
(shouldBe):
(matchOf):
(shouldBe.matchOf.a):
* JSTests/stress/regexp-lookbehind-jit-hot-loop.js: Added.
(shouldBe):
(execConstant):
(testVarying):
(replaceAll):
(searchSticky):
* JSTests/stress/regexp-lookbehind-jit-large-offset.js: Added.
(shouldBe):
(matchOf):
* JSTests/stress/regexp-lookbehind-jit.js: Added.
(shouldBe):
(matchOf):
(shouldBe.matchOf):
(string_appeared_here.string_appeared_here.repeat):
* Source/JavaScriptCore/runtime/RegExp.cpp:
(JSC::RegExp::compile):
(JSC::RegExp::compileMatchOnly):
* Source/JavaScriptCore/yarr/YarrJIT.cpp:
(JSC::Yarr::dumpCompileFailure):
Canonical link:
https://flagged.apple.com:443/proxy?t2=DW7d4H4Dq5&o=aHR0cHM6Ly9jb21taXRzLndlYmtpdC5vcmcvMzE5MDY3QG1haW4=&emid=d45ee5ac-40a8-4d5b-ac3a-f07ff9dea825&c=11
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications