diff options
| author | Lars Knoll <lars.knoll@qt.io> | 2017-09-01 16:26:51 +0200 |
|---|---|---|
| committer | Lars Knoll <lars.knoll@qt.io> | 2017-09-15 10:45:19 +0000 |
| commit | 4ca97d7289276816545ab01c9b49bfaaa29d8f5d (patch) | |
| tree | 55e88ae9444732db290d1740fbf497e2e0db9f55 /src/qml/jsruntime/qv4stringobject.cpp | |
| parent | acd206e317fd92f20aa4985f35288f793d05f3ac (diff) | |
Optimize String.match()
Change-Id: Idbf2b45a35c1bd1a843e8d01a3ea2f5157291033
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4stringobject.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 71 |
1 files changed, 30 insertions, 41 deletions
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 66ad5e79d2..2fc05e4f56 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -402,67 +402,56 @@ ReturnedValue StringPrototype::method_localeCompare(const BuiltinFunction *b, Ca ReturnedValue StringPrototype::method_match(const BuiltinFunction *b, CallData *callData) { ExecutionEngine *v4 = b->engine(); - if (callData->thisObject.isUndefined() || callData->thisObject.isNull()) + if (callData->thisObject.isNullOrUndefined()) return v4->throwTypeError(); Scope scope(v4); - ScopedString s(scope, callData->thisObject.toString(scope.engine)); - - ScopedValue regexp(scope, callData->argument(0)); - Scoped<RegExpObject> rx(scope, regexp); - if (!rx) { - JSCall jsCall(scope, scope.engine->regExpCtor(), 1); - jsCall->args[0] = regexp; - rx = jsCall.callAsConstructor(); - } + callData->thisObject = callData->thisObject.toString(scope.engine); + if (v4->hasException) + return Encode::undefined(); - if (!rx) - // ### CHECK - return v4->throwTypeError(); + if (!callData->argc) + callData->args[0] = Encode::undefined(); + callData->argc = 1; - bool global = rx->global(); + if (!callData->args[0].as<RegExpObject>()) { + // convert args[0] to a regexp + callData->args[0] = RegExpCtor::construct(b, callData); + if (v4->hasException) + return Encode::undefined(); + } - // ### use the standard builtin function, not the one that might be redefined in the proto - ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec"))); - ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString)); + bool global = static_cast<RegExpObject *>(&callData->args[0])->global(); - JSCall jsCall(scope, exec, 1); - jsCall->thisObject = rx; - jsCall->args[0] = s; + qSwap(callData->thisObject, callData->args[0]); if (!global) - return jsCall.call(); + return RegExpPrototype::method_exec(b, callData); - ScopedString lastIndex(scope, scope.engine->newString(QStringLiteral("lastIndex"))); - rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0))); + // rx is now in thisObject + RegExpObject *rx = static_cast<RegExpObject *>(&callData->thisObject); + rx->setLastIndex(0); ScopedArrayObject a(scope, scope.engine->newArrayObject()); - double previousLastIndex = 0; + int previousLastIndex = 0; uint n = 0; - ScopedValue matchStr(scope); - ScopedValue index(scope); - ScopedValue result(scope); while (1) { - result = jsCall.call(); - if (result->isNull()) + Value result = Primitive::fromReturnedValue(RegExpPrototype::execFirstMatch(b, callData)); + if (result.isNull()) break; - assert(result->isObject()); - index = rx->get(lastIndex, 0); - double thisIndex = index->toInteger(); - if (previousLastIndex == thisIndex) { - previousLastIndex = thisIndex + 1; - rx->put(lastIndex, ScopedValue(scope, Primitive::fromDouble(previousLastIndex))); + int index = rx->lastIndex(); + if (previousLastIndex == index) { + previousLastIndex = index + 1; + rx->setLastIndex(previousLastIndex); } else { - previousLastIndex = thisIndex; + previousLastIndex = index; } - matchStr = result->objectValue()->getIndexed(0); - a->arraySet(n, matchStr); + a->arraySet(n, result); ++n; } if (!n) - result = Encode::null(); + return Encode::null(); else - result = a.asReturnedValue(); - return result->asReturnedValue(); + return a.asReturnedValue(); } ReturnedValue StringPrototype::method_repeat(const BuiltinFunction *b, CallData *callData) |
