diff options
author | Ulf Hermann <[email protected]> | 2021-12-02 19:23:55 +0100 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2022-01-15 14:22:42 +0100 |
commit | a4eae734cda8a51a902b34c17454821d37b1997c (patch) | |
tree | 4b07651985e4fe47f670d645a7e571e71487e4df /src/qml | |
parent | f73e294472906077556e13ca10df185300c2450f (diff) |
Move composite types into QQmlMetaType
This way we can retrieve them without an engine. Since we construct a
new QMetaTypeInterface for each composite type we load, those
QMetaTypeInterfaces will still be unique even if the same type is used
in different engines. Therefore, we can store them all in the same
container.
This exposes the fact that we don't actually register composite types as
"custom" QMetaTypes in registerInternalCompositeType(), but we expect
them to be registered later on, in particular in
unregisterInternalCompositeType(). Retrieve the IDs once, in order to
have the types registered right away.
Change-Id: Ib8e875a5c950f105996877ea597a6de2b01aa1f5
Reviewed-by: Fabian Kosmale <[email protected]>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 60 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine_p.h | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 55 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatypedata.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatypedata_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmltypedata.cpp | 3 |
9 files changed, 74 insertions, 70 deletions
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index f1253aa6f8..5884640287 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -306,11 +306,9 @@ void ExecutableCompilationUnit::unlink() if (engine) nextCompilationUnit.remove(); - if (isRegisteredWithEngine) { + if (isRegistered) { Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0)); - if (qmlEngine) - qmlEngine->unregisterInternalCompositeType(this); - isRegisteredWithEngine = false; + QQmlMetaType::unregisterInternalCompositeType(this); } propertyCaches.clear(); @@ -404,7 +402,7 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi if (!types.isValid()) types = CompositeMetaTypeIds::fromCompositeName(rootPropertyCache()->className()); typeIds = types; - qmlEngine->registerInternalCompositeType(this); + QQmlMetaType::registerInternalCompositeType(this); } else { const QV4::CompiledData::Object *obj = objectAt(/*root object*/0); diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index e4670553cb..962517f6f4 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -181,7 +181,7 @@ public: CompositeMetaTypeIds typeIdsForComponent(int objectid = 0) const; CompositeMetaTypeIds typeIds; - bool isRegisteredWithEngine = false; + bool isRegistered = false; QHash<int, InlineComponentData> inlineComponentData; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 119eb50421..7c64988905 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -247,8 +247,6 @@ QQmlEnginePrivate::~QQmlEnginePrivate() QQmlMetaType::freeUnusedTypesAndCaches(); - for (auto iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) - iter.value()->isRegisteredWithEngine = false; #if QT_CONFIG(qml_debug) delete profiler; #endif @@ -1696,17 +1694,6 @@ QString QQmlEnginePrivate::offlineStorageDatabaseDirectory() const return q->offlineStoragePath() + QDir::separator() + QLatin1String("Databases") + QDir::separator(); } -static QQmlRefPointer<QQmlPropertyCache> propertyCacheForPotentialInlineComponentType( - int t, const QHash<int, QV4::ExecutableCompilationUnit *>::const_iterator &iter) { - if (t != (*iter)->typeIds.id.id()) { - // this is an inline component, and what we have in the iterator is currently the parent compilation unit - for (auto &&icDatum: (*iter)->inlineComponentData) - if (icDatum.typeIds.id.id() == t) - return (*iter)->propertyCaches.at(icDatum.objectIndex); - } - return (*iter)->rootPropertyCache(); -} - /*! * \internal * @@ -1714,7 +1701,7 @@ static QQmlRefPointer<QQmlPropertyCache> propertyCacheForPotentialInlineComponen */ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(QMetaType metaType) const { - if (auto composite = findPropertyCacheInCompositeTypes(metaType.id())) + if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType)) return QQmlMetaObject(composite); return QQmlMetaObject(QQmlMetaType::qmlType(metaType).baseMetaObject()); @@ -1727,7 +1714,7 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(QMetaType metaType) const */ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(QMetaType metaType) const { - if (auto composite = findPropertyCacheInCompositeTypes(metaType.id())) + if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType)) return QQmlMetaObject(composite); return QQmlMetaObject(QQmlMetaType::qmlType(metaType).metaObject()); @@ -1740,7 +1727,7 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(QMetaType metaType) const */ QQmlRefPointer<QQmlPropertyCache> QQmlEnginePrivate::propertyCacheForType(QMetaType metaType) { - if (auto composite = findPropertyCacheInCompositeTypes(metaType.id())) + if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType)) return composite; const QQmlType type = QQmlMetaType::qmlType(metaType); @@ -1758,7 +1745,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlEnginePrivate::propertyCacheForType(QMetaT */ QQmlRefPointer<QQmlPropertyCache> QQmlEnginePrivate::rawPropertyCacheForType(QMetaType metaType) { - if (auto composite = findPropertyCacheInCompositeTypes(metaType.id())) + if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType)) return composite; const QQmlType type = QQmlMetaType::qmlType(metaType); @@ -1776,7 +1763,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlEnginePrivate::rawPropertyCacheForType(QMe QQmlRefPointer<QQmlPropertyCache> QQmlEnginePrivate::rawPropertyCacheForType( QMetaType metaType, QTypeRevision version) { - if (auto composite = findPropertyCacheInCompositeTypes(metaType.id())) + if (auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType)) return composite; const QQmlType type = QQmlMetaType::qmlType(metaType); @@ -1792,43 +1779,6 @@ QQmlRefPointer<QQmlPropertyCache> QQmlEnginePrivate::rawPropertyCacheForType( return QQmlRefPointer<QQmlPropertyCache>(); } -QQmlRefPointer<QQmlPropertyCache> QQmlEnginePrivate::findPropertyCacheInCompositeTypes(int t) const -{ - QMutexLocker locker(&this->mutex); - auto iter = m_compositeTypes.constFind(t); - return (iter == m_compositeTypes.constEnd()) - ? QQmlRefPointer<QQmlPropertyCache>() - : propertyCacheForPotentialInlineComponentType(t, iter); -} - -void QQmlEnginePrivate::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) -{ - compilationUnit->isRegisteredWithEngine = true; - - QMutexLocker locker(&this->mutex); - // The QQmlCompiledData is not referenced here, but it is removed from this - // hash in the QQmlCompiledData destructor - m_compositeTypes.insert(compilationUnit->typeIds.id.id(), compilationUnit); - for (auto &&data: compilationUnit->inlineComponentData) - m_compositeTypes.insert(data.typeIds.id.id(), compilationUnit); -} - -void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) -{ - compilationUnit->isRegisteredWithEngine = false; - - QMutexLocker locker(&this->mutex); - m_compositeTypes.remove(compilationUnit->typeIds.id.id()); - for (auto&& icDatum: compilationUnit->inlineComponentData) - m_compositeTypes.remove(icDatum.typeIds.id.id()); -} - -QV4::ExecutableCompilationUnit *QQmlEnginePrivate::obtainExecutableCompilationUnit(int typeId) -{ - QMutexLocker locker(&this->mutex); - return m_compositeTypes.value(typeId, nullptr); -} - template<> QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type) { diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 58bc61dcf0..249ad74d92 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -218,9 +218,6 @@ public: QQmlRefPointer<QQmlPropertyCache> rawPropertyCacheForType(QMetaType metaType); QQmlRefPointer<QQmlPropertyCache> rawPropertyCacheForType( QMetaType metaType, QTypeRevision version); - void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); - void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); - QV4::ExecutableCompilationUnit *obtainExecutableCompilationUnit(int typeId); bool isTypeLoaded(const QUrl &url) const; bool isScriptLoaded(const QUrl &url) const; @@ -329,13 +326,9 @@ private: SingletonInstances singletonInstances; QHash<int, QQmlGadgetPtrWrapper *> cachedValueTypeInstances; - // These members must be protected by the engine's mutex as they are required by - // the threaded loader. Only access them through their respective accessor methods. - QHash<int, QV4::ExecutableCompilationUnit *> m_compositeTypes; static bool s_designerMode; void cleanupScarceResources(); - QQmlRefPointer<QQmlPropertyCache> findPropertyCacheInCompositeTypes(int t) const; }; /* diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index b5d1326ae0..44c005c2da 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -591,6 +591,10 @@ CompositeMetaTypeIds QQmlMetaType::registerInternalCompositeType(const QByteArra QMetaType ptr_type(new QQmlMetaTypeInterface(ptr, (QObject **)nullptr)); QMetaType lst_type(new QQmlListMetaTypeInterface(lst, (QQmlListProperty<QObject> *)nullptr, ptr_type.iface())); + // Retrieve the IDs once, so that the types are added to QMetaType's custom type registry. + ptr_type.id(); + lst_type.id(); + return {ptr_type, lst_type}; } @@ -1650,4 +1654,55 @@ QQmlValueType *QQmlMetaType::valueType(QMetaType type) return *data->metaTypeToValueType.insert(type.id(), nullptr); } +static QQmlRefPointer<QQmlPropertyCache> propertyCacheForPotentialInlineComponentType( + QMetaType t, const QHash<const QtPrivate::QMetaTypeInterface *, + QV4::ExecutableCompilationUnit *>::const_iterator &iter) { + if (t != (*iter)->typeIds.id) { + // this is an inline component, and what we have in the iterator is currently the parent compilation unit + for (auto &&icDatum: (*iter)->inlineComponentData) + if (icDatum.typeIds.id == t) + return (*iter)->propertyCaches.at(icDatum.objectIndex); + } + return (*iter)->rootPropertyCache(); +} + +QQmlRefPointer<QQmlPropertyCache> QQmlMetaType::findPropertyCacheInCompositeTypes(QMetaType t) +{ + const QQmlMetaTypeDataPtr data; + + auto iter = data->compositeTypes.constFind(t.iface()); + return (iter == data->compositeTypes.constEnd()) + ? QQmlRefPointer<QQmlPropertyCache>() + : propertyCacheForPotentialInlineComponentType(t, iter); +} + +void QQmlMetaType::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) +{ + compilationUnit->isRegistered = true; + + QQmlMetaTypeDataPtr data; + + // The QQmlCompiledData is not referenced here, but it is removed from this + // hash in the QQmlCompiledData destructor + data->compositeTypes.insert(compilationUnit->typeIds.id.iface(), compilationUnit); + for (auto &&inlineData: compilationUnit->inlineComponentData) + data->compositeTypes.insert(inlineData.typeIds.id.iface(), compilationUnit); +} + +void QQmlMetaType::unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) +{ + compilationUnit->isRegistered = false; + + QQmlMetaTypeDataPtr data; + data->compositeTypes.remove(compilationUnit->typeIds.id.iface()); + for (auto&& icDatum: compilationUnit->inlineComponentData) + data->compositeTypes.remove(icDatum.typeIds.id.iface()); +} + +QV4::ExecutableCompilationUnit *QQmlMetaType::obtainExecutableCompilationUnit(QMetaType type) +{ + const QQmlMetaTypeDataPtr data; + return data->compositeTypes.value(type.iface()); +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 2b00b75dc6..57e5ece326 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -254,6 +254,11 @@ public: static bool isValueType(QMetaType type); static QQmlValueType *valueType(QMetaType metaType); static const QMetaObject *metaObjectForValueType(QMetaType type); + + static QQmlRefPointer<QQmlPropertyCache> findPropertyCacheInCompositeTypes(QMetaType t); + static void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); + static void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); + static QV4::ExecutableCompilationUnit *obtainExecutableCompilationUnit(QMetaType type); }; Q_DECLARE_TYPEINFO(QQmlMetaType, Q_RELOCATABLE_TYPE); diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp index 6bac4ca8c5..5607b0f5cb 100644 --- a/src/qml/qml/qqmlmetatypedata.cpp +++ b/src/qml/qml/qqmlmetatypedata.cpp @@ -51,6 +51,9 @@ QQmlMetaTypeData::QQmlMetaTypeData() QQmlMetaTypeData::~QQmlMetaTypeData() { + for (auto iter = compositeTypes.cbegin(), end = compositeTypes.cend(); iter != end; ++iter) + iter.value()->isRegistered = false; + propertyCaches.clear(); // Do this before the attached properties disappear. types.clear(); diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h index d21a76b223..05681c0144 100644 --- a/src/qml/qml/qqmlmetatypedata_p.h +++ b/src/qml/qml/qqmlmetatypedata_p.h @@ -85,6 +85,7 @@ struct QQmlMetaTypeData MetaObjects metaObjectToType; QVector<QHash<QTypeRevision, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches; QHash<int, QQmlValueType *> metaTypeToValueType; + QHash<const QtPrivate::QMetaTypeInterface *, QV4::ExecutableCompilationUnit *> compositeTypes; struct VersionedUri { VersionedUri() = default; diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index 89bccc0c39..6698b6d78e 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -931,8 +931,7 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches( if (qmlType.isValid()) { // this is required for inline components in singletons auto type = qmlType.lookupInlineComponentById(qmlType.inlineComponentId()).typeId(); - auto exUnit = engine->obtainExecutableCompilationUnit( - type.isValid() ? type.id() : -1); + auto exUnit = QQmlMetaType::obtainExecutableCompilationUnit(type); if (exUnit) { ref->setCompilationUnit(exUnit); ref->setTypePropertyCache(engine->propertyCacheForType(type)); |