diff options
author | Lars Knoll <[email protected]> | 2014-04-06 12:51:56 +0200 |
---|---|---|
committer | Simon Hausmann <[email protected]> | 2014-07-22 13:48:56 +0200 |
commit | 3f39bc03f1fc3ba26eab7b1b0828d3cfa93abb2b (patch) | |
tree | 1a7a210d6e3430189b58d693e32a6c4b392d8a4a | |
parent | 36aa3f91177f41644422e07c338a26e688f5096c (diff) |
Convert RegExp and RegExpObject to new data layout
Change-Id: I0c2bbab4b158069d5c1648edc38f7c5e38ee67ee
Reviewed-by: Simon Hausmann <[email protected]>
-rw-r--r-- | src/qml/jsruntime/qv4regexp.cpp | 30 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexp_p.h | 42 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject.cpp | 98 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject_p.h | 28 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 22 |
5 files changed, 123 insertions, 97 deletions
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 23ef62f992..eb7810c1b0 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -49,7 +49,7 @@ RegExpCache::~RegExpCache() { for (RegExpCache::Iterator it = begin(), e = end(); it != e; ++it) - it.value()->m_cache = 0; + it.value()->data.cache = 0; clear(); } @@ -63,11 +63,11 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) WTF::String s(string); #if ENABLE(YARR_JIT) - if (!m_jitCode.isFallBack() && m_jitCode.has16BitCode()) - return m_jitCode.execute(s.characters16(), start, s.length(), (int*)matchOffsets).start; + if (!jitCode().isFallBack() && jitCode().has16BitCode()) + return jitCode().execute(s.characters16(), start, s.length(), (int*)matchOffsets).start; #endif - return JSC::Yarr::interpret(m_byteCode.get(), s.characters16(), string.length(), start, matchOffsets); + return JSC::Yarr::interpret(byteCode().get(), s.characters16(), string.length(), start, matchOffsets); } RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline) @@ -85,7 +85,7 @@ RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ign if (!cache) cache = engine->regExpCache = new RegExpCache; - result->m_cache = cache; + result->data.cache = cache; cache->insert(key, result); return result; @@ -93,33 +93,33 @@ RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ign RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) : Managed(engine->regExpValueClass) - , m_pattern(pattern) - , m_cache(0) - , m_subPatternCount(0) - , m_ignoreCase(ignoreCase) - , m_multiLine(multiline) { + data.pattern = pattern; + data.cache = 0; + data.ignoreCase = ignoreCase; + data.multiLine = multiline; + if (!engine) return; const char* error = 0; JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error); if (error) return; - m_subPatternCount = yarrPattern.m_numSubpatterns; - m_byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); + data.subPatternCount = yarrPattern.m_numSubpatterns; + data.byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); #if ENABLE(YARR_JIT) if (!yarrPattern.m_containsBackreferences && engine->iselFactory->jitCompileRegexps()) { JSC::JSGlobalData dummy(engine->regExpAllocator); - JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, m_jitCode); + JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, data.jitCode); } #endif } RegExp::~RegExp() { - if (m_cache) { + if (cache()) { RegExpCacheKey key(this); - m_cache->remove(key); + cache()->remove(key); } } diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index 63d4ed3ed2..270fe9aa2d 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -95,19 +95,38 @@ class RegExp : public Managed { V4_MANAGED Q_MANAGED_TYPE(RegExp) -public: + + struct Data { + QString pattern; + OwnPtr<JSC::Yarr::BytecodePattern> byteCode; +#if ENABLE(YARR_JIT) + JSC::Yarr::YarrCodeBlock jitCode; +#endif + RegExpCache *cache; + int subPatternCount; + bool ignoreCase; + bool multiLine; + }; + Data data; + + QString pattern() const { return data.pattern; } + OwnPtr<JSC::Yarr::BytecodePattern> &byteCode() { return data.byteCode; } +#if ENABLE(YARR_JIT) + JSC::Yarr::YarrCodeBlock jitCode() const { return data.jitCode; } +#endif + RegExpCache *cache() const { return data.cache; } + int subPatternCount() const { return data.subPatternCount; } + bool ignoreCase() const { return data.ignoreCase; } + bool multiLine() const { return data.multiLine; } + static RegExp* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false); ~RegExp(); - QString pattern() const { return m_pattern; } - - bool isValid() const { return m_byteCode.get(); } + bool isValid() const { return data.byteCode.get(); } uint match(const QString& string, int start, uint *matchOffsets); - bool ignoreCase() const { return m_ignoreCase; } - bool multiLine() const { return m_multiLine; } - int captureCount() const { return m_subPatternCount + 1; } + int captureCount() const { return subPatternCount() + 1; } static void destroy(Managed *that); static void markObjects(Managed *that, QV4::ExecutionEngine *e); @@ -117,15 +136,6 @@ private: Q_DISABLE_COPY(RegExp); RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); - const QString m_pattern; - OwnPtr<JSC::Yarr::BytecodePattern> m_byteCode; -#if ENABLE(YARR_JIT) - JSC::Yarr::YarrCodeBlock m_jitCode; -#endif - RegExpCache *m_cache; - int m_subPatternCount; - const bool m_ignoreCase; - const bool m_multiLine; }; inline RegExpCacheKey::RegExpCacheKey(const RegExp *re) diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 6187cf9f16..b9e4c37e26 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -73,18 +73,18 @@ DEFINE_OBJECT_VTABLE(RegExpObject); RegExpObject::RegExpObject(InternalClass *ic) : Object(ic) - , value(RegExp::create(ic->engine, QString(), false, false)) - , global(false) { + data.value = RegExp::create(ic->engine, QString(), false, false); + data.global = false; Q_ASSERT(internalClass()->vtable == staticVTable()); init(ic->engine); } RegExpObject::RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global) : Object(engine->regExpClass) - , value(value) - , global(global) { + data.value = value; + data.global = global; init(engine); } @@ -93,9 +93,10 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global // have different semantics/flags, but we try to do our best. RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re) : Object(engine->regExpClass) - , value(0) - , global(false) { + data.value = 0; + data.global = false; + // Convert the pattern to a ECMAScript pattern. QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax()); if (re.isMinimal()) { @@ -136,7 +137,7 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re) Scope scope(engine); ScopedObject protectThis(scope, this); - value = RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false); + data.value = RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false); init(engine); } @@ -151,10 +152,10 @@ void RegExpObject::init(ExecutionEngine *engine) ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex"))); ScopedValue v(scope, Primitive::fromInt32(0)); insertMember(lastIndex, v, Attr_NotEnumerable|Attr_NotConfigurable); - if (!this->value) + if (!this->value()) return; - QString p = this->value->pattern(); + QString p = this->value()->pattern(); if (p.isEmpty()) { p = QStringLiteral("(?:)"); } else { @@ -163,17 +164,17 @@ void RegExpObject::init(ExecutionEngine *engine) } defineReadonlyProperty(QStringLiteral("source"), (v = engine->newString(p))); - defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global)); - defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value->ignoreCase())); - defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value->multiLine())); + defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global())); + defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value()->ignoreCase())); + defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value()->multiLine())); } void RegExpObject::markObjects(Managed *that, ExecutionEngine *e) { RegExpObject *re = static_cast<RegExpObject*>(that); - if (re->value) - re->value->mark(e); + if (re->value()) + re->value()->mark(e); Object::markObjects(that, e); } @@ -189,19 +190,19 @@ Property *RegExpObject::lastIndexProperty(ExecutionContext *ctx) // have different semantics/flags, but we try to do our best. QRegExp RegExpObject::toQRegExp() const { - Qt::CaseSensitivity caseSensitivity = value->ignoreCase() ? Qt::CaseInsensitive : Qt::CaseSensitive; - return QRegExp(value->pattern(), caseSensitivity, QRegExp::RegExp2); + Qt::CaseSensitivity caseSensitivity = value()->ignoreCase() ? Qt::CaseInsensitive : Qt::CaseSensitive; + return QRegExp(value()->pattern(), caseSensitivity, QRegExp::RegExp2); } QString RegExpObject::toString() const { QString result = QLatin1Char('/') + source(); result += QLatin1Char('/'); - if (global) + if (global()) result += QLatin1Char('g'); - if (value->ignoreCase()) + if (value()->ignoreCase()) result += QLatin1Char('i'); - if (value->multiLine()) + if (value()->multiLine()) result += QLatin1Char('m'); return result; } @@ -217,11 +218,11 @@ QString RegExpObject::source() const uint RegExpObject::flags() const { uint f = 0; - if (global) + if (global()) f |= QV4::RegExpObject::RegExp_Global; - if (value->ignoreCase()) + if (value()->ignoreCase()) f |= QV4::RegExpObject::RegExp_IgnoreCase; - if (value->multiLine()) + if (value()->multiLine()) f |= QV4::RegExpObject::RegExp_Multiline; return f; } @@ -237,10 +238,10 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope) void RegExpCtor::clearLastMatch() { - lastMatch = Primitive::nullValue(); - lastInput = engine()->id_empty; - lastMatchStart = 0; - lastMatchEnd = 0; + data.lastMatch = Primitive::nullValue(); + data.lastInput = engine()->id_empty; + data.lastMatchStart = 0; + data.lastMatchEnd = 0; } ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) @@ -255,8 +256,8 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) if (!f->isUndefined()) return ctx->throwTypeError(); - Scoped<RegExp> newRe(scope, re->value); - return Encode(ctx->engine->newRegExpObject(newRe, re->global)); + Scoped<RegExp> newRe(scope, re->value()); + return Encode(ctx->engine->newRegExpObject(newRe, re->global())); } QString pattern; @@ -306,8 +307,8 @@ ReturnedValue RegExpCtor::call(Managed *that, CallData *callData) void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e) { RegExpCtor *This = static_cast<RegExpCtor*>(that); - This->lastMatch.mark(e); - This->lastInput.mark(e); + This->lastMatch().mark(e); + This->lastInput().mark(e); FunctionObject::markObjects(that, e); } @@ -360,14 +361,14 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) return Encode::undefined(); QString s = arg->stringValue()->toQString(); - int offset = r->global ? r->lastIndexProperty(ctx)->value.toInt32() : 0; + int offset = r->global() ? r->lastIndexProperty(ctx)->value.toInt32() : 0; if (offset < 0 || offset > s.length()) { r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0); return Encode::null(); } - uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint)); - const int result = r->value->match(s, offset, matchOffsets); + uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint)); + const int result = r->value()->match(s, offset, matchOffsets); Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); regExpCtor->clearLastMatch(); @@ -379,7 +380,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) // fill in result data Scoped<ArrayObject> array(scope, ctx->engine->newArrayObject(ctx->engine->regExpExecArrayClass)); - int len = r->value->captureCount(); + int len = r->value()->captureCount(); array->arrayReserve(len); ScopedValue v(scope); for (int i = 0; i < len; ++i) { @@ -392,12 +393,13 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) array->memberData()[Index_ArrayIndex] = Primitive::fromInt32(result); array->memberData()[Index_ArrayInput] = arg.asReturnedValue(); - regExpCtor->lastMatch = array; - regExpCtor->lastInput = arg->stringValue(); - regExpCtor->lastMatchStart = matchOffsets[0]; - regExpCtor->lastMatchEnd = matchOffsets[1]; + RegExpCtor::Data *d = ®ExpCtor->data; + d->lastMatch = array; + d->lastInput = arg->stringValue(); + d->lastMatchStart = matchOffsets[0]; + d->lastMatchEnd = matchOffsets[1]; - if (r->global) + if (r->global()) r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]); return array.asReturnedValue(); @@ -432,8 +434,8 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx) Scoped<RegExpObject> re(scope, ctx->engine->regExpCtor.asFunctionObject()->construct(callData)); - r->value = re->value; - r->global = re->global; + r->data.value = re->value(); + r->data.global = re->global(); return Encode::undefined(); } @@ -441,7 +443,7 @@ template <int index> ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx) { Scope scope(ctx); - ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch); + ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch()); ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined()); if (result->isUndefined()) return ctx->engine->newString(QString())->asReturnedValue(); @@ -451,7 +453,7 @@ ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx) ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx) { Scope scope(ctx); - ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch); + ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch()); ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined()); if (result->isUndefined()) return ctx->engine->newString(QString())->asReturnedValue(); @@ -460,23 +462,23 @@ ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx) ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx) { - return static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastInput.asReturnedValue(); + return static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastInput().asReturnedValue(); } ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx) { Scope scope(ctx); Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); - QString lastInput = regExpCtor->lastInput->toQString(); - return ctx->engine->newString(lastInput.left(regExpCtor->lastMatchStart))->asReturnedValue(); + QString lastInput = regExpCtor->lastInput()->toQString(); + return ctx->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue(); } ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx) { Scope scope(ctx); Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); - QString lastInput = regExpCtor->lastInput->toQString(); - return ctx->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd))->asReturnedValue(); + QString lastInput = regExpCtor->lastInput()->toQString(); + return ctx->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue(); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index 0c22d50216..909628cd72 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -80,15 +80,21 @@ struct RegExpObject: Object { Index_ArrayInput = Index_ArrayIndex + 1 }; - RegExp* value; - Property *lastIndexProperty(ExecutionContext *ctx); - bool global; + struct Data { + RegExp* value; + bool global; + }; + Data data; + + RegExp* value() const { return data.value; } + bool global() const { return data.global; } RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global); RegExpObject(ExecutionEngine *engine, const QRegExp &re); void init(ExecutionEngine *engine); + Property *lastIndexProperty(ExecutionContext *ctx); QRegExp toQRegExp() const; QString toString() const; QString source() const; @@ -106,10 +112,18 @@ struct RegExpCtor: FunctionObject V4_OBJECT RegExpCtor(ExecutionContext *scope); - Value lastMatch; - StringValue lastInput; - int lastMatchStart; - int lastMatchEnd; + struct Data { + Value lastMatch; + StringValue lastInput; + int lastMatchStart; + int lastMatchEnd; + }; + Data data; + + Value lastMatch() { return data.lastMatch; } + StringValue lastInput() { return data.lastInput; } + int lastMatchStart() { return data.lastMatchStart; } + int lastMatchEnd() { return data.lastMatchEnd; } void clearLastMatch(); static ReturnedValue construct(Managed *m, CallData *callData); diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 6ad4e8b11e..2ed5bcf642 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -396,7 +396,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context) // ### CHECK return context->throwTypeError(); - bool global = rx->global; + bool global = rx->global(); // ### use the standard builtin function, not the one that might be redefined in the proto ScopedString execString(scope, context->engine->newString(QStringLiteral("exec"))); @@ -510,7 +510,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) uint offset = 0; // We extract the pointer here to work around a compiler bug on Android. - Scoped<RegExp> re(scope, regExp->value); + Scoped<RegExp> re(scope, regExp->value()); while (true) { int oldSize = nMatchOffsets; if (allocatedMatchOffsets < nMatchOffsets + re->captureCount() * 2) { @@ -530,10 +530,10 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) break; offset = qMax(offset + 1, matchOffsets[oldSize + 1]); } - if (regExp->global) + if (regExp->global()) regExp->lastIndexProperty(ctx)->value = Primitive::fromUInt32(0); - numStringMatches = nMatchOffsets / (regExp->value->captureCount() * 2); - numCaptures = regExp->value->captureCount(); + numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2); + numCaptures = regExp->value()->captureCount(); } else { numCaptures = 1; QString searchString = searchValue->toString(ctx)->toQString(); @@ -620,8 +620,8 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx) regExp = regExpValue->as<RegExpObject>(); Q_ASSERT(regExp); } - uint* matchOffsets = (uint*)alloca(regExp->value->captureCount() * 2 * sizeof(uint)); - uint result = regExp->value->match(string, /*offset*/0, matchOffsets); + uint* matchOffsets = (uint*)alloca(regExp->value()->captureCount() * 2 * sizeof(uint)); + uint result = regExp->value()->match(string, /*offset*/0, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) return Encode(-1); return Encode(result); @@ -684,7 +684,7 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) Scoped<RegExpObject> re(scope, separatorValue); if (re) { - if (re->value->pattern().isEmpty()) { + if (re->value()->pattern().isEmpty()) { re = (RegExpObject *)0; separatorValue = ctx->engine->newString(QString()); } @@ -693,9 +693,9 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) ScopedString s(scope); if (re) { uint offset = 0; - uint* matchOffsets = (uint*)alloca(re->value->captureCount() * 2 * sizeof(uint)); + uint* matchOffsets = (uint*)alloca(re->value()->captureCount() * 2 * sizeof(uint)); while (true) { - uint result = re->value->match(text, offset, matchOffsets); + uint result = re->value()->match(text, offset, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) break; @@ -705,7 +705,7 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) if (array->getLength() >= limit) break; - for (int i = 1; i < re->value->captureCount(); ++i) { + for (int i = 1; i < re->value()->captureCount(); ++i) { uint start = matchOffsets[i * 2]; uint end = matchOffsets[i * 2 + 1]; array->push_back((s = ctx->engine->newString(text.mid(start, end - start)))); |