diff options
author | Liang Qi <liang.qi@qt.io> | 2019-01-29 12:18:53 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2019-01-29 12:37:04 +0100 |
commit | 8ec2403603f82e7a0d43b4de04c97ef1c7f1ad35 (patch) | |
tree | d7099d5a7cf813f378064ef0348647f4e68b2692 /src/qml/jsruntime | |
parent | 15525d2a309a6028d548797bc777e38905f36c46 (diff) | |
parent | 454676a8745a7334539449562a5fda47db2fc2ca (diff) |
Merge remote-tracking branch 'origin/5.12' into dev
Conflicts:
src/3rdparty/masm/yarr/YarrJIT.cpp
src/qml/compiler/qv4instr_moth.cpp
src/quick/handlers/qquicksinglepointhandler_p.h
src/quick/handlers/qquicktaphandler.cpp
src/quick/items/context2d/qquickcontext2d.cpp
Done-With: Ulf Hermann <ulf.hermann@qt.io>
Change-Id: I109453131f9f0a05316ae37c7d6ed1edc8c0f9d4
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4regexp.cpp | 60 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 39 |
3 files changed, 73 insertions, 34 deletions
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 05c3b4c4ca..4ed1dbd5aa 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -45,6 +45,22 @@ using namespace QV4; +static JSC::RegExpFlags jscFlags(uint flags) +{ + JSC::RegExpFlags jscFlags = JSC::NoFlags; + if (flags & CompiledData::RegExp::RegExp_Global) + jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagGlobal); + if (flags & CompiledData::RegExp::RegExp_IgnoreCase) + jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagIgnoreCase); + if (flags & CompiledData::RegExp::RegExp_Multiline) + jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagMultiline); + if (flags & CompiledData::RegExp::RegExp_Unicode) + jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagUnicode); + if (flags & CompiledData::RegExp::RegExp_Sticky) + jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagSticky); + return jscFlags; +} + RegExpCache::~RegExpCache() { for (RegExpCache::Iterator it = begin(), e = end(); it != e; ++it) { @@ -57,21 +73,43 @@ DEFINE_MANAGED_VTABLE(RegExp); uint RegExp::match(const QString &string, int start, uint *matchOffsets) { + static const uint offsetJITFail = std::numeric_limits<unsigned>::max() - 1; + if (!isValid()) return JSC::Yarr::offsetNoMatch; WTF::String s(string); #if ENABLE(YARR_JIT) - if (d()->hasValidJITCode()) { + auto *priv = d(); + if (priv->hasValidJITCode()) { + uint ret = JSC::Yarr::offsetNoMatch; #if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS) char buffer[8192]; - return uint(jitCode()->execute(s.characters16(), start, s.length(), (int*)matchOffsets, buffer, 8192).start); + ret = uint(priv->jitCode->execute(s.characters16(), start, s.length(), + (int*)matchOffsets, buffer, 8192).start); #else - return uint(jitCode()->execute(s.characters16(), start, s.length(), (int*)matchOffsets).start); + ret = uint(priv->jitCode->execute(s.characters16(), start, s.length(), + (int*)matchOffsets).start); #endif + if (ret != offsetJITFail) + return ret; + + // 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(); + } } -#endif +#endif // ENABLE(YARR_JIT) return JSC::Yarr::interpret(byteCode(), s.characters16(), string.length(), start, matchOffsets); } @@ -176,19 +214,7 @@ void Heap::RegExp::init(ExecutionEngine *engine, const QString &pattern, uint fl valid = false; JSC::Yarr::ErrorCode error = JSC::Yarr::ErrorCode::NoError; - JSC::RegExpFlags jscFlags = JSC::NoFlags; - if (flags & CompiledData::RegExp::RegExp_Global) - jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagGlobal); - if (flags & CompiledData::RegExp::RegExp_IgnoreCase) - jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagIgnoreCase); - if (flags & CompiledData::RegExp::RegExp_Multiline) - jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagMultiline); - if (flags & CompiledData::RegExp::RegExp_Unicode) - jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagUnicode); - if (flags & CompiledData::RegExp::RegExp_Sticky) - jscFlags = static_cast<JSC::RegExpFlags>(flags | JSC::FlagSticky); - - JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), jscFlags, error); + JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), jscFlags(flags), error); if (error != JSC::Yarr::ErrorCode::NoError) return; subPatternCount = yarrPattern.m_numSubpatterns; diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 9df286065d..39a2e96b45 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -181,17 +181,19 @@ ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *s } Q_ALLOCA_VAR(uint, matchOffsets, value()->captureCount() * 2 * sizeof(uint)); - const int result = Scoped<RegExp>(scope, value())->match(s, offset, matchOffsets); + const uint result = Scoped<RegExp>(scope, value())->match(s, offset, matchOffsets); RegExpCtor *regExpCtor = static_cast<RegExpCtor *>(scope.engine->regExpCtor()); regExpCtor->d()->clearLastMatch(); - if (result == -1) { + if (result == JSC::Yarr::offsetNoMatch) { if (global() || sticky()) setLastIndex(0); RETURN_RESULT(Encode::null()); } + Q_ASSERT(result <= uint(std::numeric_limits<int>::max())); + // fill in result data ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->internalClasses(EngineBase::Class_RegExpExecArray))); int len = value()->captureCount(); @@ -207,7 +209,7 @@ ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *s array->arrayPut(i, v); } array->setArrayLengthUnchecked(len); - array->setProperty(Index_ArrayIndex, Value::fromInt32(result)); + array->setProperty(Index_ArrayIndex, Value::fromInt32(int(result))); array->setProperty(Index_ArrayInput, *str); RegExpCtor::Data *dd = regExpCtor->d(); diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index d0f6aff9d9..8186153ba4 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -722,41 +722,52 @@ static void appendReplacementString(QString *result, const QString &input, const result->reserve(result->length() + replaceValue.length()); for (int i = 0; i < replaceValue.length(); ++i) { if (replaceValue.at(i) == QLatin1Char('$') && i < replaceValue.length() - 1) { - ushort ch = replaceValue.at(++i).unicode(); + ushort ch = replaceValue.at(i + 1).unicode(); uint substStart = JSC::Yarr::offsetNoMatch; uint substEnd = JSC::Yarr::offsetNoMatch; + int skip = 0; if (ch == '$') { *result += QChar(ch); + ++i; continue; } else if (ch == '&') { substStart = matchOffsets[0]; substEnd = matchOffsets[1]; + skip = 1; } else if (ch == '`') { substStart = 0; substEnd = matchOffsets[0]; + skip = 1; } else if (ch == '\'') { substStart = matchOffsets[1]; substEnd = input.length(); - } else if (ch >= '1' && ch <= '9') { + skip = 1; + } else if (ch >= '0' && ch <= '9') { uint capture = ch - '0'; - Q_ASSERT(capture > 0); - if (capture < static_cast<uint>(captureCount)) { + skip = 1; + if (i < replaceValue.length() - 2) { + ch = replaceValue.at(i + 2).unicode(); + if (ch >= '0' && ch <= '9') { + uint c = capture*10 + ch - '0'; + if (c < static_cast<uint>(captureCount)) { + capture = c; + skip = 2; + } + } + } + if (capture > 0 && capture < static_cast<uint>(captureCount)) { substStart = matchOffsets[capture * 2]; substEnd = matchOffsets[capture * 2 + 1]; - } - } else if (ch == '0' && i < replaceValue.length() - 1) { - int capture = (ch - '0') * 10; - ch = replaceValue.at(++i).unicode(); - if (ch >= '0' && ch <= '9') { - capture += ch - '0'; - if (capture > 0 && capture < captureCount) { - substStart = matchOffsets[capture * 2]; - substEnd = matchOffsets[capture * 2 + 1]; - } + } else { + skip = 0; } } + i += skip; if (substStart != JSC::Yarr::offsetNoMatch && substEnd != JSC::Yarr::offsetNoMatch) *result += input.midRef(substStart, substEnd - substStart); + else { + *result += replaceValue.at(i); + } } else { *result += replaceValue.at(i); } |