aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2021-12-02 19:23:55 +0100
committerUlf Hermann <[email protected]>2022-01-15 14:22:42 +0100
commita4eae734cda8a51a902b34c17454821d37b1997c (patch)
tree4b07651985e4fe47f670d645a7e571e71487e4df /src/qml
parentf73e294472906077556e13ca10df185300c2450f (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.cpp8
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h2
-rw-r--r--src/qml/qml/qqmlengine.cpp60
-rw-r--r--src/qml/qml/qqmlengine_p.h7
-rw-r--r--src/qml/qml/qqmlmetatype.cpp55
-rw-r--r--src/qml/qml/qqmlmetatype_p.h5
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp3
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h1
-rw-r--r--src/qml/qml/qqmltypedata.cpp3
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));