From c6b2dd879d02b21b18f80faab541f8f04286685a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 23 Jun 2017 13:36:13 +0200 Subject: Move property cache from the engine to QQmlType Now that the property cache is independent of a specific engine, we can cache them in QQmlType instead of caching them per engine. This simplifies the logic and avoids duplicated property caches when multiple engines are running. Task-number: QTBUG-61536 Change-Id: I6f082e1e7495ae0f5b92559e8d0a3437c56e303a Reviewed-by: Lars Knoll --- src/qml/jsapi/qjsengine.cpp | 19 +------------------ src/qml/jsapi/qjsengine_p.h | 17 +++-------------- src/qml/qml/qqmlmetatype.cpp | 29 +++++++++++++++++++++++++++++ src/qml/qml/qqmlmetatype_p.h | 3 +++ src/qml/qml/qqmlpropertycache_p.h | 2 ++ 5 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index 17f3fcedae..35b4929c3a 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -730,10 +730,7 @@ QJSEnginePrivate *QJSEnginePrivate::get(QV4::ExecutionEngine *e) QJSEnginePrivate::~QJSEnginePrivate() { - typedef QHash::Iterator PropertyCacheIt; - - for (PropertyCacheIt iter = propertyCache.begin(), end = propertyCache.end(); iter != end; ++iter) - (*iter)->release(); + // ### FIXME: sweep unused QQmlType instances } void QJSEnginePrivate::addToDebugServer(QJSEngine *q) @@ -756,20 +753,6 @@ void QJSEnginePrivate::removeFromDebugServer(QJSEngine *q) server->removeEngine(q); } -QQmlPropertyCache *QJSEnginePrivate::createCache(const QMetaObject *mo) -{ - if (!mo->superClass()) { - QQmlPropertyCache *rv = new QQmlPropertyCache(mo); - propertyCache.insert(mo, rv); - return rv; - } else { - QQmlPropertyCache *super = cache(mo->superClass()); - QQmlPropertyCache *rv = super->copyAndAppend(mo); - propertyCache.insert(mo, rv); - return rv; - } -} - /*! \since 5.5 \relates QJSEngine diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h index 2b462451ed..cbfe0f14a3 100644 --- a/src/qml/jsapi/qjsengine_p.h +++ b/src/qml/jsapi/qjsengine_p.h @@ -55,6 +55,7 @@ #include #include "qjsengine.h" #include "private/qtqmlglobal_p.h" +#include QT_BEGIN_NAMESPACE @@ -110,14 +111,6 @@ public: // These methods may be called from the QML loader thread inline QQmlPropertyCache *cache(QObject *obj); inline QQmlPropertyCache *cache(const QMetaObject *); - -private: - // Must be called locked - QQmlPropertyCache *createCache(const QMetaObject *); - - // These members must be protected by a QJSEnginePrivate::Locker as they are required by - // the threaded loader. Only access them through their respective accessor methods. - QHash propertyCache; }; QJSEnginePrivate::Locker::Locker(const QJSEngine *e) @@ -174,9 +167,7 @@ QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj) Locker locker(this); const QMetaObject *mo = obj->metaObject(); - QQmlPropertyCache *rv = propertyCache.value(mo); - if (!rv) rv = createCache(mo); - return rv; + return QQmlMetaType::propertyCache(mo); } /*! @@ -193,9 +184,7 @@ QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject) Q_ASSERT(metaObject); Locker locker(this); - QQmlPropertyCache *rv = propertyCache.value(metaObject); - if (!rv) rv = createCache(metaObject); - return rv; + return QQmlMetaType::propertyCache(metaObject); } diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 3e29222200..a2b6913943 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -110,6 +110,9 @@ struct QQmlMetaTypeData QString typeRegistrationNamespace; QStringList typeRegistrationFailures; + + QHash propertyCaches; + QQmlPropertyCache *propertyCache(const QMetaObject *metaObject); }; class QQmlTypeModulePrivate @@ -151,6 +154,9 @@ QQmlMetaTypeData::~QQmlMetaTypeData() for (TypeModules::const_iterator i = uriToModule.constBegin(), cend = uriToModule.constEnd(); i != cend; ++i) delete *i; + for (QHash::Iterator it = propertyCaches.begin(), end = propertyCaches.end(); + it != end; ++it) + (*it)->release(); } class QQmlTypePrivate @@ -1981,6 +1987,29 @@ QQmlType QQmlMetaType::qmlTypeFromIndex(int idx) return data->types.at(idx); } +QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject) +{ + if (QQmlPropertyCache *rv = propertyCaches.value(metaObject)) + return rv; + + if (!metaObject->superClass()) { + QQmlPropertyCache *rv = new QQmlPropertyCache(metaObject); + propertyCaches.insert(metaObject, rv); + return rv; + } + QQmlPropertyCache *super = propertyCache(metaObject->superClass()); + QQmlPropertyCache *rv = super->copyAndAppend(metaObject); + propertyCaches.insert(metaObject, rv); + return rv; +} + +QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject) +{ + QMutexLocker lock(metaTypeDataLock()); + QQmlMetaTypeData *data = metaTypeData(); + return data->propertyCache(metaObject); +} + /*! Returns the list of registered QML type names. */ diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index d17172a917..c577a9cc18 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -70,6 +70,7 @@ class QQmlTypeModule; class QHashedString; class QHashedStringRef; class QMutex; +class QQmlPropertyCache; namespace QV4 { struct String; } @@ -89,6 +90,8 @@ public: static QQmlType qmlType(const QUrl &url, bool includeNonFileImports = false); static QQmlType qmlTypeFromIndex(int); + static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject); + static QMetaProperty defaultProperty(const QMetaObject *); static QMetaProperty defaultProperty(QObject *); static QMetaMethod defaultMethod(const QMetaObject *); diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 6444d8800a..8fdc95af3a 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -511,6 +511,8 @@ private: QByteArray _checksum; }; +typedef QQmlRefPointer QQmlPropertyCachePtr; + // QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache. // This is necessary as we delay creation of QMetaObject for synthesized QObjects, but // we don't want to needlessly generate QQmlPropertyCaches every time we encounter a -- cgit v1.2.3