diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2024-12-10 10:26:34 +0100 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-12-12 08:00:24 +0100 |
| commit | b4b691b040f2251820292a27bdcf01d4d7530bc6 (patch) | |
| tree | b44e3672f38dc53bb503fc336646ddc1ef050017 /src/qml/jsruntime/qv4regexp.cpp | |
| parent | c5b0fa28061fc3e99ce79ff9603d87791b41a197 (diff) | |
QtQml: Add some consistency to QV4::RegExp
The RegExp JIT should behave the same as the V4 JIT. In particular, it
should honor the same JIT call threshold and not second guess any
manually set thresholds. To do this we need to store the match count in
32 bits. In turn we can store the 5 flags we may have in 8 bits. To make
this safe, pass typed flags to the initialization functions. Also,
consider the flags when calculating hash values. Finally, in the init()
function, we don't need to initialize members to zero, since that is
already guaranteed by the memory manager. And we can delete the
flagsAsString() method since it's unused.
This requires shuffling some #includes into the places where they
actually belong.
[ChangeLog][QtQml] The JavaScript regular expression engine now honors
QV4_JIT_CALL_THRESHOLD for its own JIT. If QV4_JIT_CALL_THRESHOLD is
not set, it uses the JIT after 3 interpreted matches for any regular
expression, rather than the previous 5. Matching a regular expression
on a string longer than 1024 bytes counts as 3 matches. This is to
retain the default behavior of JIT'ing regular expressions right away
when encountering long strings.
Task-number: QTBUG-131957
Change-Id: I269ccea55d34b191ef18d7cd5fccd4cad8aec7cd
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4regexp.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4regexp.cpp | 67 |
1 files changed, 30 insertions, 37 deletions
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 9c48199157..8dd14d3a43 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -10,10 +10,11 @@ using namespace QV4; #if ENABLE(YARR_JIT) -static constexpr quint8 RegexpJitThreshold = 5; +static constexpr qsizetype LongStringJitThreshold = 1024; +static constexpr int LongStringJitBoost = 3; #endif -static JSC::RegExpFlags jscFlags(uint flags) +static JSC::RegExpFlags jscFlags(quint8 flags) { JSC::RegExpFlags jscFlags = JSC::NoFlags; if (flags & CompiledData::RegExp::RegExp_Global) @@ -71,22 +72,33 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) regexp->byteCode = nullptr; }; - if (!priv->jitCode && !priv->jitFailed && priv->internalClass->engine->canJIT() - && (string.length() > 1024 || priv->matchCount++ == RegexpJitThreshold)) { - removeByteCode(priv); + if (!priv->jitCode) { - JSC::Yarr::ErrorCode error = JSC::Yarr::ErrorCode::NoError; - JSC::Yarr::YarrPattern yarrPattern( - WTF::String(*priv->pattern), jscFlags(priv->flags), error); - if (!yarrPattern.m_containsBackreferences) { - priv->jitCode = new JSC::Yarr::YarrCodeBlock; - JSC::VM *vm = static_cast<JSC::VM *>(priv->internalClass->engine); - JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, vm, *priv->jitCode); - } + // Long strings count as more calls. We want the JIT to run earlier. + const bool longString = string.length() > LongStringJitThreshold; + if (longString) + priv->interpreterCallCount += LongStringJitBoost; + + if (priv->internalClass->engine->canJIT(priv)) { + removeByteCode(priv); + + JSC::Yarr::ErrorCode error = JSC::Yarr::ErrorCode::NoError; + JSC::Yarr::YarrPattern yarrPattern( + WTF::String(*priv->pattern), jscFlags(priv->flags), error); + if (!yarrPattern.m_containsBackreferences) { + priv->jitCode = new JSC::Yarr::YarrCodeBlock; + JSC::VM *vm = static_cast<JSC::VM *>(priv->internalClass->engine); + JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, vm, *priv->jitCode); + } - if (!priv->hasValidJITCode()) { - removeJitCode(priv); - regenerateByteCode(priv); + if (!priv->hasValidJITCode()) { + removeJitCode(priv); + regenerateByteCode(priv); + } + } else if (!longString) { + // Short strings do the regular post-increment to honor + // QV4_JIT_CALL_THRESHOLD. + ++priv->interpreterCallCount; } } #endif @@ -172,23 +184,8 @@ QString RegExp::getSubstitution(const QString &matched, const QString &str, int return result; } -QString Heap::RegExp::flagsAsString() const -{ - QString result; - if (flags & CompiledData::RegExp::RegExp_Global) - result += QLatin1Char('g'); - if (flags & CompiledData::RegExp::RegExp_IgnoreCase) - result += QLatin1Char('i'); - if (flags & CompiledData::RegExp::RegExp_Multiline) - result += QLatin1Char('m'); - if (flags & CompiledData::RegExp::RegExp_Unicode) - result += QLatin1Char('u'); - if (flags & CompiledData::RegExp::RegExp_Sticky) - result += QLatin1Char('y'); - return result; -} - -Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, uint flags) +Heap::RegExp *RegExp::create( + ExecutionEngine *engine, const QString &pattern, CompiledData::RegExp::Flags flags) { RegExpCacheKey key(pattern, flags); @@ -215,10 +212,6 @@ void Heap::RegExp::init(ExecutionEngine *engine, const QString &pattern, uint fl this->pattern = new QString(pattern); this->flags = flags; - valid = false; - jitFailed = false; - matchCount = 0; - JSC::Yarr::ErrorCode error = JSC::Yarr::ErrorCode::NoError; JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), jscFlags(flags), error); if (error != JSC::Yarr::ErrorCode::NoError) |
