diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4regexp.cpp | 76 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexp_p.h | 2 |
2 files changed, 52 insertions, 26 deletions
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index be7ff77603..1876b29c3e 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -9,6 +9,10 @@ using namespace QV4; +#if ENABLE(YARR_JIT) +static constexpr quint8 RegexpJitThreshold = 5; +#endif + static JSC::RegExpFlags jscFlags(uint flags) { JSC::RegExpFlags jscFlags = JSC::NoFlags; @@ -40,12 +44,51 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) if (!isValid()) return JSC::Yarr::offsetNoMatch; +#if ENABLE(YARR_JIT) + auto *priv = d(); + + auto regenerateByteCode = [](Heap::RegExp *regexp) { + JSC::Yarr::ErrorCode error = JSC::Yarr::ErrorCode::NoError; + JSC::Yarr::YarrPattern yarrPattern(WTF::String(*regexp->pattern), jscFlags(regexp->flags), + error); + + // As we successfully parsed the pattern before, we should still be able to. + Q_ASSERT(error == JSC::Yarr::ErrorCode::NoError); + + regexp->byteCode = JSC::Yarr::byteCompile( + yarrPattern, + regexp->internalClass->engine->bumperPointerAllocator).release(); + }; + auto removeJitCode = [](Heap::RegExp *regexp) { + delete regexp->jitCode; + regexp->jitCode = nullptr; + regexp->jitFailed = true; + }; + if (!(priv->jitCode || priv->jitFailed)) { + if (string.length() > 1024 || priv->matchCount++ == RegexpJitThreshold) { + auto *engine = priv->internalClass->engine; + if (engine->canJIT()) { + 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 *>(engine); + JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, vm, *priv->jitCode); + } + } + if (!priv->hasValidJITCode()) + removeJitCode(priv); + } + // Note: We can't throw away the byte code as the JIT can't handle everything and + // might return offsetJITFail + } +#endif + WTF::String s(string); #if ENABLE(YARR_JIT) - static const uint offsetJITFail = std::numeric_limits<unsigned>::max() - 1; - auto *priv = d(); if (priv->hasValidJITCode()) { + static const uint offsetJITFail = std::numeric_limits<unsigned>::max() - 1; uint ret = JSC::Yarr::offsetNoMatch; #if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS) char buffer[8192]; @@ -58,19 +101,10 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) if (ret != offsetJITFail) return ret; + removeJitCode(priv); // JIT failed. We need byteCode to run the interpreter. - if (!priv->byteCode) { - JSC::Yarr::ErrorCode error = JSC::Yarr::ErrorCode::NoError; - JSC::Yarr::YarrPattern yarrPattern(WTF::String(*priv->pattern), jscFlags(priv->flags), - error); - - // As we successfully parsed the pattern before, we should still be able to. - Q_ASSERT(error == JSC::Yarr::ErrorCode::NoError); - - priv->byteCode = JSC::Yarr::byteCompile( - yarrPattern, - priv->internalClass->engine->bumperPointerAllocator).release(); - } + Q_ASSERT(!priv->byteCode); + regenerateByteCode(priv); } #endif // ENABLE(YARR_JIT) @@ -175,25 +209,15 @@ void Heap::RegExp::init(ExecutionEngine *engine, const QString &pattern, uint fl 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) return; subPatternCount = yarrPattern.m_numSubpatterns; -#if ENABLE(YARR_JIT) - if (!yarrPattern.m_containsBackreferences && engine->canJIT()) { - jitCode = new JSC::Yarr::YarrCodeBlock; - JSC::VM *vm = static_cast<JSC::VM *>(engine); - JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, vm, *jitCode); - } -#else Q_UNUSED(engine); -#endif - if (hasValidJITCode()) { - valid = true; - return; - } byteCode = JSC::Yarr::byteCompile(yarrPattern, internalClass->engine->bumperPointerAllocator).release(); if (byteCode) valid = true; diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index 1b70354caa..8a178dd2f6 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -66,6 +66,8 @@ struct RegExp : Base { int subPatternCount; uint flags; bool valid; + bool jitFailed; + quint8 matchCount; QString flagsAsString() const; int captureCount() const { return subPatternCount + 1; } |