diff options
author | Lars Knoll <lars.knoll@digia.com> | 2014-05-08 22:27:23 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2014-07-22 13:49:17 +0200 |
commit | 45f7120d42f628e86ae2bf3bd2789fdb190490e0 (patch) | |
tree | 5a90ec2c80f46d20124cf4adac14704777301f46 /src/qml/jsruntime | |
parent | 4632c0bfff911fa84f00aab9721519427cfa9921 (diff) |
Convert regexps
Change-Id: I5b62a265a7ce363a16b1e14ae93cadbb1ab0cb5b
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexp.cpp | 39 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexp_p.h | 75 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject.cpp | 56 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject_p.h | 24 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 28 |
11 files changed, 140 insertions, 114 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 2f64ce48bc..84c522e75c 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -302,8 +302,8 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) protoClass = objectClass->addMember(id_constructor, Attr_NotEnumerable, &index); Q_ASSERT(index == FunctionObject::Index_ProtoConstructor); - RegExpPrototype *regExpPrototype = new (memoryManager) RegExpPrototype(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype)); - regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype); + Scoped<RegExpPrototype> regExpPrototype(scope, new (this) RegExpPrototype::Data(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype))); + regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype.getPointer()); regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index); Q_ASSERT(index == RegExpObject::Index_ArrayIndex); regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index); @@ -592,13 +592,15 @@ Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern, Returned<RegExpObject> *ExecutionEngine::newRegExpObject(RegExp *re, bool global) { - RegExpObject *object = new (memoryManager) RegExpObject(this, re, global); + Scope scope(this); + Scoped<RegExpObject> object(scope, new (this) RegExpObject::Data(this, re, global)); return object->asReturned<RegExpObject>(); } Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QRegExp &re) { - RegExpObject *object = new (memoryManager) RegExpObject(this, re); + Scope scope(this); + Scoped<RegExpObject> object(scope, new (this) RegExpObject::Data(this, re)); return object->asReturned<RegExpObject>(); } diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 8d8527e3da..12434dbbcc 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -112,7 +112,7 @@ struct IdentifierTable; struct InternalClass; struct InternalClassPool; class MultiplyWrappedQObjectMap; -class RegExp; +struct RegExp; class RegExpCache; struct QmlExtensions; struct Exception; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 791ff0f3b3..38b2dcbb9e 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -169,6 +169,7 @@ void FunctionObject::init(String *n, bool createProto) d()->needsActivation = true; d()->strictMode = false; + memberData().ensureIndex(s.engine, Index_Prototype); if (createProto) { Scoped<Object> proto(s, scope()->d()->engine->newObject(scope()->d()->engine->protoClass)); proto->memberData()[Index_ProtoConstructor] = this->asReturnedValue(); @@ -178,7 +179,7 @@ void FunctionObject::init(String *n, bool createProto) } ScopedValue v(s, n); - defineReadonlyProperty(scope()->d()->engine->id_name, v); + defineReadonlyProperty(s.engine->id_name, v); } ReturnedValue FunctionObject::name() diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 9abfb252ce..235519b72b 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -90,7 +90,6 @@ Object::Object(InternalClass *ic) { Q_ASSERT(internalClass()->vtable != &Managed::static_vtbl); - Q_ASSERT(!memberData().d()); if (internalClass()->size) { Scope scope(engine()); ScopedObject protectThis(scope, this); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 4ba27ccece..b98c77108e 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -125,7 +125,7 @@ struct Q_QML_EXPORT Object: Managed { }; Members &memberData() { return d()->memberData; } - Members memberData() const { return d()->memberData; } + const Members &memberData() const { return d()->memberData; } const ArrayData *arrayData() const { return d()->arrayData; } ArrayData *arrayData() { return d()->arrayData; } void setArrayData(ArrayData *a) { d()->arrayData = a; } diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 1207500ad7..08025e07cf 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()->d()->cache = 0; + it.value()->cache = 0; clear(); } @@ -70,62 +70,59 @@ uint RegExp::match(const QString &string, int start, uint *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) +RegExp::Data* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline) { RegExpCacheKey key(pattern, ignoreCase, multiline); RegExpCache *cache = engine->regExpCache; if (cache) { - if (RegExp *result = cache->value(key)) + if (RegExp::Data *result = cache->value(key)) return result; } - RegExp *result = new (engine->memoryManager) RegExp(engine, pattern, ignoreCase, multiline); + RegExp::Data *result = new (engine) RegExp::Data(engine, pattern, ignoreCase, multiline); if (!cache) cache = engine->regExpCache = new RegExpCache; - result->d()->cache = cache; + result->cache = cache; cache->insert(key, result); return result; } -RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) - : Managed(engine->regExpValueClass) +RegExp::Data::Data(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) + : Managed::Data(engine->regExpValueClass) + , pattern(pattern) + , ignoreCase(ignoreCase) + , multiLine(multiline) { - d()->pattern = pattern; - d()->cache = 0; - d()->ignoreCase = ignoreCase; - d()->multiLine = multiline; - - if (!engine) - return; + setVTable(staticVTable()); const char* error = 0; JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error); if (error) return; - d()->subPatternCount = yarrPattern.m_numSubpatterns; - d()->byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); + subPatternCount = yarrPattern.m_numSubpatterns; + 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, d()->jitCode); + JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, jitCode); } #endif } -RegExp::~RegExp() +RegExp::Data::~Data() { - if (cache()) { + if (cache) { RegExpCacheKey key(this); - cache()->remove(key); + cache->remove(key); } } void RegExp::destroy(Managed *that) { - static_cast<RegExp*>(that)->~RegExp(); + static_cast<RegExp*>(that)->d()->~Data(); } void RegExp::markObjects(Managed *that, ExecutionEngine *e) diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index 983fd03351..29f759f93c 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -62,38 +62,13 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct ExecutionEngine; +struct RegExpCacheKey; -struct RegExpCacheKey -{ - RegExpCacheKey(const QString &pattern, bool ignoreCase, bool multiLine) - : pattern(pattern) - , ignoreCase(ignoreCase) - , multiLine(multiLine) - { } - explicit inline RegExpCacheKey(const RegExp *re); - - bool operator==(const RegExpCacheKey &other) const - { return pattern == other.pattern && ignoreCase == other.ignoreCase && multiLine == other.multiLine; } - bool operator!=(const RegExpCacheKey &other) const - { return !operator==(other); } - - QString pattern; - uint ignoreCase : 1; - uint multiLine : 1; -}; - -inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW -{ return qHash(key.pattern, seed); } - -class RegExpCache : public QHash<RegExpCacheKey, RegExp*> -{ -public: - ~RegExpCache(); -}; - -class RegExp : public Managed +struct RegExp : public Managed { struct Data : Managed::Data { + Data(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); + ~Data(); QString pattern; OwnPtr<JSC::Yarr::BytecodePattern> byteCode; #if ENABLE(YARR_JIT) @@ -129,8 +104,7 @@ class RegExp : public Managed bool ignoreCase() const { return d()->ignoreCase; } bool multiLine() const { return d()->multiLine; } - static RegExp* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false); - ~RegExp(); + static RegExp::Data* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false); bool isValid() const { return d()->byteCode.get(); } @@ -141,19 +115,44 @@ class RegExp : public Managed static void destroy(Managed *that); static void markObjects(Managed *that, QV4::ExecutionEngine *e); -private: friend class RegExpCache; - Q_DISABLE_COPY(RegExp); - RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); +}; + +struct RegExpCacheKey +{ + RegExpCacheKey(const QString &pattern, bool ignoreCase, bool multiLine) + : pattern(pattern) + , ignoreCase(ignoreCase) + , multiLine(multiLine) + { } + explicit inline RegExpCacheKey(const RegExp::Data *re); + + bool operator==(const RegExpCacheKey &other) const + { return pattern == other.pattern && ignoreCase == other.ignoreCase && multiLine == other.multiLine; } + bool operator!=(const RegExpCacheKey &other) const + { return !operator==(other); } + QString pattern; + uint ignoreCase : 1; + uint multiLine : 1; }; -inline RegExpCacheKey::RegExpCacheKey(const RegExp *re) - : pattern(re->pattern()) - , ignoreCase(re->ignoreCase()) - , multiLine(re->multiLine()) +inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re) + : pattern(re->pattern) + , ignoreCase(re->ignoreCase) + , multiLine(re->multiLine) {} +inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW +{ return qHash(key.pattern, seed); } + +class RegExpCache : public QHash<RegExpCacheKey, RegExp::Data *> +{ +public: + ~RegExpCache(); +}; + + } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 2406fa223d..f7135d9608 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -70,32 +70,42 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyn using namespace QV4; DEFINE_OBJECT_VTABLE(RegExpObject); +DEFINE_OBJECT_VTABLE(RegExpPrototype); -RegExpObject::RegExpObject(InternalClass *ic) - : Object(ic) +RegExpObject::Data::Data(InternalClass *ic) + : Object::Data(ic) { - d()->value = RegExp::create(ic->engine, QString(), false, false); - d()->global = false; - Q_ASSERT(internalClass()->vtable == staticVTable()); - init(ic->engine); + setVTable(staticVTable()); + + Scope scope(ic->engine); + Scoped<RegExpObject> o(scope, this); + o->d()->value = reinterpret_cast<RegExp *>(RegExp::create(ic->engine, QString(), false, false)); + o->d()->global = false; + o->init(ic->engine); } -RegExpObject::RegExpObject(ExecutionEngine *engine, RegExp *value, bool global) - : Object(engine->regExpClass) +RegExpObject::Data::Data(ExecutionEngine *engine, RegExp *value, bool global) + : Object::Data(engine->regExpClass) + , value(value) + , global(global) { - d()->value = value; - d()->global = global; - init(engine); + setVTable(staticVTable()); + + Scope scope(engine); + Scoped<RegExpObject> o(scope, this); + o->init(engine); } // Converts a QRegExp to a JS RegExp. // The conversion is not 100% exact since ECMA regexp and QRegExp // have different semantics/flags, but we try to do our best. -RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re) - : Object(engine->regExpClass) +RegExpObject::Data::Data(ExecutionEngine *engine, const QRegExp &re) + : Object::Data(engine->regExpClass) { - d()->value = 0; - d()->global = false; + setVTable(staticVTable()); + + value = 0; + global = false; // Convert the pattern to a ECMAScript pattern. QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax()); @@ -135,17 +145,15 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re) } Scope scope(engine); - ScopedObject protectThis(scope, this); + Scoped<RegExpObject> o(scope, this); - d()->value = RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false); + o->d()->value = reinterpret_cast<RegExp *>(RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false)); - init(engine); + o->init(engine); } void RegExpObject::init(ExecutionEngine *engine) { - setVTable(staticVTable()); - Scope scope(engine); ScopedObject protectThis(scope, this); @@ -256,8 +264,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) if (!f->isUndefined()) return ctx->throwTypeError(); - Scoped<RegExp> newRe(scope, re->value()); - return Encode(ctx->d()->engine->newRegExpObject(newRe, re->global())); + return Encode(ctx->d()->engine->newRegExpObject(re->value(), re->global())); } QString pattern; @@ -287,7 +294,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) } } - Scoped<RegExp> regexp(scope, RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine)); + RegExp *regexp = reinterpret_cast<RegExp *>(RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine)); if (!regexp->isValid()) return ctx->throwSyntaxError(QStringLiteral("Invalid regular expression")); @@ -312,10 +319,11 @@ void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e) FunctionObject::markObjects(that, e); } -void RegExpPrototype::init(ExecutionEngine *engine, Object *ctor) +void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor) { Scope scope(engine); ScopedObject o(scope); + ScopedObject ctor(scope, constructor); ctor->defineReadonlyProperty(engine->id_prototype, (o = this)); ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2)); diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index f6d2f66f6a..90ff8caf7d 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -63,15 +63,17 @@ QT_BEGIN_NAMESPACE namespace QV4 { -class RegExp; - struct RegExpObject: Object { struct Data : Object::Data { - RegExp* value; + Data(ExecutionEngine *engine, RegExp *value, bool global); + Data(ExecutionEngine *engine, const QRegExp &re); + Data(InternalClass *ic); + + RegExp *value; bool global; }; struct { - RegExp* value; + RegExp *value; bool global; } __data; @@ -93,9 +95,6 @@ struct RegExpObject: Object { RegExp *value() const { return d()->value; } bool global() const { return d()->global; } - RegExpObject(ExecutionEngine *engine, RegExp *value, bool global); - RegExpObject(ExecutionEngine *engine, const QRegExp &re); - void init(ExecutionEngine *engine); Property *lastIndexProperty(ExecutionContext *ctx); @@ -105,7 +104,6 @@ struct RegExpObject: Object { uint flags() const; protected: - RegExpObject(InternalClass *ic); static void markObjects(Managed *that, ExecutionEngine *e); }; @@ -140,7 +138,15 @@ struct RegExpCtor: FunctionObject struct RegExpPrototype: RegExpObject { - RegExpPrototype(InternalClass *ic): RegExpObject(ic) {} + struct Data : RegExpObject::Data + { + Data(InternalClass *ic): RegExpObject::Data(ic) + { + setVTable(staticVTable()); + } + }; + V4_OBJECT + void init(ExecutionEngine *engine, Object *ctor); static ReturnedValue method_exec(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 5a7852f49b..6045ea5794 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -117,6 +117,15 @@ struct ScopedValue #endif } + ScopedValue(const Scope &scope, HeapObject *o) + { + ptr = scope.engine->jsStackTop++; + ptr->m = reinterpret_cast<Managed *>(o); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + ScopedValue(const Scope &scope, Managed *m) { ptr = scope.engine->jsStackTop++; @@ -150,6 +159,11 @@ struct ScopedValue return *this; } + ScopedValue &operator=(HeapObject *o) { + ptr->m = reinterpret_cast<Managed *>(o); + return *this; + } + ScopedValue &operator=(Managed *m) { ptr->val = m->asReturnedValue(); return *this; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 635115ff0a..c397922c40 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -167,6 +167,17 @@ DEFINE_OBJECT_VTABLE(QmlBindingWrapper); struct CompilationUnitHolder : public Object { struct Data : Object::Data { + Data(ExecutionEngine *engine, CompiledData::CompilationUnit *unit) + : Object::Data(engine) + , unit(unit) + { + unit->ref(); + setVTable(staticVTable()); + } + ~Data() + { + unit->deref(); + } QV4::CompiledData::CompilationUnit *unit; }; struct { @@ -175,21 +186,10 @@ struct CompilationUnitHolder : public Object V4_OBJECT - CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit) - : Object(engine) - { - d()->unit = unit; - d()->unit->ref(); - setVTable(staticVTable()); - } - ~CompilationUnitHolder() - { - d()->unit->deref(); - } static void destroy(Managed *that) { - static_cast<CompilationUnitHolder*>(that)->~CompilationUnitHolder(); + static_cast<CompilationUnitHolder*>(that)->d()->~Data(); } }; @@ -206,7 +206,7 @@ Script::Script(ExecutionEngine *v4, Object *qml, CompiledData::CompilationUnit * vmFunction = compilationUnit->linkToEngine(v4); Q_ASSERT(vmFunction); Scope valueScope(v4); - ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)); + ScopedObject holder(valueScope, new (v4) CompilationUnitHolder::Data(v4, compilationUnit)); compilationUnitHolder = holder.asReturnedValue(); } else vmFunction = 0; @@ -278,7 +278,7 @@ void Script::parse() isel->setUseFastLookups(false); QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); vmFunction = compilationUnit->linkToEngine(v4); - ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)); + ScopedObject holder(valueScope, new (v4) CompilationUnitHolder::Data(v4, compilationUnit)); compilationUnitHolder = holder.asReturnedValue(); } |